Merge branch 'master' into net-dev (with code changes listed below besides normal...
[akaros.git] / kern / src / process.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7 #include <process.h>
8 #include <atomic.h>
9 #include <smp.h>
10 #include <pmap.h>
11 #include <schedule.h>
12 #include <manager.h>
13 #include <stdio.h>
14 #include <assert.h>
15 #include <sys/queue.h>
16
17 struct proc_list proc_freelist = TAILQ_HEAD_INITIALIZER(proc_freelist);
18 spinlock_t freelist_lock = 0;
19 struct proc_list proc_runnablelist = TAILQ_HEAD_INITIALIZER(proc_runnablelist);
20 spinlock_t runnablelist_lock = 0;
21
22 /*
23  * While this could be done with just an assignment, this gives us the
24  * opportunity to check for bad transitions.  Might compile these out later, so
25  * we shouldn't rely on them for sanity checking from userspace.
26  */
27 int proc_set_state(struct proc *p, uint32_t state)
28 {
29         uint32_t curstate = p->state;
30         /* Valid transitions:
31          * C   -> RBS
32          * RBS -> RGS
33          * RGS -> RBS
34          * RGS -> W
35          * W   -> RBS
36          * RGS -> RBM
37          * RBM -> RGM
38          * RGM -> RBM
39          * RGM -> RBS
40          * RGS -> D
41          * RGM -> D
42          *
43          * These ought to be implemented later (allowed, not thought through yet).
44          * RBS -> D
45          * RBM -> D
46          *
47          * This isn't allowed yet, may be later.
48          * C   -> D
49          */
50         #if 1 // some sort of correctness flag
51         switch (curstate) {
52                 case PROC_CREATED:
53                         if (state != PROC_RUNNABLE_S)
54                                 panic("Invalid State Transition! PROC_CREATED to %d", state);
55                         break;
56                 case PROC_RUNNABLE_S:
57                         if (!(state & (PROC_RUNNING_S | PROC_DYING)))
58                                 panic("Invalid State Transition! PROC_RUNNABLE_S to %d", state);
59                         break;
60                 case PROC_RUNNING_S:
61                         if (!(state & (PROC_RUNNABLE_S | PROC_RUNNABLE_M | PROC_WAITING |
62                                        PROC_DYING)))
63                                 panic("Invalid State Transition! PROC_RUNNING_S to %d", state);
64                         break;
65                 case PROC_WAITING:
66                         if (state != PROC_RUNNABLE_S)
67                                 panic("Invalid State Transition! PROC_WAITING to %d", state);
68                         break;
69                 case PROC_DYING:
70                         if (state != PROC_CREATED) // when it is reused (TODO)
71                                 panic("Invalid State Transition! PROC_DYING to %d", state);
72                         break;
73                 case PROC_RUNNABLE_M:
74                         if (!(state & (PROC_RUNNING_M | PROC_DYING)))
75                                 panic("Invalid State Transition! PROC_RUNNABLE_M to %d", state);
76                         break;
77                 case PROC_RUNNING_M:
78                         if (!(state & (PROC_RUNNABLE_S | PROC_RUNNABLE_M | PROC_DYING)))
79                                 panic("Invalid State Transition! PROC_RUNNING_M to %d", state);
80                         break;
81         }
82         #endif
83         p->state = state;
84         return 0;
85 }
86
87 /* Change this when we aren't using an array */
88 struct proc *get_proc(unsigned pid)
89 {
90         // should have some error checking when we do this for real
91         return &envs[ENVX(pid)];
92 }
93
94 /* Whether or not actor can control target */
95 bool proc_controls(struct proc *actor, struct proc *target)
96 {
97         return target->env_parent_id == actor->env_id;
98 }
99
100 /*
101  * Dispatches a process to run, either on the current core in the case of a
102  * RUNNABLE_S, or on its partition in the case of a RUNNABLE_M.
103  * This should never be called to "restart" a core.
104  */
105 void proc_run(struct proc *p)
106 {
107         spin_lock_irqsave(&p->proc_lock);
108         switch (p->state) {
109                 case (PROC_DYING):
110                         spin_unlock_irqsave(&p->proc_lock);
111                         printk("Process %d not starting due to async death\n", p->env_id);
112                         // There should be no core cleanup to do (like decref).
113                         assert(current != p);
114                         // if we're a worker core, smp_idle, o/w return
115                         // TODO considering encapsulating this block (core_id too)
116                         if (core_id())
117                                 smp_idle(); // this never returns
118                         return;
119                 case (PROC_RUNNABLE_S):
120                         proc_set_state(p, PROC_RUNNING_S);
121                         spin_unlock_irqsave(&p->proc_lock);
122                         // This normally doesn't return, but might error out in the future.
123                         proc_startcore(p, &p->env_tf);
124                         break;
125                 case (PROC_RUNNABLE_M):
126                         // BIG TODO: do this.
127                         // Check for how we're supposed to dispatch this
128                         // Update core map or whatever with what we're about to do
129
130                         /* There a subtle (attempted) race avoidance here.  proc_startcore
131                          * can handle a death IPI, but we can't have the startcore come
132                          * after the death IPI.  Otherwise, it would look like a new
133                          * process.  So we hold the lock to make sure our IPI went out
134                          * before a possible death IPI.  We don't IPI ourselves, since we
135                          * need to let go of the lock.  This could change if we
136                          * process_workqueue in the interrupt handler path and do something
137                          * like light kernel threading, which ties into state bundling.
138                          * Also, we may never allow proc_run to run on a target/worker core.
139                          */
140                         // Send IPIs to everyone else involved
141                         spin_unlock_irqsave(&p->proc_lock);
142                         // if (am_involved)
143                         //      proc_startcore(p, &appropriate_trapframe);
144                         // if not, need to make sure we don't return to the process's core 0
145                         panic("Unimplemented");
146                 default:
147                         spin_unlock_irqsave(&p->proc_lock);
148                         panic("Invalid process state in proc_run()!!");
149         }
150 }
151
152 /*
153  * Runs the given context (trapframe) of process p on the core this code
154  * executes on.  The refcnt tracks how many cores have "an interest" in this
155  * process, which so far just means it uses the process's page table.  See the
156  * massive comments around the incref function
157  *
158  * Given we are RUNNING_*, an IPI for death or preemption could come in:
159  * 1. death attempt (IPI to kill whatever is on your core):
160  *              we don't need to worry about protecting the stack, since we're
161  *              abandoning ship - just need to get a good cr3 and decref current, which
162  *              the death handler will do.
163  *              If a death IPI comes in, we immediately stop this function and will
164  *              never come back.
165  * 2. preempt attempt (IPI to package state and maybe run something else):
166  *              - if a preempt attempt comes in while we're in the kernel, it'll
167  *              just set a flag.  we could attempt to bundle the kernel state
168  *              and rerun it later, but it's really messy (and possibly given
169  *              back to userspace).  we'll disable ints, check this flag, and if
170  *              so, handle the preemption using the same funcs as the normal
171  *              preemption handler.  nonblocking kernel calls will just slow
172  *              down the preemption while they work.  blocking kernel calls will
173  *              need to package their state properly anyway.
174  *
175  * TODO: in general, think about when we no longer need the stack, in case we
176  * are preempted and expected to run again from somewhere else.  we can't
177  * expect to have the kernel stack around anymore.  the nice thing about being
178  * at this point is that we are just about ready to give up the stack anyways.
179  *
180  * I think we need to make it such that the kernel in "process context" never
181  * gets removed from the core (displaced from its stack) without going through
182  * some "bundling" code.
183  */
184 void proc_startcore(struct proc *p, trapframe_t *tf) {
185         // TODO it's possible to be DYING, but it's a rare race.  remove this soon.
186         assert(p->state & (PROC_RUNNING_S | PROC_RUNNING_M));
187         // sucks to have ints disabled when doing env_decref and possibly freeing
188         disable_irq();
189         if (per_cpu_info[core_id()].preempt_pending) {
190                 // TODO: handle preemption
191                 // the functions will need to consider deal with current like down below
192                 panic("Preemption not supported!");
193         }
194         /* If the process wasn't here, then we need to load its address space. */
195         if (p != current) {
196                 if (proc_incref(p))
197                         // getting here would mean someone tried killing this while we tried
198                         // to start one of it's contexts (from scratch, o/w we had it's CR3
199                         // loaded already)
200                         // if this happens, the death-IPI ought to be on its way...  we can
201                         // either wait, or just cleanup_core() and smp_idle.
202                         panic("Proc is dying, handle me!"); // TODO
203                 lcr3(p->env_cr3);
204                 // we unloaded the old cr3, so decref it (if it exists)
205                 // TODO: Consider moving this to wherever we really "mean to leave the
206                 // process's context".
207                 if (current)
208                         proc_decref(current);
209                 current = p;
210         }
211         /* need to load our silly state, preferably somewhere other than here so we
212          * can avoid the case where the context was just running here.  it's not
213          * sufficient to do it in the "new process" if-block above (could be things
214          * like page faults that cause us to keep the same process, but want a
215          * different context.
216          * for now, we load this silly state here. (TODO)
217          * We also need this to be per trapframe, and not per process...
218          */
219         env_pop_ancillary_state(p);
220         env_pop_tf(&p->env_tf);
221 }
222
223 /*
224  * Destroys the given process.  This may be called from another process, a light
225  * kernel thread (no real process context), asynchronously/cross-core, or from
226  * the process on its own core.
227  *
228  * Here's the way process death works:
229  * 0. grab the lock (protects state transition and core map)
230  * 1. set state to dying.  that keeps the kernel from doing anything for the
231  * process (like proc_running it).
232  * 2. figure out where the process is running (cross-core/async or RUNNING_M)
233  * 3. IPI to clean up those cores (decref, etc).
234  * 4. Unlock
235  * 5. Clean up your core, if applicable
236  * (Last core/kernel thread to decref cleans up and deallocates resources.)
237  *
238  * Note that some cores can be processing async calls, but will eventually
239  * decref.  Should think about this more.
240  */
241 void proc_destroy(struct proc *p)
242 {
243         spin_lock_irqsave(&p->proc_lock);
244         // Could save the state and do this outside the lock
245         switch (p->state) {
246                 case PROC_DYING:
247                         return; // someone else killed this already.
248                 case PROC_RUNNABLE_S:
249                 case PROC_RUNNABLE_M:
250                         deschedule_proc(p);
251                         break;
252                 default:
253                         // Think about other lists, or better ways to do this
254         }
255         proc_set_state(p, PROC_DYING);
256         // BIG TODO: check the coremap to find out who needs to die
257         // send the death IPI to everyone else involved
258         spin_unlock_irqsave(&p->proc_lock);
259
260         proc_decref(p); // this decref is for the process in general
261         atomic_dec(&num_envs);
262
263         /*
264          * If we are currently running this address space on our core, we need a
265          * known good pgdir before releasing the old one.  This is currently the
266          * major practical implication of the kernel caring about a processes
267          * existence (the inc and decref).  This decref corresponds to the incref in
268          * proc_startcore (though it's not the only one).
269          */
270         // TODO - probably make this a function, which the death IPI calls
271         if (current == p) {
272                 lcr3(boot_cr3);
273                 proc_decref(p); // this decref is for the cr3
274                 current = NULL;
275         } else {
276                 return;
277         }
278
279         // for old envs that die on user cores.  since env run never returns, cores
280         // never get back to their old hlt/relaxed/spin state, so we need to force
281         // them back to an idle function.
282
283         if (core_id()) {
284                 smp_idle();
285                 panic("should never see me");
286         }
287         // else we're core 0 and can do the usual
288
289         /* Instead of picking a new environment to run, or defaulting to the monitor
290          * like before, for now we'll hop into the manager() function, which
291          * dispatches jobs.  Note that for now we start the manager from the top,
292          * and not from where we left off the last time we called manager.  That
293          * would require us to save some context (and a stack to work on) here.
294          */
295         manager();
296         assert(0); // never get here
297 }
298
299 /*
300  * The process refcnt is the number of places the process 'exists' in the
301  * system.  Creation counts as 1.  Having your page tables loaded somewhere
302  * (lcr3) counts as another 1.  A non-RUNNING_* process should have refcnt at
303  * least 1.  If the kernel is on another core and in a processes address space
304  * (like processing its backring), that counts as another 1.
305  *
306  * Note that the actual loading and unloading of cr3 is up to the caller, since
307  * that's not the only use for this (and decoupling is more flexible).
308  *
309  * The refcnt should always be greater than 0 for processes that aren't dying.
310  * When refcnt is 0, the process is dying and should not allow any more increfs.
311  * A process can be dying with a refcnt greater than 0, since it could be
312  * waiting for other cores to "get the message" to die, or a kernel core can be
313  * finishing work in the processes's address space.
314  *
315  * Implementation aside, the important thing is that we atomically increment
316  * only if it wasn't already 0.  If it was 0, then we shouldn't be attaching to
317  * the process, so we return an error, which should be handled however is
318  * appropriate.  We currently use spinlocks, but some sort of clever atomics
319  * would work too.
320  *
321  * Also, no one should ever update the refcnt outside of these functions.
322  * Eventually, we'll have Ivy support for this. (TODO)
323  */
324 error_t proc_incref(struct proc *p)
325 {
326         error_t retval = 0;
327         spin_lock_irqsave(&p->proc_lock);
328         if (p->env_refcnt)
329                 p->env_refcnt++;
330         else
331                 retval = -EBADENV;
332         spin_unlock_irqsave(&p->proc_lock);
333         return retval;
334 }
335
336 /*
337  * When the kernel is done with a process, it decrements its reference count.
338  * When the count hits 0, no one is using it and it should be freed.
339  * "Last one out" actually finalizes the death of the process.  This is tightly
340  * coupled with the previous function (incref)
341  * Be sure to load a different cr3 before calling this!
342  */
343 void proc_decref(struct proc *p)
344 {
345         spin_lock_irqsave(&p->proc_lock);
346         p->env_refcnt--;
347         spin_unlock_irqsave(&p->proc_lock);
348         // if we hit 0, no one else will increment and we can check outside the lock
349         if (p->env_refcnt == 0)
350                 env_free(p);
351 }