diff options
Diffstat (limited to 'doc/pintos_2.html')
| -rw-r--r-- | doc/pintos_2.html | 1734 |
1 files changed, 1734 insertions, 0 deletions
diff --git a/doc/pintos_2.html b/doc/pintos_2.html new file mode 100644 index 0000000..ae51974 --- /dev/null +++ b/doc/pintos_2.html | |||
| @@ -0,0 +1,1734 @@ | |||
| 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | ||
| 2 | "http://www.w3.org/TR/html40/loose.dtd"> | ||
| 3 | <HTML> | ||
| 4 | <!-- Created on March, 6 2012 by texi2html 1.66 --> | ||
| 5 | <!-- | ||
| 6 | Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author) | ||
| 7 | Karl Berry <karl@freefriends.org> | ||
| 8 | Olaf Bachmann <obachman@mathematik.uni-kl.de> | ||
| 9 | and many others. | ||
| 10 | Maintained by: Many creative people <dev@texi2html.cvshome.org> | ||
| 11 | Send bugs and suggestions to <users@texi2html.cvshome.org> | ||
| 12 | |||
| 13 | --> | ||
| 14 | <HEAD> | ||
| 15 | <TITLE>Pintos Projects: Project 0--Introducing Pintos</TITLE> | ||
| 16 | |||
| 17 | <META NAME="description" CONTENT="Pintos Projects: Project 0--Introducing Pintos"> | ||
| 18 | <META NAME="keywords" CONTENT="Pintos Projects: Project 0--Introducing Pintos"> | ||
| 19 | <META NAME="resource-type" CONTENT="document"> | ||
| 20 | <META NAME="distribution" CONTENT="global"> | ||
| 21 | <META NAME="Generator" CONTENT="texi2html 1.66"> | ||
| 22 | <LINK REL="stylesheet" HREF="pintos.css"> | ||
| 23 | </HEAD> | ||
| 24 | |||
| 25 | <BODY > | ||
| 26 | |||
| 27 | <A NAME="SEC15"></A> | ||
| 28 | <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> | ||
| 29 | <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_1.html#SEC1"> << </A>]</TD> | ||
| 30 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_3.html#SEC41"> >> </A>]</TD> | ||
| 31 | <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos.html#SEC_Top">Top</A>]</TD> | ||
| 32 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos.html#SEC_Contents">Contents</A>]</TD> | ||
| 33 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> | ||
| 34 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_abt.html#SEC_About"> ? </A>]</TD> | ||
| 35 | </TR></TABLE> | ||
| 36 | |||
| 37 | <HR SIZE=2> | ||
| 38 | <H1> 2. Project 0: Introducing Pintos </H1> | ||
| 39 | <!--docid::SEC15::--> | ||
| 40 | <P> | ||
| 41 | |||
| 42 | In this assignment, you will learn about the existing functionality | ||
| 43 | in Pintos, and add two small features to the system: a more efficient | ||
| 44 | implementation of <Q><SAMP>sleep</SAMP></Q>, and the ability to pass command line | ||
| 45 | arguments to user programs. | ||
| 46 | </P> | ||
| 47 | <P> | ||
| 48 | |||
| 49 | You will be working in the <Q><TT>threads</TT></Q> directory for the first part | ||
| 50 | of this assignment (with some work in the <Q><TT>devices</TT></Q> directory on | ||
| 51 | the side), and modify the file <Q><TT>userprog/process.c</TT></Q> in the second part. | ||
| 52 | </P> | ||
| 53 | <P> | ||
| 54 | |||
| 55 | The tests for Project 0 are executed by changing the working directory | ||
| 56 | to <Q><TT>intro</TT></Q> and running <Q><SAMP>make</SAMP></Q> followed by <Q><SAMP>make check</SAMP></Q>. | ||
| 57 | </P> | ||
| 58 | <P> | ||
| 59 | |||
| 60 | Before you read the description of this project, you should read all of | ||
| 61 | the following sections: <A HREF="pintos_1.html#SEC1">1. Introduction</A>, <A HREF="pintos_6.html#SEC89">B. Coding Standards</A>, | ||
| 62 | <A HREF="pintos_8.html#SEC96">D. Debugging Tools</A>, and <A HREF="pintos_9.html#SEC109">E. Development Tools</A>. You should at least | ||
| 63 | skim the material from <A HREF="pintos_5.html#SEC49">A.1 Loading</A> through <A HREF="pintos_5.html#SEC69">A.5 Memory Allocation</A>, especially <A HREF="pintos_5.html#SEC58">A.3 Synchronization</A>. | ||
| 64 | </P> | ||
| 65 | <P> | ||
| 66 | |||
| 67 | <A NAME="Understanding Threads"></A> | ||
| 68 | <HR SIZE="6"> | ||
| 69 | <A NAME="SEC16"></A> | ||
| 70 | <H2> 2.1 Understanding Threads </H2> | ||
| 71 | <!--docid::SEC16::--> | ||
| 72 | <P> | ||
| 73 | |||
| 74 | The first step is to read and understand the code for the initial thread | ||
| 75 | system. | ||
| 76 | Pintos already implements thread creation and thread completion, | ||
| 77 | a simple scheduler to switch between threads, and synchronization | ||
| 78 | primitives (semaphores, locks, condition variables, and optimization | ||
| 79 | barriers). | ||
| 80 | </P> | ||
| 81 | <P> | ||
| 82 | |||
| 83 | Some of this code might seem slightly mysterious. If | ||
| 84 | you haven't already compiled and run the base system, as described in | ||
| 85 | the introduction (see section <A HREF="pintos_1.html#SEC1">1. Introduction</A>), you should do so now. You | ||
| 86 | can read through parts of the source code to see what's going | ||
| 87 | on. If you like, you can add calls to <CODE>printf()</CODE> almost | ||
| 88 | anywhere, then recompile and run to see what happens and in what | ||
| 89 | order. You can also run the kernel in a debugger and set breakpoints | ||
| 90 | at interesting spots, single-step through code and examine data, and | ||
| 91 | so on. | ||
| 92 | </P> | ||
| 93 | <P> | ||
| 94 | |||
| 95 | When a thread is created, you are creating a new context to be | ||
| 96 | scheduled. You provide a function to be run in this context as an | ||
| 97 | argument to <CODE>thread_create()</CODE>. The first time the thread is | ||
| 98 | scheduled and runs, it starts from the beginning of that function | ||
| 99 | and executes in that context. When the function returns, the thread | ||
| 100 | terminates. Each thread, therefore, acts like a mini-program running | ||
| 101 | inside Pintos, with the function passed to <CODE>thread_create()</CODE> | ||
| 102 | acting like <CODE>main()</CODE>. | ||
| 103 | </P> | ||
| 104 | <P> | ||
| 105 | |||
| 106 | At any given time, exactly one thread runs and the rest, if any, | ||
| 107 | become inactive. The scheduler decides which thread to | ||
| 108 | run next. (If no thread is ready to run | ||
| 109 | at any given time, then the special "idle" thread, implemented in | ||
| 110 | <CODE>idle()</CODE>, runs.) | ||
| 111 | Synchronization primitives can force context switches when one | ||
| 112 | thread needs to wait for another thread to do something. | ||
| 113 | </P> | ||
| 114 | <P> | ||
| 115 | |||
| 116 | The mechanics of a context switch are | ||
| 117 | in <Q><TT>threads/switch.S</TT></Q>, which is 80<VAR>x</VAR>86 | ||
| 118 | assembly code. (You don't have to understand it.) It saves the | ||
| 119 | state of the currently running thread and restores the state of the | ||
| 120 | thread we're switching to. | ||
| 121 | </P> | ||
| 122 | <P> | ||
| 123 | |||
| 124 | Using the GDB debugger, slowly trace through a context | ||
| 125 | switch to see what happens (see section <A HREF="pintos_8.html#SEC102">D.5 GDB</A>). You can set a | ||
| 126 | breakpoint on <CODE>schedule()</CODE> to start out, and then | ||
| 127 | single-step from there.<A NAME="DOCF1" HREF="pintos_fot.html#FOOT1">(1)</A> Be sure | ||
| 128 | to keep track of each thread's address | ||
| 129 | and state, and what procedures are on the call stack for each thread. | ||
| 130 | You will notice that when one thread calls <CODE>switch_threads()</CODE>, | ||
| 131 | another thread starts running, and the first thing the new thread does | ||
| 132 | is to return from <CODE>switch_threads()</CODE>. You will understand the thread | ||
| 133 | system once you understand why and how the <CODE>switch_threads()</CODE> that | ||
| 134 | gets called is different from the <CODE>switch_threads()</CODE> that returns. | ||
| 135 | See section <A HREF="pintos_5.html#SEC57">A.2.3 Thread Switching</A>, for more information. | ||
| 136 | </P> | ||
| 137 | <P> | ||
| 138 | |||
| 139 | <STRONG>Warning</STRONG>: In Pintos, each thread is assigned a small, | ||
| 140 | fixed-size execution stack just under 4 kB in size. The kernel | ||
| 141 | tries to detect stack overflow, but it cannot do so perfectly. You | ||
| 142 | may cause bizarre problems, such as mysterious kernel panics, if you | ||
| 143 | declare large data structures as non-static local variables, | ||
| 144 | e.g. <Q><SAMP>int buf[1000];</SAMP></Q>. Alternatives to stack allocation include | ||
| 145 | the page allocator and the block allocator (see section <A HREF="pintos_5.html#SEC69">A.5 Memory Allocation</A>). | ||
| 146 | </P> | ||
| 147 | <P> | ||
| 148 | |||
| 149 | <A NAME="Project 1 Source Files"></A> | ||
| 150 | <HR SIZE="6"> | ||
| 151 | <A NAME="SEC17"></A> | ||
| 152 | <H3> 2.1.1 Source Files </H3> | ||
| 153 | <!--docid::SEC17::--> | ||
| 154 | <P> | ||
| 155 | |||
| 156 | Here is a brief overview of the files in the <Q><TT>threads</TT></Q> | ||
| 157 | directory. You will not need to modify most of this code, but the | ||
| 158 | hope is that presenting this overview will give you a start on what | ||
| 159 | code to look at. | ||
| 160 | </P> | ||
| 161 | <P> | ||
| 162 | |||
| 163 | </P> | ||
| 164 | <DL COMPACT> | ||
| 165 | <DT><Q><TT>loader.S</TT></Q> | ||
| 166 | <DD><DT><Q><TT>loader.h</TT></Q> | ||
| 167 | <DD>The kernel loader. Assembles to 512 bytes of code and data that the | ||
| 168 | PC BIOS loads into memory and which in turn finds the kernel on disk, | ||
| 169 | loads it into memory, and jumps to <CODE>start()</CODE> in <Q><TT>start.S</TT></Q>. | ||
| 170 | See section <A HREF="pintos_5.html#SEC50">A.1.1 The Loader</A>, for details. You should not need to look at | ||
| 171 | this code or modify it. | ||
| 172 | <P> | ||
| 173 | |||
| 174 | </P> | ||
| 175 | <DT><Q><TT>start.S</TT></Q> | ||
| 176 | <DD>Does basic setup needed for memory protection and 32-bit | ||
| 177 | operation on 80<VAR>x</VAR>86 CPUs. Unlike the loader, this code is | ||
| 178 | actually part of the kernel. See section <A HREF="pintos_5.html#SEC51">A.1.2 Low-Level Kernel Initialization</A>, | ||
| 179 | for details. | ||
| 180 | <P> | ||
| 181 | |||
| 182 | </P> | ||
| 183 | <DT><Q><TT>kernel.lds.S</TT></Q> | ||
| 184 | <DD>The linker script used to link the kernel. Sets the load address of | ||
| 185 | the kernel and arranges for <Q><TT>start.S</TT></Q> to be near the beginning | ||
| 186 | of the kernel image. See section <A HREF="pintos_5.html#SEC50">A.1.1 The Loader</A>, for details. Again, you | ||
| 187 | should not need to look at this code | ||
| 188 | or modify it, but it's here in case you're curious. | ||
| 189 | <P> | ||
| 190 | |||
| 191 | </P> | ||
| 192 | <DT><Q><TT>init.c</TT></Q> | ||
| 193 | <DD><DT><Q><TT>init.h</TT></Q> | ||
| 194 | <DD>Kernel initialization, including <CODE>main()</CODE>, the kernel's "main | ||
| 195 | program." You should look over <CODE>main()</CODE> at least to see what | ||
| 196 | gets initialized. You might want to add your own initialization code | ||
| 197 | here. See section <A HREF="pintos_5.html#SEC52">A.1.3 High-Level Kernel Initialization</A>, for details. | ||
| 198 | <P> | ||
| 199 | |||
| 200 | </P> | ||
| 201 | <DT><Q><TT>thread.c</TT></Q> | ||
| 202 | <DD><DT><Q><TT>thread.h</TT></Q> | ||
| 203 | <DD>Basic thread support. Much of your work will take place in these files. | ||
| 204 | <Q><TT>thread.h</TT></Q> defines <CODE>struct thread</CODE>, which you are likely to modify | ||
| 205 | in all three projects. See <A HREF="pintos_5.html#SEC55">A.2.1 <CODE>struct thread</CODE></A> and <A HREF="pintos_5.html#SEC54">A.2 Threads</A> for | ||
| 206 | more information. | ||
| 207 | <P> | ||
| 208 | |||
| 209 | </P> | ||
| 210 | <DT><Q><TT>switch.S</TT></Q> | ||
| 211 | <DD><DT><Q><TT>switch.h</TT></Q> | ||
| 212 | <DD>Assembly language routine for switching threads. Already discussed | ||
| 213 | above. See section <A HREF="pintos_5.html#SEC56">A.2.2 Thread Functions</A>, for more information. | ||
| 214 | <P> | ||
| 215 | |||
| 216 | </P> | ||
| 217 | <DT><Q><TT>palloc.c</TT></Q> | ||
| 218 | <DD><DT><Q><TT>palloc.h</TT></Q> | ||
| 219 | <DD>Page allocator, which hands out system memory in multiples of 4 kB | ||
| 220 | pages. See section <A HREF="pintos_5.html#SEC70">A.5.1 Page Allocator</A>, for more information. | ||
| 221 | <P> | ||
| 222 | |||
| 223 | </P> | ||
| 224 | <DT><Q><TT>malloc.c</TT></Q> | ||
| 225 | <DD><DT><Q><TT>malloc.h</TT></Q> | ||
| 226 | <DD>A simple implementation of <CODE>malloc()</CODE> and <CODE>free()</CODE> for | ||
| 227 | the kernel. See section <A HREF="pintos_5.html#SEC71">A.5.2 Block Allocator</A>, for more information. | ||
| 228 | <P> | ||
| 229 | |||
| 230 | </P> | ||
| 231 | <DT><Q><TT>interrupt.c</TT></Q> | ||
| 232 | <DD><DT><Q><TT>interrupt.h</TT></Q> | ||
| 233 | <DD>Basic interrupt handling and functions for turning interrupts on and | ||
| 234 | off. See section <A HREF="pintos_5.html#SEC65">A.4 Interrupt Handling</A>, for more information. | ||
| 235 | <P> | ||
| 236 | |||
| 237 | </P> | ||
| 238 | <DT><Q><TT>intr-stubs.S</TT></Q> | ||
| 239 | <DD><DT><Q><TT>intr-stubs.h</TT></Q> | ||
| 240 | <DD>Assembly code for low-level interrupt handling. See section <A HREF="pintos_5.html#SEC66">A.4.1 Interrupt Infrastructure</A>, for more information. | ||
| 241 | <P> | ||
| 242 | |||
| 243 | </P> | ||
| 244 | <DT><Q><TT>synch.c</TT></Q> | ||
| 245 | <DD><DT><Q><TT>synch.h</TT></Q> | ||
| 246 | <DD>Basic synchronization primitives: semaphores, locks, condition | ||
| 247 | variables, and optimization barriers. You will need to use these for | ||
| 248 | synchronization in all | ||
| 249 | four projects. See section <A HREF="pintos_5.html#SEC58">A.3 Synchronization</A>, for more information. | ||
| 250 | <P> | ||
| 251 | |||
| 252 | </P> | ||
| 253 | <DT><Q><TT>io.h</TT></Q> | ||
| 254 | <DD>Functions for I/O port access. This is mostly used by source code in | ||
| 255 | the <Q><TT>devices</TT></Q> directory that you won't have to touch. | ||
| 256 | <P> | ||
| 257 | |||
| 258 | </P> | ||
| 259 | <DT><Q><TT>vaddr.h</TT></Q> | ||
| 260 | <DD><DT><Q><TT>pte.h</TT></Q> | ||
| 261 | <DD>Functions and macros for working with virtual addresses and page table | ||
| 262 | entries. These will be more important to you in project 2. For now, | ||
| 263 | you can ignore them. | ||
| 264 | <P> | ||
| 265 | |||
| 266 | </P> | ||
| 267 | <DT><Q><TT>flags.h</TT></Q> | ||
| 268 | <DD>Macros that define a few bits in the 80<VAR>x</VAR>86 "flags" register. | ||
| 269 | Probably of no interest. See [ <A HREF="pintos_10.html#IA32-v1">IA32-v1</A>], section 3.4.3, "EFLAGS | ||
| 270 | Register," for more information. | ||
| 271 | </DL> | ||
| 272 | <P> | ||
| 273 | |||
| 274 | <A NAME="devices code"></A> | ||
| 275 | <HR SIZE="6"> | ||
| 276 | <A NAME="SEC18"></A> | ||
| 277 | <H4> 2.1.1.1 <Q><TT>devices</TT></Q> code </H4> | ||
| 278 | <!--docid::SEC18::--> | ||
| 279 | <P> | ||
| 280 | |||
| 281 | The basic threaded kernel also includes these files in the | ||
| 282 | <Q><TT>devices</TT></Q> directory: | ||
| 283 | </P> | ||
| 284 | <P> | ||
| 285 | |||
| 286 | </P> | ||
| 287 | <DL COMPACT> | ||
| 288 | <DT><Q><TT>timer.c</TT></Q> | ||
| 289 | <DD><DT><Q><TT>timer.h</TT></Q> | ||
| 290 | <DD>System timer that ticks, by default, 100 times per second. You will | ||
| 291 | modify this code in this project. | ||
| 292 | <P> | ||
| 293 | |||
| 294 | </P> | ||
| 295 | <DT><Q><TT>vga.c</TT></Q> | ||
| 296 | <DD><DT><Q><TT>vga.h</TT></Q> | ||
| 297 | <DD>VGA display driver. Responsible for writing text to the screen. | ||
| 298 | You should have no need to look at this code. <CODE>printf()</CODE> | ||
| 299 | calls into the VGA display driver for you, so there's little reason to | ||
| 300 | call this code yourself. | ||
| 301 | <P> | ||
| 302 | |||
| 303 | </P> | ||
| 304 | <DT><Q><TT>serial.c</TT></Q> | ||
| 305 | <DD><DT><Q><TT>serial.h</TT></Q> | ||
| 306 | <DD>Serial port driver. Again, <CODE>printf()</CODE> calls this code for you, | ||
| 307 | so you don't need to do so yourself. | ||
| 308 | It handles serial input by passing it to the input layer (see below). | ||
| 309 | <P> | ||
| 310 | |||
| 311 | </P> | ||
| 312 | <DT><Q><TT>block.c</TT></Q> | ||
| 313 | <DD><DT><Q><TT>block.h</TT></Q> | ||
| 314 | <DD>An abstraction layer for <EM>block devices</EM>, that is, random-access, | ||
| 315 | disk-like devices that are organized as arrays of fixed-size blocks. | ||
| 316 | Out of the box, Pintos supports two types of block devices: IDE disks | ||
| 317 | and partitions. | ||
| 318 | <P> | ||
| 319 | |||
| 320 | </P> | ||
| 321 | <DT><Q><TT>ide.c</TT></Q> | ||
| 322 | <DD><DT><Q><TT>ide.h</TT></Q> | ||
| 323 | <DD>Supports reading and writing sectors on up to 4 IDE disks. | ||
| 324 | <P> | ||
| 325 | |||
| 326 | </P> | ||
| 327 | <DT><Q><TT>partition.c</TT></Q> | ||
| 328 | <DD><DT><Q><TT>partition.h</TT></Q> | ||
| 329 | <DD>Understands the structure of partitions on disks, allowing a single | ||
| 330 | disk to be carved up into multiple regions (partitions) for | ||
| 331 | independent use. | ||
| 332 | <P> | ||
| 333 | |||
| 334 | </P> | ||
| 335 | <DT><Q><TT>kbd.c</TT></Q> | ||
| 336 | <DD><DT><Q><TT>kbd.h</TT></Q> | ||
| 337 | <DD>Keyboard driver. Handles keystrokes passing them to the input layer | ||
| 338 | (see below). | ||
| 339 | <P> | ||
| 340 | |||
| 341 | </P> | ||
| 342 | <DT><Q><TT>input.c</TT></Q> | ||
| 343 | <DD><DT><Q><TT>input.h</TT></Q> | ||
| 344 | <DD>Input layer. Queues input characters passed along by the keyboard or | ||
| 345 | serial drivers. | ||
| 346 | <P> | ||
| 347 | |||
| 348 | </P> | ||
| 349 | <DT><Q><TT>intq.c</TT></Q> | ||
| 350 | <DD><DT><Q><TT>intq.h</TT></Q> | ||
| 351 | <DD>Interrupt queue, for managing a circular queue that both kernel | ||
| 352 | threads and interrupt handlers want to access. Used by the keyboard | ||
| 353 | and serial drivers. | ||
| 354 | <P> | ||
| 355 | |||
| 356 | </P> | ||
| 357 | <DT><Q><TT>rtc.c</TT></Q> | ||
| 358 | <DD><DT><Q><TT>rtc.h</TT></Q> | ||
| 359 | <DD>Real-time clock driver, to enable the kernel to determine the current | ||
| 360 | date and time. By default, this is only used by <Q><TT>thread/init.c</TT></Q> | ||
| 361 | to choose an initial seed for the random number generator. | ||
| 362 | <P> | ||
| 363 | |||
| 364 | </P> | ||
| 365 | <DT><Q><TT>speaker.c</TT></Q> | ||
| 366 | <DD><DT><Q><TT>speaker.h</TT></Q> | ||
| 367 | <DD>Driver that can produce tones on the PC speaker. | ||
| 368 | <P> | ||
| 369 | |||
| 370 | </P> | ||
| 371 | <DT><Q><TT>pit.c</TT></Q> | ||
| 372 | <DD><DT><Q><TT>pit.h</TT></Q> | ||
| 373 | <DD>Code to configure the 8254 Programmable Interrupt Timer. This code is | ||
| 374 | used by both <Q><TT>devices/timer.c</TT></Q> and <Q><TT>devices/speaker.c</TT></Q> | ||
| 375 | because each device uses one of the PIT's output channel. | ||
| 376 | </DL> | ||
| 377 | <P> | ||
| 378 | |||
| 379 | <A NAME="lib files"></A> | ||
| 380 | <HR SIZE="6"> | ||
| 381 | <A NAME="SEC19"></A> | ||
| 382 | <H4> 2.1.1.2 <Q><TT>lib</TT></Q> files </H4> | ||
| 383 | <!--docid::SEC19::--> | ||
| 384 | <P> | ||
| 385 | |||
| 386 | Finally, <Q><TT>lib</TT></Q> and <Q><TT>lib/kernel</TT></Q> contain useful library | ||
| 387 | routines. (<Q><TT>lib/user</TT></Q> will be used by user programs, starting in | ||
| 388 | project 2, but it is not part of the kernel.) Here's a few more | ||
| 389 | details: | ||
| 390 | </P> | ||
| 391 | <P> | ||
| 392 | |||
| 393 | </P> | ||
| 394 | <DL COMPACT> | ||
| 395 | <DT><Q><TT>ctype.h</TT></Q> | ||
| 396 | <DD><DT><Q><TT>inttypes.h</TT></Q> | ||
| 397 | <DD><DT><Q><TT>limits.h</TT></Q> | ||
| 398 | <DD><DT><Q><TT>stdarg.h</TT></Q> | ||
| 399 | <DD><DT><Q><TT>stdbool.h</TT></Q> | ||
| 400 | <DD><DT><Q><TT>stddef.h</TT></Q> | ||
| 401 | <DD><DT><Q><TT>stdint.h</TT></Q> | ||
| 402 | <DD><DT><Q><TT>stdio.c</TT></Q> | ||
| 403 | <DD><DT><Q><TT>stdio.h</TT></Q> | ||
| 404 | <DD><DT><Q><TT>stdlib.c</TT></Q> | ||
| 405 | <DD><DT><Q><TT>stdlib.h</TT></Q> | ||
| 406 | <DD><DT><Q><TT>string.c</TT></Q> | ||
| 407 | <DD><DT><Q><TT>string.h</TT></Q> | ||
| 408 | <DD>A subset of the standard C library. See section <A HREF="pintos_6.html#SEC91">B.2 C99</A>, for | ||
| 409 | information | ||
| 410 | on a few recently introduced pieces of the C library that you might | ||
| 411 | not have encountered before. See section <A HREF="pintos_6.html#SEC92">B.3 Unsafe String Functions</A>, for | ||
| 412 | information on what's been intentionally left out for safety. | ||
| 413 | <P> | ||
| 414 | |||
| 415 | </P> | ||
| 416 | <DT><Q><TT>debug.c</TT></Q> | ||
| 417 | <DD><DT><Q><TT>debug.h</TT></Q> | ||
| 418 | <DD>Functions and macros to aid debugging. See section <A HREF="pintos_8.html#SEC96">D. Debugging Tools</A>, for | ||
| 419 | more information. | ||
| 420 | <P> | ||
| 421 | |||
| 422 | </P> | ||
| 423 | <DT><Q><TT>random.c</TT></Q> | ||
| 424 | <DD><DT><Q><TT>random.h</TT></Q> | ||
| 425 | <DD>Pseudo-random number generator. The actual sequence of random values | ||
| 426 | will not vary from one Pintos run to another, unless you do one of | ||
| 427 | three things: specify a new random seed value on the <Q><SAMP>-rs</SAMP></Q> | ||
| 428 | kernel command-line option on each run, or use a simulator other than | ||
| 429 | Bochs, or specify the <Q><SAMP>-r</SAMP></Q> option to <CODE>pintos</CODE>. | ||
| 430 | <P> | ||
| 431 | |||
| 432 | </P> | ||
| 433 | <DT><Q><TT>round.h</TT></Q> | ||
| 434 | <DD>Macros for rounding. | ||
| 435 | <P> | ||
| 436 | |||
| 437 | </P> | ||
| 438 | <DT><Q><TT>syscall-nr.h</TT></Q> | ||
| 439 | <DD>System call numbers. Not used until project 2. | ||
| 440 | <P> | ||
| 441 | |||
| 442 | </P> | ||
| 443 | <DT><Q><TT>kernel/list.c</TT></Q> | ||
| 444 | <DD><DT><Q><TT>kernel/list.h</TT></Q> | ||
| 445 | <DD>Doubly linked list implementation. Used all over the Pintos code, and | ||
| 446 | you'll probably want to use it a few places yourself. | ||
| 447 | <P> | ||
| 448 | |||
| 449 | </P> | ||
| 450 | <DT><Q><TT>kernel/bitmap.c</TT></Q> | ||
| 451 | <DD><DT><Q><TT>kernel/bitmap.h</TT></Q> | ||
| 452 | <DD>Bitmap implementation. You can use this in your code if you like, but | ||
| 453 | you probably won't have any need for it in project 0 and project 1. | ||
| 454 | <P> | ||
| 455 | |||
| 456 | </P> | ||
| 457 | <DT><Q><TT>kernel/hash.c</TT></Q> | ||
| 458 | <DD><DT><Q><TT>kernel/hash.h</TT></Q> | ||
| 459 | <DD>Hash table implementation. | ||
| 460 | <P> | ||
| 461 | |||
| 462 | </P> | ||
| 463 | <DT><Q><TT>kernel/console.c</TT></Q> | ||
| 464 | <DD><DT><Q><TT>kernel/console.h</TT></Q> | ||
| 465 | <DD><DT><Q><TT>kernel/stdio.h</TT></Q> | ||
| 466 | <DD>Implements <CODE>printf()</CODE> and a few other functions. | ||
| 467 | </DL> | ||
| 468 | <P> | ||
| 469 | |||
| 470 | <A NAME="Project 1 Synchronization"></A> | ||
| 471 | <HR SIZE="6"> | ||
| 472 | <A NAME="SEC20"></A> | ||
| 473 | <H3> 2.1.2 Synchronization </H3> | ||
| 474 | <!--docid::SEC20::--> | ||
| 475 | <P> | ||
| 476 | |||
| 477 | Proper synchronization is an important part of the solutions to these | ||
| 478 | problems. Any synchronization problem can be easily solved by turning | ||
| 479 | interrupts off: while interrupts are off, there is no concurrency, so | ||
| 480 | there's no possibility for race conditions. Therefore, it's tempting to | ||
| 481 | solve all synchronization problems this way, but <STRONG>don't</STRONG>. | ||
| 482 | Instead, use semaphores, locks, and condition variables to solve the | ||
| 483 | bulk of your synchronization problems. Read the tour section on | ||
| 484 | synchronization (see section <A HREF="pintos_5.html#SEC58">A.3 Synchronization</A>) or the comments in | ||
| 485 | <Q><TT>threads/synch.c</TT></Q> if you're unsure what synchronization primitives | ||
| 486 | may be used in what situations. | ||
| 487 | </P> | ||
| 488 | <P> | ||
| 489 | |||
| 490 | In the Pintos projects, the only class of problem best solved by | ||
| 491 | disabling interrupts is coordinating data shared between a kernel thread | ||
| 492 | and an interrupt handler. Because interrupt handlers can't sleep, they | ||
| 493 | can't acquire locks. This means that data shared between kernel threads | ||
| 494 | and an interrupt handler must be protected within a kernel thread by | ||
| 495 | turning off interrupts. | ||
| 496 | </P> | ||
| 497 | <P> | ||
| 498 | |||
| 499 | This project only requires accessing a little bit of thread state from | ||
| 500 | interrupt handlers. For the alarm clock, the timer interrupt needs to | ||
| 501 | wake up sleeping threads. In the advanced scheduler, the timer | ||
| 502 | interrupt needs to access a few global and per-thread variables. When | ||
| 503 | you access these variables from kernel threads, you will need to disable | ||
| 504 | interrupts to prevent the timer interrupt from interfering. | ||
| 505 | </P> | ||
| 506 | <P> | ||
| 507 | |||
| 508 | When you do turn off interrupts, take care to do so for the least amount | ||
| 509 | of code possible, or you can end up losing important things such as | ||
| 510 | timer ticks or input events. Turning off interrupts also increases the | ||
| 511 | interrupt handling latency, which can make a machine feel sluggish if | ||
| 512 | taken too far. | ||
| 513 | </P> | ||
| 514 | <P> | ||
| 515 | |||
| 516 | The synchronization primitives themselves in <Q><TT>synch.c</TT></Q> are | ||
| 517 | implemented by disabling interrupts. You may need to increase the | ||
| 518 | amount of code that runs with interrupts disabled here, but you should | ||
| 519 | still try to keep it to a minimum. | ||
| 520 | </P> | ||
| 521 | <P> | ||
| 522 | |||
| 523 | Disabling interrupts can be useful for debugging, if you want to make | ||
| 524 | sure that a section of code is not interrupted. You should remove | ||
| 525 | debugging code before turning in your project. (Don't just comment it | ||
| 526 | out, because that can make the code difficult to read.) | ||
| 527 | </P> | ||
| 528 | <P> | ||
| 529 | |||
| 530 | There should be no busy waiting in your submission. A tight loop that | ||
| 531 | calls <CODE>thread_yield()</CODE> is one form of busy waiting. | ||
| 532 | </P> | ||
| 533 | <P> | ||
| 534 | |||
| 535 | <A NAME="Development Suggestions"></A> | ||
| 536 | <HR SIZE="6"> | ||
| 537 | <A NAME="SEC21"></A> | ||
| 538 | <H3> 2.1.3 Development Suggestions </H3> | ||
| 539 | <!--docid::SEC21::--> | ||
| 540 | <P> | ||
| 541 | |||
| 542 | In the past, many groups divided the assignment into pieces, then each | ||
| 543 | group member worked on his or her piece until just before the | ||
| 544 | deadline, at which time the group reconvened to combine their code and | ||
| 545 | submit. <STRONG>This is a bad idea. We do not recommend this | ||
| 546 | approach.</STRONG> Groups that do this often find that two changes conflict | ||
| 547 | with each other, requiring lots of last-minute debugging. Some groups | ||
| 548 | who have done this have turned in code that did not even compile or | ||
| 549 | boot, much less pass any tests. | ||
| 550 | </P> | ||
| 551 | <P> | ||
| 552 | |||
| 553 | Instead, we recommend integrating your team's changes early and often, | ||
| 554 | using the source code control system git. | ||
| 555 | This is less likely to produce surprises, because everyone can see | ||
| 556 | everyone else's code as it is written, instead of just when it is | ||
| 557 | finished. These systems also make it possible to review changes and, | ||
| 558 | when a change introduces a bug, drop back to working versions of code. | ||
| 559 | </P> | ||
| 560 | <P> | ||
| 561 | |||
| 562 | You should expect to run into bugs that you simply don't understand | ||
| 563 | while working on this and subsequent projects. When you do, | ||
| 564 | reread the appendix on debugging tools, which is filled with | ||
| 565 | useful debugging tips that should help you to get back up to speed | ||
| 566 | (see section <A HREF="pintos_8.html#SEC96">D. Debugging Tools</A>). Be sure to read the section on backtraces | ||
| 567 | (see section <A HREF="pintos_8.html#SEC100">D.4 Backtraces</A>), which will help you to get the most out of every | ||
| 568 | kernel panic or assertion failure. | ||
| 569 | </P> | ||
| 570 | <P> | ||
| 571 | |||
| 572 | <A NAME="Understanding User Programs"></A> | ||
| 573 | <HR SIZE="6"> | ||
| 574 | <A NAME="SEC22"></A> | ||
| 575 | <H2> 2.2 Understanding User Programs </H2> | ||
| 576 | <!--docid::SEC22::--> | ||
| 577 | <P> | ||
| 578 | |||
| 579 | The tests for both the alarm clock assignment in Project 0, and the | ||
| 580 | priority scheduler in Project 1, run as part of the operating system | ||
| 581 | kernel, with full access to privileged parts of the system. | ||
| 582 | Once we start running user programs on top of the operating system, this | ||
| 583 | is no longer true. | ||
| 584 | </P> | ||
| 585 | <P> | ||
| 586 | |||
| 587 | We allow more than one process to run at a time. Each process has one | ||
| 588 | thread (multithreaded processes are not supported). User programs are | ||
| 589 | written under the illusion that they have the entire machine. This | ||
| 590 | means that when you load and run multiple processes at a time, you must | ||
| 591 | manage memory, scheduling, and other state correctly to maintain this | ||
| 592 | illusion. | ||
| 593 | </P> | ||
| 594 | <P> | ||
| 595 | |||
| 596 | In Project 2, we will test your operating system by running | ||
| 597 | user programs. This gives you much greater freedom. You must make sure | ||
| 598 | that the user program interface meets the specifications described here, | ||
| 599 | but given that constraint you are free to restructure or rewrite kernel | ||
| 600 | code however you wish. | ||
| 601 | </P> | ||
| 602 | <P> | ||
| 603 | |||
| 604 | <A NAME="User Program Source Files"></A> | ||
| 605 | <HR SIZE="6"> | ||
| 606 | <A NAME="SEC23"></A> | ||
| 607 | <H3> 2.2.1 Source Files </H3> | ||
| 608 | <!--docid::SEC23::--> | ||
| 609 | <P> | ||
| 610 | |||
| 611 | </P> | ||
| 612 | <DL COMPACT> | ||
| 613 | <DT><Q><TT>process.c</TT></Q> | ||
| 614 | <DD><DT><Q><TT>process.h</TT></Q> | ||
| 615 | <DD>Loads ELF binaries and starts processes. | ||
| 616 | <P> | ||
| 617 | |||
| 618 | </P> | ||
| 619 | <DT><Q><TT>pagedir.c</TT></Q> | ||
| 620 | <DD><DT><Q><TT>pagedir.h</TT></Q> | ||
| 621 | <DD>A simple manager for 80<VAR>x</VAR>86 hardware page tables. | ||
| 622 | Although you probably won't want to modify this code for this project, | ||
| 623 | you may want to call some of its functions. | ||
| 624 | See <A HREF="pintos_4.html#Page Tables">Page Tables</A>, for more information. | ||
| 625 | <P> | ||
| 626 | |||
| 627 | </P> | ||
| 628 | <DT><Q><TT>syscall.c</TT></Q> | ||
| 629 | <DD><DT><Q><TT>syscall.h</TT></Q> | ||
| 630 | <DD>Whenever a user process wants to access some kernel functionality, it | ||
| 631 | invokes a system call. | ||
| 632 | <P> | ||
| 633 | |||
| 634 | </P> | ||
| 635 | <DT><Q><TT>exception.c</TT></Q> | ||
| 636 | <DD><DT><Q><TT>exception.h</TT></Q> | ||
| 637 | <DD>When a user process performs a privileged or prohibited operation, it | ||
| 638 | traps into the kernel as an "exception" or "fault."<A NAME="DOCF2" HREF="pintos_fot.html#FOOT2">(2)</A> These files handle | ||
| 639 | exceptions. In project 2, you will need to modify the page fault | ||
| 640 | handler to support lazy page loading and stack growth. | ||
| 641 | <P> | ||
| 642 | |||
| 643 | </P> | ||
| 644 | <DT><Q><TT>gdt.c</TT></Q> | ||
| 645 | <DD><DT><Q><TT>gdt.h</TT></Q> | ||
| 646 | <DD>The 80<VAR>x</VAR>86 is a segmented architecture. The Global Descriptor | ||
| 647 | Table (GDT) is a table that describes the segments in use. These | ||
| 648 | files set up the GDT. You should not need to modify these | ||
| 649 | files for any of the projects. You can read the code if | ||
| 650 | you're interested in how the GDT works. | ||
| 651 | <P> | ||
| 652 | |||
| 653 | </P> | ||
| 654 | <DT><Q><TT>tss.c</TT></Q> | ||
| 655 | <DD><DT><Q><TT>tss.h</TT></Q> | ||
| 656 | <DD>The Task-State Segment (TSS) is used for 80<VAR>x</VAR>86 architectural | ||
| 657 | task switching. Pintos uses the TSS only for switching stacks when a | ||
| 658 | user process enters an interrupt handler, as does Linux. You | ||
| 659 | should not need to modify these files for any of the projects. | ||
| 660 | You can read the code if you're interested in how the TSS | ||
| 661 | works. | ||
| 662 | </DL> | ||
| 663 | <P> | ||
| 664 | |||
| 665 | <A NAME="Using the File System"></A> | ||
| 666 | <HR SIZE="6"> | ||
| 667 | <A NAME="SEC24"></A> | ||
| 668 | <H3> 2.2.2 Using the File System </H3> | ||
| 669 | <!--docid::SEC24::--> | ||
| 670 | <P> | ||
| 671 | |||
| 672 | You will need to interface to the file system code, because | ||
| 673 | user programs are loaded from the file system and most of the | ||
| 674 | system calls you must implement deal with the file system. | ||
| 675 | You will want to look over the <Q><TT>filesys.h</TT></Q> and <Q><TT>file.h</TT></Q> | ||
| 676 | interfaces to understand how to use the file system, and especially | ||
| 677 | its many limitations. | ||
| 678 | </P> | ||
| 679 | <P> | ||
| 680 | |||
| 681 | There is no need to modify the file system code in this course, and so | ||
| 682 | we recommend that you do not. Working on the file system is likely to | ||
| 683 | distract you from the project's foci. | ||
| 684 | </P> | ||
| 685 | <P> | ||
| 686 | |||
| 687 | You will have to tolerate the following limitations, however: | ||
| 688 | </P> | ||
| 689 | <P> | ||
| 690 | |||
| 691 | <UL> | ||
| 692 | <LI> | ||
| 693 | No internal synchronization. Concurrent accesses will interfere with one | ||
| 694 | another. You should use synchronization to ensure that only one process at a | ||
| 695 | time is executing file system code. | ||
| 696 | <P> | ||
| 697 | |||
| 698 | </P> | ||
| 699 | <LI> | ||
| 700 | File size is fixed at creation time. The root directory is | ||
| 701 | represented as a file, so the number of files that may be created is also | ||
| 702 | limited. | ||
| 703 | <P> | ||
| 704 | |||
| 705 | </P> | ||
| 706 | <LI> | ||
| 707 | File data is allocated as a single extent, that is, data in a single | ||
| 708 | file must occupy a contiguous range of sectors on disk. External | ||
| 709 | fragmentation can therefore become a serious problem as a file system is | ||
| 710 | used over time. | ||
| 711 | <P> | ||
| 712 | |||
| 713 | </P> | ||
| 714 | <LI> | ||
| 715 | No subdirectories. | ||
| 716 | <P> | ||
| 717 | |||
| 718 | </P> | ||
| 719 | <LI> | ||
| 720 | File names are limited to 14 characters. | ||
| 721 | <P> | ||
| 722 | |||
| 723 | </P> | ||
| 724 | <LI> | ||
| 725 | A system crash mid-operation may corrupt the disk in a way | ||
| 726 | that cannot be repaired automatically. There is no file system repair | ||
| 727 | tool anyway. | ||
| 728 | </UL> | ||
| 729 | <P> | ||
| 730 | |||
| 731 | One important feature is included: | ||
| 732 | </P> | ||
| 733 | <P> | ||
| 734 | |||
| 735 | <UL> | ||
| 736 | <LI> | ||
| 737 | Unix-like semantics for <CODE>filesys_remove()</CODE> are implemented. | ||
| 738 | That is, if a file is open when it is removed, its blocks | ||
| 739 | are not deallocated and it may still be accessed by any | ||
| 740 | threads that have it open, until the last one closes it. See <A HREF="pintos_2.html#Removing an Open File">Removing an Open File</A>, for more information. | ||
| 741 | </UL> | ||
| 742 | <P> | ||
| 743 | |||
| 744 | You need to be able to create a simulated disk with a file system | ||
| 745 | partition. The <CODE>pintos-mkdisk</CODE> program provides this | ||
| 746 | functionality. From the <Q><TT>userprog/build</TT></Q> directory, execute | ||
| 747 | <CODE>pintos-mkdisk filesys.dsk --filesys-size=2</CODE>. This command | ||
| 748 | creates a simulated disk named <Q><TT>filesys.dsk</TT></Q> that contains a 2 | ||
| 749 | MB Pintos file system partition. Then format the file system | ||
| 750 | partition by passing <Q><SAMP>-f -q</SAMP></Q> on the kernel's command line: | ||
| 751 | <CODE>pintos -f -q</CODE>. The <Q><SAMP>-f</SAMP></Q> option causes the file system to | ||
| 752 | be formatted, and <Q><SAMP>-q</SAMP></Q> causes Pintos to exit as soon as the | ||
| 753 | format is done. | ||
| 754 | </P> | ||
| 755 | <P> | ||
| 756 | |||
| 757 | You'll need a way to copy files in and out of the simulated file system. | ||
| 758 | The <CODE>pintos</CODE> <Q><SAMP>-p</SAMP></Q> ("put") and <Q><SAMP>-g</SAMP></Q> ("get") | ||
| 759 | options do this. To copy <Q><TT><VAR>file</VAR></TT></Q> into the | ||
| 760 | Pintos file system, use the command <Q><TT>pintos -p <VAR>file</VAR> -- -q</TT></Q>. | ||
| 761 | (The <Q><SAMP>--</SAMP></Q> is needed because <Q><SAMP>-p</SAMP></Q> is for the <CODE>pintos</CODE> | ||
| 762 | script, not for the simulated kernel.) To copy it to the Pintos file | ||
| 763 | system under the name <Q><TT><VAR>newname</VAR></TT></Q>, add <Q><SAMP>-a | ||
| 764 | <VAR>newname</VAR></SAMP></Q>: <Q><TT>pintos -p <VAR>file</VAR> -a <VAR>newname</VAR> -- -q</TT></Q>. The | ||
| 765 | commands for copying files out of a VM are similar, but substitute | ||
| 766 | <Q><SAMP>-g</SAMP></Q> for <Q><SAMP>-p</SAMP></Q>. | ||
| 767 | </P> | ||
| 768 | <P> | ||
| 769 | |||
| 770 | Incidentally, these commands work by passing special commands | ||
| 771 | <CODE>extract</CODE> and <CODE>append</CODE> on the kernel's command line and copying | ||
| 772 | to and from a special simulated "scratch" partition. If you're very | ||
| 773 | curious, you can look at the <CODE>pintos</CODE> script as well as | ||
| 774 | <Q><TT>filesys/fsutil.c</TT></Q> to learn the implementation details. | ||
| 775 | </P> | ||
| 776 | <P> | ||
| 777 | |||
| 778 | Here's a summary of how to create a disk with a file system partition, | ||
| 779 | format the file system, copy the <CODE>echo</CODE> program into the new | ||
| 780 | disk, and then run <CODE>echo</CODE>, passing argument <CODE>x</CODE>. | ||
| 781 | (Argument passing won't work until you implemented it.) It assumes | ||
| 782 | that you've already built the examples in <Q><TT>examples</TT></Q> and that the | ||
| 783 | current directory is <Q><TT>userprog/build</TT></Q>: | ||
| 784 | </P> | ||
| 785 | <P> | ||
| 786 | |||
| 787 | <TABLE><tr><td> </td><td class=example><pre>pintos-mkdisk filesys.dsk --filesys-size=2 | ||
| 788 | pintos -f -q | ||
| 789 | pintos -p ../../examples/echo -a echo -- -q | ||
| 790 | pintos -q run 'echo x' | ||
| 791 | </pre></td></tr></table><P> | ||
| 792 | |||
| 793 | The three final steps can actually be combined into a single command: | ||
| 794 | </P> | ||
| 795 | <P> | ||
| 796 | |||
| 797 | <TABLE><tr><td> </td><td class=example><pre>pintos-mkdisk filesys.dsk --filesys-size=2 | ||
| 798 | pintos -p ../../examples/echo -a echo -- -f -q run 'echo x' | ||
| 799 | </pre></td></tr></table><P> | ||
| 800 | |||
| 801 | If you don't want to keep the file system disk around for later use or | ||
| 802 | inspection, you can even combine all four steps into a single command. | ||
| 803 | The <CODE>--filesys-size=<VAR>n</VAR></CODE> option creates a temporary file | ||
| 804 | system partition | ||
| 805 | approximately <VAR>n</VAR> megabytes in size just for the duration of the | ||
| 806 | <CODE>pintos</CODE> run. The Pintos automatic test suite makes extensive | ||
| 807 | use of this syntax: | ||
| 808 | </P> | ||
| 809 | <P> | ||
| 810 | |||
| 811 | <TABLE><tr><td> </td><td class=example><pre>pintos --filesys-size=2 -p ../../examples/echo -a echo -- -f -q run 'echo x' | ||
| 812 | </pre></td></tr></table><P> | ||
| 813 | |||
| 814 | You can delete a file from the Pintos file system using the <CODE>rm | ||
| 815 | <VAR>file</VAR></CODE> kernel action, e.g. <CODE>pintos -q rm <VAR>file</VAR></CODE>. Also, | ||
| 816 | <CODE>ls</CODE> lists the files in the file system and <CODE>cat | ||
| 817 | <VAR>file</VAR></CODE> prints a file's contents to the display. | ||
| 818 | </P> | ||
| 819 | <P> | ||
| 820 | |||
| 821 | <A NAME="How User Programs Work"></A> | ||
| 822 | <HR SIZE="6"> | ||
| 823 | <A NAME="SEC25"></A> | ||
| 824 | <H3> 2.2.3 How User Programs Work </H3> | ||
| 825 | <!--docid::SEC25::--> | ||
| 826 | <P> | ||
| 827 | |||
| 828 | Pintos can run normal C programs, as long as they fit into memory and use | ||
| 829 | only the system calls you implement. Notably, <CODE>malloc()</CODE> cannot be | ||
| 830 | implemented because none of the system calls required for this project | ||
| 831 | allow for memory allocation. Pintos also can't run programs that use | ||
| 832 | floating point operations, since the kernel doesn't save and restore the | ||
| 833 | processor's floating-point unit when switching threads. | ||
| 834 | </P> | ||
| 835 | <P> | ||
| 836 | |||
| 837 | The <Q><TT>src/examples</TT></Q> directory contains a few sample user | ||
| 838 | programs. The <Q><TT>Makefile</TT></Q> in this directory | ||
| 839 | compiles the provided examples, and you can edit it | ||
| 840 | compile your own programs as well. Some of the example programs will | ||
| 841 | not work with the current implementation of Pintos. | ||
| 842 | </P> | ||
| 843 | <P> | ||
| 844 | |||
| 845 | Pintos can load <EM>ELF</EM> executables with the loader provided for you | ||
| 846 | in <Q><TT>userprog/process.c</TT></Q>. ELF is a file format used by Linux, | ||
| 847 | Solaris, and many other operating systems for object files, | ||
| 848 | shared libraries, and executables. You can actually use any compiler | ||
| 849 | and linker that output 80<VAR>x</VAR>86 ELF executables to produce programs | ||
| 850 | for Pintos. (We've provided compilers and linkers that should do just | ||
| 851 | fine.) | ||
| 852 | </P> | ||
| 853 | <P> | ||
| 854 | |||
| 855 | You should realize immediately that, until you copy a | ||
| 856 | test program to the simulated file system, Pintos will be unable to do | ||
| 857 | useful work. You won't be able to do | ||
| 858 | interesting things until you copy a variety of programs to the file system. | ||
| 859 | You might want to create a clean reference file system disk and copy that | ||
| 860 | over whenever you trash your <Q><TT>filesys.dsk</TT></Q> beyond a useful state, | ||
| 861 | which may happen occasionally while debugging. | ||
| 862 | </P> | ||
| 863 | <P> | ||
| 864 | |||
| 865 | <A NAME="Virtual Memory Layout"></A> | ||
| 866 | <HR SIZE="6"> | ||
| 867 | <A NAME="SEC26"></A> | ||
| 868 | <H3> 2.2.4 Virtual Memory Layout </H3> | ||
| 869 | <!--docid::SEC26::--> | ||
| 870 | <P> | ||
| 871 | |||
| 872 | Virtual memory in Pintos is divided into two regions: user virtual | ||
| 873 | memory and kernel virtual memory. User virtual memory ranges from | ||
| 874 | virtual address 0 up to <CODE>PHYS_BASE</CODE>, which is defined in | ||
| 875 | <Q><TT>threads/vaddr.h</TT></Q> and defaults to <TT>0xc0000000</TT> (3 GB). Kernel | ||
| 876 | virtual memory occupies the rest of the virtual address space, from | ||
| 877 | <CODE>PHYS_BASE</CODE> up to 4 GB. | ||
| 878 | </P> | ||
| 879 | <P> | ||
| 880 | |||
| 881 | User virtual memory is per-process. | ||
| 882 | When the kernel switches from one process to another, it | ||
| 883 | also switches user virtual address spaces by changing the processor's | ||
| 884 | page directory base register (see <CODE>pagedir_activate()</CODE> in | ||
| 885 | <Q><TT>userprog/pagedir.c</TT></Q>). <CODE>struct thread</CODE> contains a pointer to a | ||
| 886 | process's page table. | ||
| 887 | </P> | ||
| 888 | <P> | ||
| 889 | |||
| 890 | Kernel virtual memory is global. It is always mapped the same way, | ||
| 891 | regardless of what user process or kernel thread is running. In | ||
| 892 | Pintos, kernel virtual memory is mapped one-to-one to physical | ||
| 893 | memory, starting at <CODE>PHYS_BASE</CODE>. That is, virtual address | ||
| 894 | <CODE>PHYS_BASE</CODE> accesses physical | ||
| 895 | address 0, virtual address <CODE>PHYS_BASE</CODE> + <TT>0x1234</TT> accesses | ||
| 896 | physical address <TT>0x1234</TT>, and so on up to the size of the machine's | ||
| 897 | physical memory. | ||
| 898 | </P> | ||
| 899 | <P> | ||
| 900 | |||
| 901 | A user program can only access its own user virtual memory. An attempt to | ||
| 902 | access kernel virtual memory causes a page fault, handled by | ||
| 903 | <CODE>page_fault()</CODE> in <Q><TT>userprog/exception.c</TT></Q>, and the process | ||
| 904 | will be terminated. Kernel threads can access both kernel virtual | ||
| 905 | memory and, if a user process is running, the user virtual memory of | ||
| 906 | the running process. However, even in the kernel, an attempt to | ||
| 907 | access memory at an unmapped user virtual address | ||
| 908 | will cause a page fault. | ||
| 909 | </P> | ||
| 910 | <P> | ||
| 911 | |||
| 912 | <A NAME="Typical Memory Layout"></A> | ||
| 913 | <HR SIZE="6"> | ||
| 914 | <A NAME="SEC27"></A> | ||
| 915 | <H4> 2.2.4.1 Typical Memory Layout </H4> | ||
| 916 | <!--docid::SEC27::--> | ||
| 917 | <P> | ||
| 918 | |||
| 919 | Conceptually, each process is | ||
| 920 | free to lay out its own user virtual memory however it | ||
| 921 | chooses. In practice, user virtual memory is laid out like this: | ||
| 922 | </P> | ||
| 923 | <P> | ||
| 924 | |||
| 925 | <CENTER> | ||
| 926 | <TABLE><tr><td> </td><td class=example><pre> PHYS_BASE +----------------------------------+ | ||
| 927 | | user stack | | ||
| 928 | | | | | ||
| 929 | | | | | ||
| 930 | | V | | ||
| 931 | | grows downward | | ||
| 932 | | | | ||
| 933 | | | | ||
| 934 | | | | ||
| 935 | | | | ||
| 936 | | grows upward | | ||
| 937 | | ^ | | ||
| 938 | | | | | ||
| 939 | | | | | ||
| 940 | +----------------------------------+ | ||
| 941 | | uninitialized data segment (BSS) | | ||
| 942 | +----------------------------------+ | ||
| 943 | | initialized data segment | | ||
| 944 | +----------------------------------+ | ||
| 945 | | code segment | | ||
| 946 | 0x08048000 +----------------------------------+ | ||
| 947 | | | | ||
| 948 | | | | ||
| 949 | | | | ||
| 950 | | | | ||
| 951 | | | | ||
| 952 | 0 +----------------------------------+ | ||
| 953 | </pre></td></tr></table></CENTER> | ||
| 954 | <P> | ||
| 955 | |||
| 956 | In this project, the user stack is fixed in size, but in project 2 it | ||
| 957 | will be allowed to grow. Traditionally, the size of the uninitialized | ||
| 958 | data segment can be adjusted with a system call, but you will not have | ||
| 959 | to implement this. | ||
| 960 | </P> | ||
| 961 | <P> | ||
| 962 | |||
| 963 | The code segment in Pintos starts at user virtual address | ||
| 964 | <TT>0x08084000</TT>, approximately 128 MB from the bottom of the address | ||
| 965 | space. This value is specified in [ <A HREF="pintos_10.html#SysV-i386">SysV-i386</A>] and has no deep | ||
| 966 | significance. | ||
| 967 | </P> | ||
| 968 | <P> | ||
| 969 | |||
| 970 | The linker sets the layout of a user program in memory, as directed by a | ||
| 971 | "linker script" that tells it the names and locations of the various | ||
| 972 | program segments. You can learn more about linker scripts by reading | ||
| 973 | the "Scripts" chapter in the linker manual, accessible via <Q><SAMP>info | ||
| 974 | ld</SAMP></Q>. | ||
| 975 | </P> | ||
| 976 | <P> | ||
| 977 | |||
| 978 | To view the layout of a particular executable, run <CODE>objdump</CODE> | ||
| 979 | (80<VAR>x</VAR>86) or <CODE>i386-elf-objdump</CODE> (SPARC) with the <Q><SAMP>-p</SAMP></Q> | ||
| 980 | option. | ||
| 981 | </P> | ||
| 982 | <P> | ||
| 983 | |||
| 984 | <A NAME="Accessing User Memory"></A> | ||
| 985 | <HR SIZE="6"> | ||
| 986 | <A NAME="SEC28"></A> | ||
| 987 | <H3> 2.2.5 Accessing User Memory </H3> | ||
| 988 | <!--docid::SEC28::--> | ||
| 989 | <P> | ||
| 990 | |||
| 991 | As part of a system | ||
| 992 | call, the kernel must often access memory through pointers provided by a user | ||
| 993 | program. The kernel must be very careful about doing so, because | ||
| 994 | the user can pass a null pointer, a pointer to | ||
| 995 | unmapped virtual memory, or a pointer to kernel virtual address space | ||
| 996 | (above <CODE>PHYS_BASE</CODE>). All of these types of invalid pointers must | ||
| 997 | be rejected without harm to the kernel or other running processes, by | ||
| 998 | terminating the offending process and freeing its resources. | ||
| 999 | </P> | ||
| 1000 | <P> | ||
| 1001 | |||
| 1002 | There are at least two reasonable ways to do this correctly. The | ||
| 1003 | first method is to verify | ||
| 1004 | the validity of a user-provided pointer, then dereference it. | ||
| 1005 | The second method is to check only that a user | ||
| 1006 | pointer points below <CODE>PHYS_BASE</CODE>, then dereference it. | ||
| 1007 | An invalid user pointer will cause a "page fault" that you can | ||
| 1008 | handle by modifying the code for <CODE>page_fault()</CODE> in | ||
| 1009 | <Q><TT>userprog/exception.c</TT></Q>. This technique is normally faster | ||
| 1010 | because it takes advantage of the processor's MMU, so it tends to be | ||
| 1011 | used in real kernels (including Linux). It is also the way | ||
| 1012 | access to user pointers is implemented in the Pintos version provided. | ||
| 1013 | </P> | ||
| 1014 | <P> | ||
| 1015 | |||
| 1016 | In either case, one needs to make sure not to "leak" resources. For | ||
| 1017 | example, suppose that your system call has acquired a lock or | ||
| 1018 | allocated memory with <CODE>malloc()</CODE>. If you encounter an invalid user pointer | ||
| 1019 | afterward, you must still be sure to release the lock or free the page | ||
| 1020 | of memory. If you choose to verify user pointers before dereferencing | ||
| 1021 | them, this should be straightforward. It's more difficult to handle | ||
| 1022 | if an invalid pointer causes a page fault, | ||
| 1023 | because there's no way to return an error code from a memory access. | ||
| 1024 | </P> | ||
| 1025 | <P> | ||
| 1026 | |||
| 1027 | <A NAME="Project 0 Requirements"></A> | ||
| 1028 | <HR SIZE="6"> | ||
| 1029 | <A NAME="SEC29"></A> | ||
| 1030 | <H2> 2.3 Requirements </H2> | ||
| 1031 | <!--docid::SEC29::--> | ||
| 1032 | <P> | ||
| 1033 | |||
| 1034 | <A NAME="Project 0 Design Document"></A> | ||
| 1035 | <HR SIZE="6"> | ||
| 1036 | <A NAME="SEC30"></A> | ||
| 1037 | <H3> 2.3.1 Design Document </H3> | ||
| 1038 | <!--docid::SEC30::--> | ||
| 1039 | <P> | ||
| 1040 | |||
| 1041 | Before you turn in your project, you must copy <A HREF="start.tmpl">the | ||
| 1042 | project 0 design document template</A> into your source tree under the name | ||
| 1043 | <Q><TT>pintos/src/intro/DESIGNDOC</TT></Q> and fill it in. We recommend that | ||
| 1044 | you read the design document template before you start working on the | ||
| 1045 | project. See section <A HREF="pintos_7.html#SEC93">C. Project Documentation</A>, for a sample design document | ||
| 1046 | that goes along with a fictitious project. | ||
| 1047 | </P> | ||
| 1048 | <P> | ||
| 1049 | |||
| 1050 | <A NAME="Alarm Clock"></A> | ||
| 1051 | <HR SIZE="6"> | ||
| 1052 | <A NAME="SEC31"></A> | ||
| 1053 | <H3> 2.3.2 Alarm Clock </H3> | ||
| 1054 | <!--docid::SEC31::--> | ||
| 1055 | <P> | ||
| 1056 | |||
| 1057 | Reimplement <CODE>timer_sleep()</CODE>, defined in <Q><TT>devices/timer.c</TT></Q>. | ||
| 1058 | Although a working implementation is provided, it "busy waits," that | ||
| 1059 | is, it spins in a loop checking the current time and calling | ||
| 1060 | <CODE>thread_yield()</CODE> until enough time has gone by. Reimplement it to | ||
| 1061 | avoid busy waiting. | ||
| 1062 | </P> | ||
| 1063 | <P> | ||
| 1064 | |||
| 1065 | <A NAME="IDX1"></A> | ||
| 1066 | </P> | ||
| 1067 | <DL> | ||
| 1068 | <DT><U>Function:</U> void <B>timer_sleep</B> (int64_t <VAR>ticks</VAR>) | ||
| 1069 | <DD>Suspends execution of the calling thread until time has advanced by at | ||
| 1070 | least <VAR>x</VAR> timer ticks. Unless the system is otherwise idle, the | ||
| 1071 | thread need not wake up after exactly <VAR>x</VAR> ticks. Just put it on | ||
| 1072 | the ready queue after they have waited for the right amount of time. | ||
| 1073 | <P> | ||
| 1074 | |||
| 1075 | <CODE>timer_sleep()</CODE> is useful for threads that operate in real-time, | ||
| 1076 | e.g. for blinking the cursor once per second. | ||
| 1077 | </P> | ||
| 1078 | <P> | ||
| 1079 | |||
| 1080 | The argument to <CODE>timer_sleep()</CODE> is expressed in timer ticks, not in | ||
| 1081 | milliseconds or any another unit. There are <CODE>TIMER_FREQ</CODE> timer | ||
| 1082 | ticks per second, where <CODE>TIMER_FREQ</CODE> is a macro defined in | ||
| 1083 | <CODE>devices/timer.h</CODE>. The default value is 100. We don't recommend | ||
| 1084 | changing this value, because any change is likely to cause many of | ||
| 1085 | the tests to fail. | ||
| 1086 | </P> | ||
| 1087 | </DL> | ||
| 1088 | <P> | ||
| 1089 | |||
| 1090 | Separate functions <CODE>timer_msleep()</CODE>, <CODE>timer_usleep()</CODE>, and | ||
| 1091 | <CODE>timer_nsleep()</CODE> do exist for sleeping a specific number of | ||
| 1092 | milliseconds, microseconds, or nanoseconds, respectively, but these will | ||
| 1093 | call <CODE>timer_sleep()</CODE> automatically when necessary. You do not need | ||
| 1094 | to modify them. | ||
| 1095 | </P> | ||
| 1096 | <P> | ||
| 1097 | |||
| 1098 | If your delays seem too short or too long, reread the explanation of the | ||
| 1099 | <Q><SAMP>-r</SAMP></Q> option to <CODE>pintos</CODE> (see section <A HREF="pintos_1.html#SEC6">1.1.4 Debugging versus Testing</A>). | ||
| 1100 | </P> | ||
| 1101 | <P> | ||
| 1102 | |||
| 1103 | The tests for the <A HREF="pintos_2.html#SEC31">2.3.2 Alarm Clock</A> assignment are executed by changing the | ||
| 1104 | working directory <Q><TT>intro</TT></Q>. The run <Q><SAMP>make</SAMP></Q> to build the | ||
| 1105 | Pintos kernel. Finally run <Q><SAMP>make check</SAMP></Q> to run the tests, | ||
| 1106 | followed by <Q><SAMP>make grade</SAMP></Q> to obtain your score. | ||
| 1107 | </P> | ||
| 1108 | <P> | ||
| 1109 | |||
| 1110 | The alarm clock implementation is not needed for later projects. | ||
| 1111 | </P> | ||
| 1112 | <P> | ||
| 1113 | |||
| 1114 | <A NAME="Argument Passing"></A> | ||
| 1115 | <HR SIZE="6"> | ||
| 1116 | <A NAME="SEC32"></A> | ||
| 1117 | <H3> 2.3.3 Argument Passing </H3> | ||
| 1118 | <!--docid::SEC32::--> | ||
| 1119 | <P> | ||
| 1120 | |||
| 1121 | Currently, <CODE>process_execute()</CODE> does not support passing arguments to | ||
| 1122 | new processes. Implement this functionality, by extending | ||
| 1123 | <CODE>process_execute()</CODE> so that instead of simply taking a program file | ||
| 1124 | name as its argument, it divides it into words at spaces. The first | ||
| 1125 | word is the program name, the second word is the first argument, and so | ||
| 1126 | on. That is, <CODE>process_execute("grep foo bar")</CODE> should run | ||
| 1127 | <CODE>grep</CODE> passing two arguments <CODE>foo</CODE> and <CODE>bar</CODE>. | ||
| 1128 | </P> | ||
| 1129 | <P> | ||
| 1130 | |||
| 1131 | Within a command line, multiple spaces are equivalent to a single | ||
| 1132 | space, so that <CODE>process_execute("grep foo bar")</CODE> | ||
| 1133 | is equivalent to our original example. You can impose a reasonable | ||
| 1134 | limit on the length of the command line arguments. For example, you | ||
| 1135 | could limit the arguments to those that will fit in a single page (4 | ||
| 1136 | kB). (There is an unrelated limit of 128 bytes on command-line | ||
| 1137 | arguments that the <CODE>pintos</CODE> utility can pass to the kernel.) | ||
| 1138 | </P> | ||
| 1139 | <P> | ||
| 1140 | |||
| 1141 | You can parse argument strings any way you like. If you're lost, | ||
| 1142 | look at <CODE>strtok_r()</CODE>, prototyped in <Q><TT>lib/string.h</TT></Q> and | ||
| 1143 | implemented with thorough comments in <Q><TT>lib/string.c</TT></Q>. You can | ||
| 1144 | find more about it by looking at the man page (run <CODE>man strtok_r</CODE> | ||
| 1145 | at the prompt). | ||
| 1146 | </P> | ||
| 1147 | <P> | ||
| 1148 | |||
| 1149 | See section <A HREF="pintos_2.html#SEC39">2.5.1 Program Startup Details</A>, for information on exactly how you | ||
| 1150 | need to set up the stack. | ||
| 1151 | </P> | ||
| 1152 | <P> | ||
| 1153 | |||
| 1154 | <A NAME="Project 0 FAQ"></A> | ||
| 1155 | <HR SIZE="6"> | ||
| 1156 | <A NAME="SEC33"></A> | ||
| 1157 | <H2> 2.4 FAQ </H2> | ||
| 1158 | <!--docid::SEC33::--> | ||
| 1159 | <P> | ||
| 1160 | |||
| 1161 | </P> | ||
| 1162 | <DL COMPACT> | ||
| 1163 | <DT><B>How much code will I need to write?</B> | ||
| 1164 | <DD><P> | ||
| 1165 | |||
| 1166 | Here's a summary of our reference solution, produced by the | ||
| 1167 | <CODE>diffstat</CODE> program. The final row gives total lines inserted | ||
| 1168 | and deleted; a changed line counts as both an insertion and a deletion. | ||
| 1169 | </P> | ||
| 1170 | <P> | ||
| 1171 | |||
| 1172 | The reference solution represents just one possible solution. Many | ||
| 1173 | other solutions are also possible and many of those differ greatly from | ||
| 1174 | the reference solution. Some excellent solutions may not modify all the | ||
| 1175 | files modified by the reference solution, and some may modify files not | ||
| 1176 | modified by the reference solution. | ||
| 1177 | </P> | ||
| 1178 | <P> | ||
| 1179 | |||
| 1180 | <TABLE><tr><td> </td><td class=example><pre> devices/timer.c | 40 +++++++++++- | ||
| 1181 | threads/thread.h | 3 + | ||
| 1182 | userprog/process.c | 148 ++++++++++++++++++++++++++++++----------- | ||
| 1183 | 3 files changed, 150 insertions(+), 41 deletions(-) | ||
| 1184 | </pre></td></tr></table></DL> | ||
| 1185 | <P> | ||
| 1186 | |||
| 1187 | <A NAME="Threads FAQ"></A> | ||
| 1188 | <HR SIZE="6"> | ||
| 1189 | <A NAME="SEC34"></A> | ||
| 1190 | <H3> 2.4.1 Threads FAQ </H3> | ||
| 1191 | <!--docid::SEC34::--> | ||
| 1192 | <P> | ||
| 1193 | |||
| 1194 | </P> | ||
| 1195 | <DL COMPACT> | ||
| 1196 | <DT><B>How do I update the <Q><TT>Makefile</TT></Q>s when I add a new source file?</B> | ||
| 1197 | <DD><P> | ||
| 1198 | |||
| 1199 | <A NAME="Adding Source Files"></A> | ||
| 1200 | To add a <Q><TT>.c</TT></Q> file, edit the top-level <Q><TT>Makefile.build</TT></Q>. | ||
| 1201 | Add the new file to variable <Q><SAMP><VAR>dir</VAR>_SRC</SAMP></Q>, where | ||
| 1202 | <VAR>dir</VAR> is the directory where you added the file. For this | ||
| 1203 | project, that means you should add it to <CODE>threads_SRC</CODE> or | ||
| 1204 | <CODE>devices_SRC</CODE>. Then run <CODE>make</CODE>. If your new file | ||
| 1205 | doesn't get | ||
| 1206 | compiled, run <CODE>make clean</CODE> and then try again. | ||
| 1207 | </P> | ||
| 1208 | <P> | ||
| 1209 | |||
| 1210 | When you modify the top-level <Q><TT>Makefile.build</TT></Q> and re-run | ||
| 1211 | <CODE>make</CODE>, the modified | ||
| 1212 | version should be automatically copied to | ||
| 1213 | <Q><TT>threads/build/Makefile</TT></Q>. The converse is | ||
| 1214 | not true, so any changes will be lost the next time you run <CODE>make | ||
| 1215 | clean</CODE> from the <Q><TT>threads</TT></Q> directory. Unless your changes are | ||
| 1216 | truly temporary, you should prefer to edit <Q><TT>Makefile.build</TT></Q>. | ||
| 1217 | </P> | ||
| 1218 | <P> | ||
| 1219 | |||
| 1220 | A new <Q><TT>.h</TT></Q> file does not require editing the <Q><TT>Makefile</TT></Q>s. | ||
| 1221 | </P> | ||
| 1222 | <P> | ||
| 1223 | |||
| 1224 | </P> | ||
| 1225 | <DT><B>What does <CODE>warning: no previous prototype for `<VAR>func</VAR>'</CODE> mean?</B> | ||
| 1226 | <DD><P> | ||
| 1227 | |||
| 1228 | It means that you defined a non-<CODE>static</CODE> function without | ||
| 1229 | preceding it by a prototype. Because non-<CODE>static</CODE> functions are | ||
| 1230 | intended for use by other <Q><TT>.c</TT></Q> files, for safety they should be | ||
| 1231 | prototyped in a header file included before their definition. To fix | ||
| 1232 | the problem, add a prototype in a header file that you include, or, if | ||
| 1233 | the function isn't actually used by other <Q><TT>.c</TT></Q> files, make it | ||
| 1234 | <CODE>static</CODE>. | ||
| 1235 | </P> | ||
| 1236 | <P> | ||
| 1237 | |||
| 1238 | </P> | ||
| 1239 | <DT><B>What is the interval between timer interrupts?</B> | ||
| 1240 | <DD><P> | ||
| 1241 | |||
| 1242 | Timer interrupts occur <CODE>TIMER_FREQ</CODE> times per second. You can | ||
| 1243 | adjust this value by editing <Q><TT>devices/timer.h</TT></Q>. The default is | ||
| 1244 | 100 Hz. | ||
| 1245 | </P> | ||
| 1246 | <P> | ||
| 1247 | |||
| 1248 | We don't recommend changing this value, because any changes are likely | ||
| 1249 | to cause many of the tests to fail. | ||
| 1250 | </P> | ||
| 1251 | <P> | ||
| 1252 | |||
| 1253 | </P> | ||
| 1254 | <DT><B>How long is a time slice?</B> | ||
| 1255 | <DD><P> | ||
| 1256 | |||
| 1257 | There are <CODE>TIME_SLICE</CODE> ticks per time slice. This macro is | ||
| 1258 | declared in <Q><TT>threads/thread.c</TT></Q>. The default is 4 ticks. | ||
| 1259 | </P> | ||
| 1260 | <P> | ||
| 1261 | |||
| 1262 | We don't recommend changing this value, because any changes are likely | ||
| 1263 | to cause many of the tests to fail. | ||
| 1264 | </P> | ||
| 1265 | <P> | ||
| 1266 | |||
| 1267 | </P> | ||
| 1268 | <DT><B>How do I run the tests?</B> | ||
| 1269 | <DD><P> | ||
| 1270 | |||
| 1271 | See section <A HREF="pintos_1.html#SEC8">1.2.1 Testing</A>. | ||
| 1272 | </P> | ||
| 1273 | <P> | ||
| 1274 | |||
| 1275 | See section <A HREF="pintos_8.html#SEC100">D.4 Backtraces</A>, for more information. | ||
| 1276 | </DL> | ||
| 1277 | <P> | ||
| 1278 | |||
| 1279 | <A NAME="Alarm Clock FAQ"></A> | ||
| 1280 | <HR SIZE="6"> | ||
| 1281 | <A NAME="SEC35"></A> | ||
| 1282 | <H3> 2.4.2 Alarm Clock FAQ </H3> | ||
| 1283 | <!--docid::SEC35::--> | ||
| 1284 | <P> | ||
| 1285 | |||
| 1286 | </P> | ||
| 1287 | <DL COMPACT> | ||
| 1288 | <DT><B>Do I need to account for timer values overflowing?</B> | ||
| 1289 | <DD><P> | ||
| 1290 | |||
| 1291 | Don't worry about the possibility of timer values overflowing. Timer | ||
| 1292 | values are expressed as signed 64-bit numbers, which at 100 ticks per | ||
| 1293 | second should be good for almost 2,924,712,087 years. By then, we | ||
| 1294 | expect Pintos to have been phased out of the curriculum. | ||
| 1295 | </DL> | ||
| 1296 | <P> | ||
| 1297 | |||
| 1298 | <A NAME="Userprog FAQ"></A> | ||
| 1299 | <HR SIZE="6"> | ||
| 1300 | <A NAME="SEC36"></A> | ||
| 1301 | <H3> 2.4.3 Userprog FAQ </H3> | ||
| 1302 | <!--docid::SEC36::--> | ||
| 1303 | <P> | ||
| 1304 | |||
| 1305 | </P> | ||
| 1306 | <DL COMPACT> | ||
| 1307 | <DT><B>The kernel always panics when I run <CODE>pintos -p <VAR>file</VAR> -- -q</CODE>.</B> | ||
| 1308 | <DD><P> | ||
| 1309 | |||
| 1310 | Did you format the file system (with <Q><SAMP>pintos -f</SAMP></Q>)? | ||
| 1311 | </P> | ||
| 1312 | <P> | ||
| 1313 | |||
| 1314 | Is your file name too long? The file system limits file names to 14 | ||
| 1315 | characters. A command like <Q><SAMP>pintos -p ../../examples/echo -- -q</SAMP></Q> | ||
| 1316 | will exceed the limit. Use <Q><SAMP>pintos -p ../../examples/echo -a echo | ||
| 1317 | -- -q</SAMP></Q> to put the file under the name <Q><TT>echo</TT></Q> instead. | ||
| 1318 | </P> | ||
| 1319 | <P> | ||
| 1320 | |||
| 1321 | Is the file system full? | ||
| 1322 | </P> | ||
| 1323 | <P> | ||
| 1324 | |||
| 1325 | Does the file system already contain 16 files? The base Pintos file | ||
| 1326 | system has a 16-file limit. | ||
| 1327 | </P> | ||
| 1328 | <P> | ||
| 1329 | |||
| 1330 | The file system may be so fragmented that there's not enough contiguous | ||
| 1331 | space for your file. | ||
| 1332 | </P> | ||
| 1333 | <P> | ||
| 1334 | |||
| 1335 | </P> | ||
| 1336 | <DT><B>When I run <CODE>pintos -p ../file --</CODE>, <Q><TT>file</TT></Q> isn't copied.</B> | ||
| 1337 | <DD><P> | ||
| 1338 | |||
| 1339 | Files are written under the name you refer to them, by default, so in | ||
| 1340 | this case the file copied in would be named <Q><TT>../file</TT></Q>. You | ||
| 1341 | probably want to run <CODE>pintos -p ../file -a file --</CODE> instead. | ||
| 1342 | </P> | ||
| 1343 | <P> | ||
| 1344 | |||
| 1345 | You can list the files in your file system with <CODE>pintos -q ls</CODE>. | ||
| 1346 | </P> | ||
| 1347 | <P> | ||
| 1348 | |||
| 1349 | </P> | ||
| 1350 | <DT><B>All my user programs die with page faults.</B> | ||
| 1351 | <DD><P> | ||
| 1352 | |||
| 1353 | This will happen if you haven't implemented argument passing | ||
| 1354 | (or haven't done so correctly). The basic C library for user programs tries | ||
| 1355 | to read <VAR>argc</VAR> and <VAR>argv</VAR> off the stack. If the stack | ||
| 1356 | isn't properly set up, this causes a page fault. | ||
| 1357 | </P> | ||
| 1358 | <P> | ||
| 1359 | |||
| 1360 | </P> | ||
| 1361 | <DT><B>How can I disassemble user programs?</B> | ||
| 1362 | <DD><P> | ||
| 1363 | |||
| 1364 | The <CODE>objdump</CODE> (80<VAR>x</VAR>86) or <CODE>i386-elf-objdump</CODE> | ||
| 1365 | (SPARC) utility can disassemble entire user | ||
| 1366 | programs or object files. Invoke it as <CODE>objdump -d | ||
| 1367 | <VAR>file</VAR></CODE>. You can use GDB's | ||
| 1368 | <CODE>disassemble</CODE> command to disassemble individual functions | ||
| 1369 | (see section <A HREF="pintos_8.html#SEC102">D.5 GDB</A>). | ||
| 1370 | </P> | ||
| 1371 | <P> | ||
| 1372 | |||
| 1373 | </P> | ||
| 1374 | <DT><B>Why do many C include files not work in Pintos programs?</B> | ||
| 1375 | <DD><DT><B>Can I use lib<VAR>foo</VAR> in my Pintos programs?</B> | ||
| 1376 | <DD><P> | ||
| 1377 | |||
| 1378 | The C library we provide is very limited. It does not include many of | ||
| 1379 | the features that are expected of a real operating system's C library. | ||
| 1380 | The C library must be built specifically for the operating system (and | ||
| 1381 | architecture), since it must make system calls for I/O and memory | ||
| 1382 | allocation. (Not all functions do, of course, but usually the library | ||
| 1383 | is compiled as a unit.) | ||
| 1384 | </P> | ||
| 1385 | <P> | ||
| 1386 | |||
| 1387 | The chances are good that the library you want uses parts of the C library | ||
| 1388 | that Pintos doesn't implement. It will probably take at least some | ||
| 1389 | porting effort to make it work under Pintos. Notably, the Pintos | ||
| 1390 | user program C library does not have a <CODE>malloc()</CODE> implementation. | ||
| 1391 | </P> | ||
| 1392 | <P> | ||
| 1393 | |||
| 1394 | </P> | ||
| 1395 | <DT><B>How do I compile new user programs?</B> | ||
| 1396 | <DD><P> | ||
| 1397 | |||
| 1398 | Modify <Q><TT>src/examples/Makefile</TT></Q>, then run <CODE>make</CODE>. | ||
| 1399 | </P> | ||
| 1400 | <P> | ||
| 1401 | |||
| 1402 | </P> | ||
| 1403 | <DT><B>Can I run user programs under a debugger?</B> | ||
| 1404 | <DD><P> | ||
| 1405 | |||
| 1406 | Yes, with some limitations. See section <A HREF="pintos_8.html#SEC102">D.5 GDB</A>. | ||
| 1407 | </P> | ||
| 1408 | <P> | ||
| 1409 | |||
| 1410 | </P> | ||
| 1411 | <DT><B>How can I run user programs that need more than 4 kB stack space?</B> | ||
| 1412 | <DD><P> | ||
| 1413 | |||
| 1414 | You may modify the stack setup code to allocate more than one page of | ||
| 1415 | stack space for each process. In project 2, you will implement a better | ||
| 1416 | solution. | ||
| 1417 | </P> | ||
| 1418 | <P> | ||
| 1419 | |||
| 1420 | </P> | ||
| 1421 | <DT><B>What happens when an open file is removed?</B> | ||
| 1422 | <DD><A NAME="Removing an Open File"></A> | ||
| 1423 | <P> | ||
| 1424 | |||
| 1425 | You should implement the standard Unix semantics for files. That is, when | ||
| 1426 | a file is removed any process which has a file descriptor for that file | ||
| 1427 | may continue to use that descriptor. This means that | ||
| 1428 | they can read and write from the file. The file will not have a name, | ||
| 1429 | and no other processes will be able to open it, but it will continue | ||
| 1430 | to exist until all file descriptors referring to the file are closed | ||
| 1431 | or the machine shuts down. | ||
| 1432 | </P> | ||
| 1433 | <P> | ||
| 1434 | |||
| 1435 | </DL> | ||
| 1436 | <P> | ||
| 1437 | |||
| 1438 | <A NAME="Argument Passing FAQ"></A> | ||
| 1439 | <HR SIZE="6"> | ||
| 1440 | <A NAME="SEC37"></A> | ||
| 1441 | <H3> 2.4.4 Argument Passing FAQ </H3> | ||
| 1442 | <!--docid::SEC37::--> | ||
| 1443 | <P> | ||
| 1444 | |||
| 1445 | </P> | ||
| 1446 | <DL COMPACT> | ||
| 1447 | <DT><B>Isn't the top of stack in kernel virtual memory?</B> | ||
| 1448 | <DD><P> | ||
| 1449 | |||
| 1450 | The top of stack is at <CODE>PHYS_BASE</CODE>, typically <TT>0xc0000000</TT>, which | ||
| 1451 | is also where kernel virtual memory starts. | ||
| 1452 | But before the processor pushes data on the stack, it decrements the stack | ||
| 1453 | pointer. Thus, the first (4-byte) value pushed on the stack | ||
| 1454 | will be at address <TT>0xbffffffc</TT>. | ||
| 1455 | </P> | ||
| 1456 | <P> | ||
| 1457 | |||
| 1458 | </P> | ||
| 1459 | <DT><B>Is <CODE>PHYS_BASE</CODE> fixed?</B> | ||
| 1460 | <DD><P> | ||
| 1461 | |||
| 1462 | No. You should be able to support <CODE>PHYS_BASE</CODE> values that are | ||
| 1463 | any multiple of <TT>0x10000000</TT> from <TT>0x80000000</TT> to <TT>0xf0000000</TT>, | ||
| 1464 | simply via recompilation. | ||
| 1465 | </DL> | ||
| 1466 | <P> | ||
| 1467 | |||
| 1468 | <A NAME="80x86 Calling Convention"></A> | ||
| 1469 | <HR SIZE="6"> | ||
| 1470 | <A NAME="SEC38"></A> | ||
| 1471 | <H2> 2.5 80<VAR>x</VAR>86 Calling Convention </H2> | ||
| 1472 | <!--docid::SEC38::--> | ||
| 1473 | <P> | ||
| 1474 | |||
| 1475 | This section summarizes important points of the convention used for | ||
| 1476 | normal function calls on 32-bit 80<VAR>x</VAR>86 implementations of Unix. | ||
| 1477 | Some details are omitted for brevity. If you do want all the details, | ||
| 1478 | refer to [ <A HREF="pintos_10.html#SysV-i386">SysV-i386</A>]. | ||
| 1479 | </P> | ||
| 1480 | <P> | ||
| 1481 | |||
| 1482 | The calling convention works like this: | ||
| 1483 | </P> | ||
| 1484 | <P> | ||
| 1485 | |||
| 1486 | <OL> | ||
| 1487 | <LI> | ||
| 1488 | The caller pushes each of the function's arguments on the stack one by | ||
| 1489 | one, normally using the <CODE>PUSH</CODE> assembly language instruction. | ||
| 1490 | Arguments are pushed in right-to-left order. | ||
| 1491 | <P> | ||
| 1492 | |||
| 1493 | The stack grows downward: each push decrements the stack pointer, then | ||
| 1494 | stores into the location it now points to, like the C expression | ||
| 1495 | <Q><SAMP>*--sp = <VAR>value</VAR></SAMP></Q>. | ||
| 1496 | </P> | ||
| 1497 | <P> | ||
| 1498 | |||
| 1499 | </P> | ||
| 1500 | <LI> | ||
| 1501 | The caller pushes the address of its next instruction (the <EM>return | ||
| 1502 | address</EM>) on the stack and jumps to the first instruction of the callee. | ||
| 1503 | A single 80<VAR>x</VAR>86 instruction, <CODE>CALL</CODE>, does both. | ||
| 1504 | <P> | ||
| 1505 | |||
| 1506 | </P> | ||
| 1507 | <LI> | ||
| 1508 | The callee executes. When it takes control, the stack pointer points to | ||
| 1509 | the return address, the first argument is just above it, the second | ||
| 1510 | argument is just above the first argument, and so on. | ||
| 1511 | <P> | ||
| 1512 | |||
| 1513 | </P> | ||
| 1514 | <LI> | ||
| 1515 | If the callee has a return value, it stores it into register <CODE>EAX</CODE>. | ||
| 1516 | <P> | ||
| 1517 | |||
| 1518 | </P> | ||
| 1519 | <LI> | ||
| 1520 | The callee returns by popping the return address from the stack and | ||
| 1521 | jumping to the location it specifies, using the 80<VAR>x</VAR>86 <CODE>RET</CODE> | ||
| 1522 | instruction. | ||
| 1523 | <P> | ||
| 1524 | |||
| 1525 | </P> | ||
| 1526 | <LI> | ||
| 1527 | The caller pops the arguments off the stack. | ||
| 1528 | </OL> | ||
| 1529 | <P> | ||
| 1530 | |||
| 1531 | Consider a function <CODE>f()</CODE> that takes three <CODE>int</CODE> arguments. | ||
| 1532 | This diagram shows a sample stack frame as seen by the callee at the | ||
| 1533 | beginning of step 3 above, supposing that <CODE>f()</CODE> is invoked as | ||
| 1534 | <CODE>f(1, 2, 3)</CODE>. The initial stack address is arbitrary: | ||
| 1535 | </P> | ||
| 1536 | <P> | ||
| 1537 | |||
| 1538 | <CENTER> | ||
| 1539 | <TABLE><tr><td> </td><td class=example><pre> +----------------+ | ||
| 1540 | 0xbffffe7c | 3 | | ||
| 1541 | 0xbffffe78 | 2 | | ||
| 1542 | 0xbffffe74 | 1 | | ||
| 1543 | stack pointer --> 0xbffffe70 | return address | | ||
| 1544 | +----------------+ | ||
| 1545 | </pre></td></tr></table></CENTER> | ||
| 1546 | <P> | ||
| 1547 | |||
| 1548 | <A NAME="Program Startup Details"></A> | ||
| 1549 | <HR SIZE="6"> | ||
| 1550 | <A NAME="SEC39"></A> | ||
| 1551 | <H3> 2.5.1 Program Startup Details </H3> | ||
| 1552 | <!--docid::SEC39::--> | ||
| 1553 | <P> | ||
| 1554 | |||
| 1555 | The Pintos C library for user programs designates <CODE>_start()</CODE>, in | ||
| 1556 | <Q><TT>lib/user/entry.c</TT></Q>, as the entry point for user programs. This | ||
| 1557 | function is a wrapper around <CODE>main()</CODE> that calls <CODE>exit()</CODE> if | ||
| 1558 | <CODE>main()</CODE> returns: | ||
| 1559 | </P> | ||
| 1560 | <P> | ||
| 1561 | |||
| 1562 | <TABLE><tr><td> </td><td class=example><pre>void | ||
| 1563 | _start (int argc, char *argv[]) | ||
| 1564 | { | ||
| 1565 | exit (main (argc, argv)); | ||
| 1566 | } | ||
| 1567 | </pre></td></tr></table><P> | ||
| 1568 | |||
| 1569 | The kernel must put the arguments for the initial function on the stack | ||
| 1570 | before it allows the user program to begin executing. The arguments are | ||
| 1571 | passed in the same way as the normal calling convention (see section <A HREF="pintos_2.html#SEC38">2.5 80<VAR>x</VAR>86 Calling Convention</A>). | ||
| 1572 | </P> | ||
| 1573 | <P> | ||
| 1574 | |||
| 1575 | Consider how to handle arguments for the following example command: | ||
| 1576 | <Q><SAMP>/bin/ls -l foo bar</SAMP></Q>. | ||
| 1577 | First, break the command into words: <Q><SAMP>/bin/ls</SAMP></Q>, | ||
| 1578 | <Q><SAMP>-l</SAMP></Q>, <Q><SAMP>foo</SAMP></Q>, <Q><SAMP>bar</SAMP></Q>. Place the words at the top of the | ||
| 1579 | stack. Order doesn't matter, because they will be referenced through | ||
| 1580 | pointers. | ||
| 1581 | </P> | ||
| 1582 | <P> | ||
| 1583 | |||
| 1584 | Then, push the address of each string plus a null pointer sentinel, on | ||
| 1585 | the stack, in right-to-left order. These are the elements of | ||
| 1586 | <CODE>argv</CODE>. The null pointer sentinel ensures that <CODE>argv[argc]</CODE> | ||
| 1587 | is a null pointer, as required by the C standard. The order ensures | ||
| 1588 | that <CODE>argv[0]</CODE> is at the lowest virtual address. Word-aligned | ||
| 1589 | accesses are faster than unaligned accesses, so for best performance | ||
| 1590 | round the stack pointer down to a multiple of 4 before the first push. | ||
| 1591 | </P> | ||
| 1592 | <P> | ||
| 1593 | |||
| 1594 | Then, push <CODE>argv</CODE> (the address of <CODE>argv[0]</CODE>) and <CODE>argc</CODE>, | ||
| 1595 | in that order. Finally, push a fake "return address": although the | ||
| 1596 | entry function will never return, its stack frame must have the same | ||
| 1597 | structure as any other. | ||
| 1598 | </P> | ||
| 1599 | <P> | ||
| 1600 | |||
| 1601 | The table below shows the state of the stack and the relevant registers | ||
| 1602 | right before the beginning of the user program, assuming | ||
| 1603 | <CODE>PHYS_BASE</CODE> is <TT>0xc0000000</TT>: | ||
| 1604 | </P> | ||
| 1605 | <P> | ||
| 1606 | |||
| 1607 | <CENTER> | ||
| 1608 | </P> | ||
| 1609 | <TABLE> | ||
| 1610 | <TR><TD>Address </TD><TD> Name </TD><TD> Data </TD><TD> Type</TD> | ||
| 1611 | </TR> | ||
| 1612 | <TR><TD><TT>0xbffffffc</TT> </TD><TD> <CODE>argv[3][<small>...</small>]</CODE> </TD><TD> <Q><SAMP>bar\0</SAMP></Q> </TD><TD> <CODE>char[4]</CODE></TD> | ||
| 1613 | </TR> | ||
| 1614 | <TR><TD><TT>0xbffffff8</TT> </TD><TD> <CODE>argv[2][<small>...</small>]</CODE> </TD><TD> <Q><SAMP>foo\0</SAMP></Q> </TD><TD> <CODE>char[4]</CODE></TD> | ||
| 1615 | </TR> | ||
| 1616 | <TR><TD><TT>0xbffffff5</TT> </TD><TD> <CODE>argv[1][<small>...</small>]</CODE> </TD><TD> <Q><SAMP>-l\0</SAMP></Q> </TD><TD> <CODE>char[3]</CODE></TD> | ||
| 1617 | </TR> | ||
| 1618 | <TR><TD><TT>0xbfffffed</TT> </TD><TD> <CODE>argv[0][<small>...</small>]</CODE> </TD><TD> <Q><SAMP>/bin/ls\0</SAMP></Q> </TD><TD> <CODE>char[8]</CODE></TD> | ||
| 1619 | </TR> | ||
| 1620 | <TR><TD><TT>0xbfffffec</TT> </TD><TD> word-align </TD><TD> 0 </TD><TD> <CODE>uint8_t</CODE></TD> | ||
| 1621 | </TR> | ||
| 1622 | <TR><TD><TT>0xbfffffe8</TT> </TD><TD> <CODE>argv[4]</CODE> </TD><TD> <TT>0</TT> </TD><TD> <CODE>char *</CODE></TD> | ||
| 1623 | </TR> | ||
| 1624 | <TR><TD><TT>0xbfffffe4</TT> </TD><TD> <CODE>argv[3]</CODE> </TD><TD> <TT>0xbffffffc</TT> </TD><TD> <CODE>char *</CODE></TD> | ||
| 1625 | </TR> | ||
| 1626 | <TR><TD><TT>0xbfffffe0</TT> </TD><TD> <CODE>argv[2]</CODE> </TD><TD> <TT>0xbffffff8</TT> </TD><TD> <CODE>char *</CODE></TD> | ||
| 1627 | </TR> | ||
| 1628 | <TR><TD><TT>0xbfffffdc</TT> </TD><TD> <CODE>argv[1]</CODE> </TD><TD> <TT>0xbffffff5</TT> </TD><TD> <CODE>char *</CODE></TD> | ||
| 1629 | </TR> | ||
| 1630 | <TR><TD><TT>0xbfffffd8</TT> </TD><TD> <CODE>argv[0]</CODE> </TD><TD> <TT>0xbfffffed</TT> </TD><TD> <CODE>char *</CODE></TD> | ||
| 1631 | </TR> | ||
| 1632 | <TR><TD><TT>0xbfffffd4</TT> </TD><TD> <CODE>argv</CODE> </TD><TD> <TT>0xbfffffd8</TT> </TD><TD> <CODE>char **</CODE></TD> | ||
| 1633 | </TR> | ||
| 1634 | <TR><TD><TT>0xbfffffd0</TT> </TD><TD> <CODE>argc</CODE> </TD><TD> 4 </TD><TD> <CODE>int</CODE></TD> | ||
| 1635 | </TR> | ||
| 1636 | <TR><TD><TT>0xbfffffcc</TT> </TD><TD> return address </TD><TD> 0 </TD><TD> <CODE>void (*) ()</CODE></TD> | ||
| 1637 | </TR></TABLE> | ||
| 1638 | </CENTER> | ||
| 1639 | <P> | ||
| 1640 | |||
| 1641 | In this example, the stack pointer would be initialized to | ||
| 1642 | <TT>0xbfffffcc</TT>. | ||
| 1643 | </P> | ||
| 1644 | <P> | ||
| 1645 | |||
| 1646 | As shown above, your code should start the stack at the very top of | ||
| 1647 | the user virtual address space, in the page just below virtual address | ||
| 1648 | <CODE>PHYS_BASE</CODE> (defined in <Q><TT>threads/vaddr.h</TT></Q>). | ||
| 1649 | </P> | ||
| 1650 | <P> | ||
| 1651 | |||
| 1652 | You may find the non-standard <CODE>hex_dump()</CODE> function, declared in | ||
| 1653 | <Q><TT><stdio.h></TT></Q>, useful for debugging your argument passing code. | ||
| 1654 | Here's what it would show in the above example: | ||
| 1655 | </P> | ||
| 1656 | <P> | ||
| 1657 | |||
| 1658 | <TABLE><tr><td> </td><td class=example><pre>bfffffc0 00 00 00 00 | ....| | ||
| 1659 | bfffffd0 04 00 00 00 d8 ff ff bf-ed ff ff bf f5 ff ff bf |................| | ||
| 1660 | bfffffe0 f8 ff ff bf fc ff ff bf-00 00 00 00 00 2f 62 69 |............./bi| | ||
| 1661 | bffffff0 6e 2f 6c 73 00 2d 6c 00-66 6f 6f 00 62 61 72 00 |n/ls.-l.foo.bar.| | ||
| 1662 | </pre></td></tr></table><P> | ||
| 1663 | |||
| 1664 | <A NAME="System Call Details"></A> | ||
| 1665 | <HR SIZE="6"> | ||
| 1666 | <A NAME="SEC40"></A> | ||
| 1667 | <H3> 2.5.2 System Call Details </H3> | ||
| 1668 | <!--docid::SEC40::--> | ||
| 1669 | <P> | ||
| 1670 | |||
| 1671 | We already know one way that the operating system | ||
| 1672 | can regain control from a user program: interrupts from timers and I/O | ||
| 1673 | devices. These are "external" interrupts, because they are caused | ||
| 1674 | by entities outside the CPU (see section <A HREF="pintos_5.html#SEC68">A.4.3 External Interrupt Handling</A>). | ||
| 1675 | </P> | ||
| 1676 | <P> | ||
| 1677 | |||
| 1678 | The operating system also deals with software exceptions, which are | ||
| 1679 | events that occur in program code (see section <A HREF="pintos_5.html#SEC67">A.4.2 Internal Interrupt Handling</A>). These can be errors such as a page fault or division by | ||
| 1680 | zero. Exceptions are also the means by which a user program | ||
| 1681 | can request services ("system calls") from the operating system. | ||
| 1682 | </P> | ||
| 1683 | <P> | ||
| 1684 | |||
| 1685 | In the 80<VAR>x</VAR>86 architecture, the <Q><SAMP>int</SAMP></Q> instruction is the | ||
| 1686 | most commonly used means for invoking system calls. This instruction | ||
| 1687 | is handled in the same way as other software exceptions. In Pintos, | ||
| 1688 | user programs invoke <Q><SAMP>int $0x30</SAMP></Q> to make a system call. The | ||
| 1689 | system call number and any additional arguments are expected to be | ||
| 1690 | pushed on the stack in the normal fashion before invoking the | ||
| 1691 | interrupt (see section <A HREF="pintos_2.html#SEC38">2.5 80<VAR>x</VAR>86 Calling Convention</A>). | ||
| 1692 | </P> | ||
| 1693 | <P> | ||
| 1694 | |||
| 1695 | Thus, when the system call handler <CODE>syscall_handler()</CODE> gets control, | ||
| 1696 | the system call number is in the 32-bit word at the caller's stack | ||
| 1697 | pointer, the first argument is in the 32-bit word at the next higher | ||
| 1698 | address, and so on. The caller's stack pointer is accessible to | ||
| 1699 | <CODE>syscall_handler()</CODE> as the <Q><SAMP>esp</SAMP></Q> member of the | ||
| 1700 | <CODE>struct intr_frame</CODE> passed to it. (<CODE>struct intr_frame</CODE> is on the kernel | ||
| 1701 | stack.) | ||
| 1702 | </P> | ||
| 1703 | <P> | ||
| 1704 | |||
| 1705 | The 80<VAR>x</VAR>86 convention for function return values is to place them | ||
| 1706 | in the <CODE>EAX</CODE> register. System calls that return a value can do | ||
| 1707 | so by modifying the <Q><SAMP>eax</SAMP></Q> member of <CODE>struct intr_frame</CODE>. | ||
| 1708 | </P> | ||
| 1709 | <P> | ||
| 1710 | |||
| 1711 | You should try to avoid writing large amounts of repetitive code for | ||
| 1712 | implementing system calls. Each system call argument, whether an | ||
| 1713 | integer or a pointer, takes up 4 bytes on the stack. You should be able | ||
| 1714 | to take advantage of this to avoid writing much near-identical code for | ||
| 1715 | retrieving each system call's arguments from the stack. | ||
| 1716 | <A NAME="Project 1--Threads"></A> | ||
| 1717 | <HR SIZE="6"> | ||
| 1718 | <TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> | ||
| 1719 | <TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_2.html#SEC15"> << </A>]</TD> | ||
| 1720 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_3.html#SEC41"> >> </A>]</TD> | ||
| 1721 | <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos.html#SEC_Top">Top</A>]</TD> | ||
| 1722 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos.html#SEC_Contents">Contents</A>]</TD> | ||
| 1723 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> | ||
| 1724 | <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="pintos_abt.html#SEC_About"> ? </A>]</TD> | ||
| 1725 | </TR></TABLE> | ||
| 1726 | <BR> | ||
| 1727 | <FONT SIZE="-1"> | ||
| 1728 | This document was generated | ||
| 1729 | by on <I>March, 6 2012</I> | ||
| 1730 | using <A HREF="http://texi2html.cvshome.org"><I>texi2html</I></A> | ||
| 1731 | </FONT> | ||
| 1732 | |||
| 1733 | </BODY> | ||
| 1734 | </HTML> | ||
