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