11 struct proc proc
[NPROC
];
14 static struct proc
*initproc
;
17 extern void forkret(void);
18 extern void trapret(void);
20 static void wakeup1(void *chan
);
25 initlock(&ptable
.lock
, "ptable");
28 // Look in the process table for an UNUSED proc.
29 // If found, change state to EMBRYO and initialize
30 // state required to run in the kernel.
31 // Otherwise return 0.
38 acquire(&ptable
.lock
);
39 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++)
40 if(p
->state
== UNUSED
)
42 release(&ptable
.lock
);
48 release(&ptable
.lock
);
50 // Allocate kernel stack if possible.
51 if((p
->kstack
= kalloc()) == 0){
55 sp
= p
->kstack
+ KSTACKSIZE
;
57 // Leave room for trap frame.
59 p
->tf
= (struct trapframe
*)sp
;
61 // Set up new context to start executing at forkret,
62 // which returns to trapret.
64 *(uint
*)sp
= (uint
)trapret
;
66 sp
-= sizeof *p
->context
;
67 p
->context
= (struct context
*)sp
;
68 memset(p
->context
, 0, sizeof *p
->context
);
69 p
->context
->eip
= (uint
)forkret
;
74 // Set up first user process.
79 extern char _binary_initcode_start
[], _binary_initcode_size
[];
83 if((p
->pgdir
= setupkvm()) == 0)
84 panic("userinit: out of memory?");
85 inituvm(p
->pgdir
, _binary_initcode_start
, (int)_binary_initcode_size
);
87 memset(p
->tf
, 0, sizeof(*p
->tf
));
88 p
->tf
->cs
= (SEG_UCODE
<< 3) | DPL_USER
;
89 p
->tf
->ds
= (SEG_UDATA
<< 3) | DPL_USER
;
90 p
->tf
->es
= p
->tf
->ds
;
91 p
->tf
->ss
= p
->tf
->ds
;
92 p
->tf
->eflags
= FL_IF
;
94 p
->tf
->eip
= 0; // beginning of initcode.S
96 safestrcpy(p
->name
, "initcode", sizeof(p
->name
));
102 // Grow current process's memory by n bytes.
103 // Return 0 on success, -1 on failure.
111 if((sz
= allocuvm(proc
->pgdir
, sz
, sz
+ n
)) == 0)
114 if((sz
= deallocuvm(proc
->pgdir
, sz
, sz
+ n
)) == 0)
122 // Create a new process copying p as the parent.
123 // Sets up stack to return as if from system call.
124 // Caller must set state of returned proc to RUNNABLE.
132 if((np
= allocproc()) == 0)
135 // Copy process state from p.
136 if((np
->pgdir
= copyuvm(proc
->pgdir
, proc
->sz
)) == 0){
146 // Clear %eax so that fork returns 0 in the child.
149 for(i
= 0; i
< NOFILE
; i
++)
151 np
->ofile
[i
] = filedup(proc
->ofile
[i
]);
152 np
->cwd
= idup(proc
->cwd
);
155 np
->state
= RUNNABLE
;
156 safestrcpy(np
->name
, proc
->name
, sizeof(proc
->name
));
160 // Exit the current process. Does not return.
161 // An exited process remains in the zombie state
162 // until its parent calls wait() to find out it exited.
170 panic("init exiting");
172 // Close all open files.
173 for(fd
= 0; fd
< NOFILE
; fd
++){
175 fileclose(proc
->ofile
[fd
]);
183 acquire(&ptable
.lock
);
185 // Parent might be sleeping in wait().
186 wakeup1(proc
->parent
);
188 // Pass abandoned children to init.
189 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++){
190 if(p
->parent
== proc
){
191 p
->parent
= initproc
;
192 if(p
->state
== ZOMBIE
)
197 // Jump into the scheduler, never to return.
198 proc
->state
= ZOMBIE
;
200 panic("zombie exit");
203 // Wait for a child process to exit and return its pid.
204 // Return -1 if this process has no children.
211 acquire(&ptable
.lock
);
213 // Scan through table looking for zombie children.
215 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++){
216 if(p
->parent
!= proc
)
219 if(p
->state
== ZOMBIE
){
230 release(&ptable
.lock
);
235 // No point waiting if we don't have any children.
236 if(!havekids
|| proc
->killed
){
237 release(&ptable
.lock
);
241 // Wait for children to exit. (See wakeup1 call in proc_exit.)
242 sleep(proc
, &ptable
.lock
); //DOC: wait-sleep
246 // Per-CPU process scheduler.
247 // Each CPU calls scheduler() after setting itself up.
248 // Scheduler never returns. It loops, doing:
249 // - choose a process to run
250 // - swtch to start running that process
251 // - eventually that process transfers control
252 // via swtch back to the scheduler.
259 // Enable interrupts on this processor.
262 // Loop over process table looking for process to run.
263 acquire(&ptable
.lock
);
264 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++){
265 if(p
->state
!= RUNNABLE
)
268 // Switch to chosen process. It is the process's job
269 // to release ptable.lock and then reacquire it
270 // before jumping back to us.
274 swtch(&cpu
->scheduler
, proc
->context
);
277 // Process is done running for now.
278 // It should have changed its p->state before coming back.
281 release(&ptable
.lock
);
286 // Enter scheduler. Must hold only ptable.lock
287 // and have changed proc->state.
293 if(!holding(&ptable
.lock
))
294 panic("sched ptable.lock");
296 panic("sched locks");
297 if(proc
->state
== RUNNING
)
298 panic("sched running");
299 if(readeflags()&FL_IF
)
300 panic("sched interruptible");
301 intena
= cpu
->intena
;
302 swtch(&proc
->context
, cpu
->scheduler
);
303 cpu
->intena
= intena
;
306 // Give up the CPU for one scheduling round.
310 acquire(&ptable
.lock
); //DOC: yieldlock
311 proc
->state
= RUNNABLE
;
313 release(&ptable
.lock
);
316 // A fork child's very first scheduling by scheduler()
317 // will swtch here. "Return" to user space.
321 // Still holding ptable.lock from scheduler.
322 release(&ptable
.lock
);
324 // Return to "caller", actually trapret (see allocproc).
327 // Atomically release lock and sleep on chan.
328 // Reacquires lock when awakened.
330 sleep(void *chan
, struct spinlock
*lk
)
336 panic("sleep without lk");
338 // Must acquire ptable.lock in order to
339 // change p->state and then call sched.
340 // Once we hold ptable.lock, we can be
341 // guaranteed that we won't miss any wakeup
342 // (wakeup runs with ptable.lock locked),
343 // so it's okay to release lk.
344 if(lk
!= &ptable
.lock
){ //DOC: sleeplock0
345 acquire(&ptable
.lock
); //DOC: sleeplock1
351 proc
->state
= SLEEPING
;
357 // Reacquire original lock.
358 if(lk
!= &ptable
.lock
){ //DOC: sleeplock2
359 release(&ptable
.lock
);
364 // Wake up all processes sleeping on chan.
365 // The ptable lock must be held.
371 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++)
372 if(p
->state
== SLEEPING
&& p
->chan
== chan
)
376 // Wake up all processes sleeping on chan.
380 acquire(&ptable
.lock
);
382 release(&ptable
.lock
);
385 // Kill the process with the given pid.
386 // Process won't exit until it returns
387 // to user space (see trap in trap.c).
393 acquire(&ptable
.lock
);
394 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++){
397 // Wake process from sleep if necessary.
398 if(p
->state
== SLEEPING
)
400 release(&ptable
.lock
);
404 release(&ptable
.lock
);
408 // Print a process listing to console. For debugging.
409 // Runs when user types ^P on console.
410 // No lock to avoid wedging a stuck machine further.
414 static char *states
[] = {
427 for(p
= ptable
.proc
; p
< &ptable
.proc
[NPROC
]; p
++){
428 if(p
->state
== UNUSED
)
430 if(p
->state
>= 0 && p
->state
< NELEM(states
) && states
[p
->state
])
431 state
= states
[p
->state
];
434 cprintf("%d %s %s", p
->pid
, state
, p
->name
);
435 if(p
->state
== SLEEPING
){
436 getcallerpcs((uint
*)p
->context
->ebp
+2, pc
);
437 for(i
=0; i
<10 && pc
[i
] != 0; i
++)
438 cprintf(" %p", pc
[i
]);