DISABLE_IRQSAVE/ENABLE_IRQRESTORE: Convert to IRQ_SAVE_DISABLE/IRQ_RESTORE.
[bertos.git] / kern / proc.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2001,2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 1999,2000,2001 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \brief Simple realtime multitasking scheduler.
10  *        Context switching is only done cooperatively.
11  *
12  * \version $Id$
13  *
14  * \author Bernardo Innocenti <bernie@develer.com>
15  * \author Stefano Fedrigo <aleph@develer.com>
16  */
17
18 /*#*
19  *#* $Log$
20  *#* Revision 1.23  2004/12/13 12:07:06  bernie
21  *#* DISABLE_IRQSAVE/ENABLE_IRQRESTORE: Convert to IRQ_SAVE_DISABLE/IRQ_RESTORE.
22  *#*
23  *#* Revision 1.22  2004/12/13 11:51:08  bernie
24  *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE.
25  *#*
26  *#* Revision 1.21  2004/11/28 23:20:25  bernie
27  *#* Remove obsolete INITLIST macro.
28  *#*
29  *#* Revision 1.20  2004/11/16 22:37:14  bernie
30  *#* Replace IPTR with iptr_t.
31  *#*
32  *#* Revision 1.19  2004/10/19 11:47:39  bernie
33  *#* Kill warnings when !CONFIG_PROC_MONITOR.
34  *#*
35  *#* Revision 1.18  2004/10/19 08:54:43  bernie
36  *#* Initialize forbid_cnt; Formatting/comments fixes.
37  *#*
38  *#* Revision 1.17  2004/10/19 08:47:13  bernie
39  *#* proc_rename(), proc_forbid(), proc_permit(): New functions.
40  *#*
41  *#* Revision 1.16  2004/10/03 20:39:28  bernie
42  *#* Import changes from sc/firmware.
43  *#*
44  *#* Revision 1.15  2004/09/20 03:29:39  bernie
45  *#* C++ fixes.
46  *#*
47  *#* Revision 1.14  2004/09/14 21:06:44  bernie
48  *#* Use debug.h instead of kdebug.h.
49  *#*
50  *#* Revision 1.13  2004/08/29 21:58:53  bernie
51  *#* Include macros.h explicityl.
52  *#*
53  *#* Revision 1.11  2004/08/24 16:09:08  bernie
54  *#* Add missing header.
55  *#*
56  *#* Revision 1.10  2004/08/24 16:07:01  bernie
57  *#* Use kputs()/kputchar() when possible.
58  *#*
59  *#* Revision 1.9  2004/08/24 14:26:57  bernie
60  *#* monitor_debug_stacks(): Conditionally compile on CONFIG_KERN_MONITOR.
61  *#*
62  *#* Revision 1.8  2004/08/14 19:37:57  rasky
63  *#* Merge da SC: macros.h, pool.h, BIT_CHANGE, nome dei processi, etc.
64  *#*
65  *#* Revision 1.7  2004/08/02 20:20:29  aleph
66  *#* Merge from project_ks
67  *#*
68  *#* Revision 1.6  2004/07/30 14:24:16  rasky
69  *#* Task switching con salvataggio perfetto stato di interrupt (SR)
70  *#* Kernel monitor per dump informazioni su stack dei processi
71  *#*
72  *#* Revision 1.5  2004/07/14 14:18:09  rasky
73  *#* Merge da SC: Rimosso timer dentro il task, che รจ uno spreco di memoria per troppi task
74  *#*
75  *#* Revision 1.4  2004/07/13 19:21:28  aleph
76  *#* Avoid warning for unused arg when compiled without some CONFIG_KERN_xx options
77  *#*
78  *#* Revision 1.3  2004/06/06 18:37:57  bernie
79  *#* Rename event macros to look like regular functions.
80  *#*
81  *#* Revision 1.2  2004/06/03 11:27:09  bernie
82  *#* Add dual-license information.
83  *#*
84  *#* Revision 1.1  2004/05/23 17:27:00  bernie
85  *#* Import kern/ subdirectory.
86  *#*
87  *#*/
88
89 #include "proc_p.h"
90 #include "proc.h"
91 #include "cpu.h"
92 #include "event.h"
93 #include "hw.h"
94 #include <debug.h>
95 #include <arch_config.h>  /* ARCH_EMUL */
96 #include <macros.h>  /* ABS() */
97
98 #include <string.h> /* memset() */
99
100 /*!
101  * CPU dependent context switching routines.
102  *
103  * \note This function *MUST* preserve also the status of the interrupts.
104  */
105 EXTERN_C void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp);
106 EXTERN_C int asm_switch_version(void);
107
108 /*
109  * The scheduer tracks ready and waiting processes
110  * by enqueuing them in these lists. A pointer to the currently
111  * running process is stored in the CurrentProcess pointer.
112  *
113  * NOTE: these variables are protected by DI/EI locking
114  */
115 REGISTER Process *CurrentProcess;
116 REGISTER List     ProcReadyList;
117
118
119 #if CONFIG_KERN_PREEMPTIVE
120 /*
121  * The time sharing scheduler forces a task switch when
122  * the current process has consumed its quantum.
123  */
124 uint16_t Quantum;
125 #endif
126
127
128 /* In Win32 we must emulate stack on the real process stack */
129 #if (ARCH & ARCH_EMUL)
130 extern List StackFreeList;
131 #endif
132
133 /*! The main process (the one that executes main()). */
134 struct Process MainProcess;
135
136
137 static void proc_init_struct(Process *proc)
138 {
139         /* Avoid warning for unused argument. */
140         (void)proc;
141
142 #if CONFIG_KERN_SIGNALS
143         proc->sig_recv = 0;
144 #endif
145
146 #if CONFIG_KERN_PREEMPTIVE
147         proc->forbid_cnt = 0;
148 #endif
149
150 #if CONFIG_KERN_HEAP
151         proc->flags = 0;
152 #endif
153 }
154
155
156 void proc_init(void)
157 {
158         LIST_INIT(&ProcReadyList);
159
160 #if CONFIG_KERN_MONITOR
161         monitor_init();
162 #endif
163
164         /* We "promote" the current context into a real process. The only thing we have
165          * to do is create a PCB and make it current. We don't need to setup the stack
166          * pointer because it will be written the first time we switch to another process.
167          */
168         proc_init_struct(&MainProcess);
169         CurrentProcess = &MainProcess;
170
171         /* Make sure the assembly routine is up-to-date with us */
172         ASSERT(asm_switch_version() == 1);
173 }
174
175
176 /*!
177  * Create a new process, starting at the provided entry point.
178  *
179  * \return Process structure of new created process
180  *         if successful, NULL otherwise.
181  */
182 struct Process *proc_new_with_name(UNUSED(const char*, name), void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack_base)
183 {
184         Process *proc;
185         cpuflags_t flags;
186         size_t i;
187         size_t proc_size_words = ROUND2(sizeof(Process), sizeof(cpustack_t)) / sizeof(cpustack_t);
188 #if CONFIG_KERN_HEAP
189         bool free_stack = false;
190 #endif
191
192 #if (ARCH & ARCH_EMUL)
193         /* Ignore stack provided by caller and use the large enough default instead. */
194         stack_base = (cpustack_t *)StackFreeList.head;
195         REMOVE((Node *)stack_base);
196         stacksize = DEF_STACKSIZE;
197 #elif CONFIG_KERN_HEAP
198         /* Did the caller provide a stack for us? */
199         if (!stack_base)
200         {
201                 /* Did the caller specify the desired stack size? */
202                 if (!stacksize)
203                         stacksize = CONFIG_KERN_DEFSTACKSIZE + sizeof(Process);
204
205                 /* Allocate stack dinamically */
206                 if (!(stack_base = heap_alloc(stacksize)))
207                         return NULL;
208
209                 free_stack = true;
210         }
211 #else
212         /* Stack must have been provided by the user */
213         ASSERT(stack_base);
214         ASSERT(stacksize);
215 #endif
216
217 #if CONFIG_KERN_MONITOR
218         /* Fill-in the stack with a special marker to help debugging */
219         memset(stack_base, CONFIG_KERN_STACKFILLCODE, stacksize / sizeof(cpustack_t));
220 #endif
221
222         /* Initialize the process control block */
223         if (CPU_STACK_GROWS_UPWARD)
224         {
225                 proc = (Process*)stack_base;
226                 proc->stack = stack_base + proc_size_words;
227                 if (CPU_SP_ON_EMPTY_SLOT)
228                         proc->stack++;
229         }
230         else
231         {
232                 proc = (Process*)(stack_base + stacksize / sizeof(cpustack_t) - proc_size_words);
233                 proc->stack = (cpustack_t*)proc;
234                 if (CPU_SP_ON_EMPTY_SLOT)
235                         proc->stack--;
236         }
237
238         proc_init_struct(proc);
239         proc->user_data = data;
240
241 #if CONFIG_KERN_HEAP
242         proc->stack_base = stack_base;
243         proc->stack_size = stack_size;
244         if (free_stack)
245                 proc->flags |= PF_FREESTACK;
246 #endif
247
248         /* Initialize process stack frame */
249         CPU_PUSH_CALL_CONTEXT(proc->stack, proc_exit);
250         CPU_PUSH_CALL_CONTEXT(proc->stack, entry);
251
252         /* Push a clean set of CPU registers for asm_switch_context() */
253         for (i = 0; i < CPU_SAVED_REGS_CNT; i++)
254                 CPU_PUSH_WORD(proc->stack, CPU_REG_INIT_VALUE(i));
255
256         /* Add to ready list */
257         ATOMIC(SCHED_ENQUEUE(proc));
258
259 #if CONFIG_KERN_MONITOR
260         monitor_add(proc, name, stack_base, stacksize);
261 #endif
262
263         return proc;
264 }
265
266 /*! Rename a process */
267 void proc_rename(struct Process *proc, const char *name)
268 {
269 #if CONFIG_KERN_MONITOR
270         monitor_rename(proc, name);
271 #else
272         (void)proc; (void)name;
273 #endif
274 }
275
276
277 /*!
278  * System scheduler: pass CPU control to the next process in
279  * the ready queue.
280  *
281  * Saving and restoring the context on the stack is done
282  * by a CPU-dependent support routine which must usually be
283  * written in assembly.
284  */
285 void proc_schedule(void)
286 {
287         /* This function must not have any "auto" variables, otherwise
288          * the compiler might put them on the stack of the process
289          * being switched out.
290          */
291         static struct Process *old_process;
292         static cpuflags_t flags;
293
294         /* Remember old process to save its context later */
295         old_process = CurrentProcess;
296
297         /* Poll on the ready queue for the first ready process */
298         IRQ_SAVE_DISABLE(flags);
299         while (!(CurrentProcess = (struct Process *)REMHEAD(&ProcReadyList)))
300         {
301                 /*
302                  * Make sure we physically reenable interrupts here, no matter what
303                  * the current task status is. This is important because if we
304                  * are idle-spinning, we must allow interrupts, otherwise no
305                  * process will ever wake up.
306                  *
307                  * \todo If there was a way to write sig_wait() so that it does not
308                  * disable interrupts while waiting, there would not be any
309                  * reason to do this.
310                  */
311                 IRQ_ENABLE;
312                 SCHEDULER_IDLE;
313                 IRQ_DISABLE;
314         }
315         IRQ_RESTORE(flags);
316
317         /*
318          * Optimization: don't switch contexts when the active
319          * process has not changed.
320          */
321         if (CurrentProcess != old_process)
322         {
323                 static cpustack_t *dummy;
324
325 #if CONFIG_KERN_PREEMPTIVE
326                 /* Reset quantum for this process */
327                 Quantum = CONFIG_KERN_QUANTUM;
328 #endif
329
330                 /* Save context of old process and switch to new process. If there is no
331                  * old process, we save the old stack pointer into a dummy variable that
332                  * we ignore. In fact, this happens only when the old process has just
333                  * exited.
334                  * TODO: Instead of physically clearing the process at exit time, a zombie
335                  * list should be created.
336                  */
337                 asm_switch_context(&CurrentProcess->stack, old_process ? &old_process->stack : &dummy);
338         }
339
340         /* This RET resumes the execution on the new process */
341 }
342
343
344 /*!
345  * Terminate the current process
346  */
347 void proc_exit(void)
348 {
349 #if CONFIG_KERN_HEAP
350         /* The following code is BROKEN.
351          * We are freeing our own stack before entering proc_schedule()
352          * BAJO: A correct fix would be to rearrange the scheduler with
353          *  an additional parameter which frees the old stack/process
354          *  after a context switch.
355          */
356         if (CurrentProcess->flags & PF_FREESTACK)
357                 heap_free(CurrentProcess->stack_base, CurrentProcess->stack_size);
358         heap_free(CurrentProcess);
359 #endif
360
361 #if (ARCH & ARCH_EMUL)
362 #error This is wrong
363         /* Reinsert process stack in free list */
364         ADDHEAD(&StackFreeList, (Node *)(CurrentProcess->stack
365                 - (DEF_STACKSIZE / sizeof(cpustack_t))));
366
367         /* NOTE: At this point the first two words of what used
368          * to be our stack contain a list node. From now on, we
369          * rely on the compiler not reading/writing the stack.
370          */
371 #endif /* ARCH_EMUL */
372
373 #if CONFIG_KERN_MONITOR
374         monitor_remove(CurrentProcess);
375 #endif
376
377         CurrentProcess = NULL;
378         proc_schedule();
379         /* not reached */
380 }
381
382
383 /*!
384  * Co-operative context switch
385  */
386 void proc_switch(void)
387 {
388         /* Just like proc_schedule, this function must not have auto variables. */
389         static cpuflags_t flags;
390
391         IRQ_SAVE_DISABLE(flags);
392         SCHED_ENQUEUE(CurrentProcess);
393         IRQ_RESTORE(flags);
394
395         proc_schedule();
396 }
397
398
399 /*!
400  * Get the pointer to the current process
401  */
402 struct Process *proc_current(void)
403 {
404         return CurrentProcess;
405 }
406
407 /*!
408  * Get the pointer to the user data of the current process
409  */
410 iptr_t proc_current_user_data(void)
411 {
412         return CurrentProcess->user_data;
413 }
414
415
416 #if CONFIG_KERN_PREEMPTIVE
417
418 /*!
419  * Disable preemptive task switching.
420  *
421  * The scheduler maintains a per-process nesting counter.  Task switching is
422  * effectively re-enabled only when the number of calls to proc_permit()
423  * matches the number of calls to proc_forbid().
424  *
425  * Calling functions that could sleep while task switching is disabled
426  * is dangerous, although supported.  Preemptive task switching is
427  * resumed while the process is sleeping and disabled again as soon as
428  * it wakes up again.
429  *
430  * \sa proc_permit()
431  */
432 void proc_forbid(void)
433 {
434         /* No need to protect against interrupts here. */
435         ++CurrentProcess->forbid_cnt;
436 }
437
438 /*!
439  * Re-enable preemptive task switching.
440  *
441  * \sa proc_forbid()
442  */
443 void proc_permit(void)
444 {
445         /* No need to protect against interrupts here. */
446         --CurrentProcess->forbid_cnt;
447 }
448
449 #endif /* CONFIG_KERN_PREEMPTIVE */
450
451
452 #if 0 /* Simple testcase for the scheduler */
453
454 #include <drv/timer.h>
455
456 /*!
457  * Proc scheduling test subthread 1
458  */
459 static void NORETURN proc_test_thread1(void)
460 {
461         for (;;)
462         {
463                 kputs(">task 1\n");
464                 timer_delay(50);
465                 proc_switch();
466         }
467 }
468
469 /*!
470  * Proc scheduling test subthread 2
471  */
472 static void NORETURN proc_test_thread2(void)
473 {
474         for (;;)
475         {
476                 kputs(">task 2\n");
477                 timer_delay(75);
478                 proc_switch();
479         }
480 }
481
482 static cpustack_t proc_test_stack1[CONFIG_KERN_DEFSTACKSIZE/sizeof(cpustack_t)];
483 static cpustack_t proc_test_stack2[CONFIG_KERN_DEFSTACKSIZE/sizeof(cpustack_t)];
484
485 /*!
486  * Proc scheduling test
487  */
488 void NORETURN proc_test(void)
489 {
490         proc_new(proc_test_thread1, NULL, sizeof(proc_test_stack1), proc_test_stack1);
491         proc_new(proc_test_thread2, NULL, sizeof(proc_test_stack2), proc_test_stack2);
492         kputs("Created tasks\n");
493
494         kputs("stack1:\n");
495         kdump(proc_test_stack1+sizeof(proc_test_stack1)-64, 64);
496         kputs("stack2:\n");
497         kdump(proc_test_stack2+sizeof(proc_test_stack1)-64, 64);
498
499         for (;;)
500         {
501                 kputs(">main task\n");
502                 timer_delay(93);
503                 proc_switch();
504         }
505
506         ASSERT(false);
507 }
508 #endif