proc.c
Go to the documentation of this file.00001
00044 #include "proc_p.h"
00045 #include "proc.h"
00046
00047 #include <mware/event.h>
00048 #include <cpu/irq.h>
00049 #include <cpu/types.h>
00050 #include <cpu/attr.h>
00051 #include <cfg/debug.h>
00052 #include <cfg/module.h>
00053 #include <cfg/arch_config.h>
00054 #include <cfg/macros.h>
00055
00056 #include <string.h>
00057
00063 EXTERN_C void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp);
00064 EXTERN_C int asm_switch_version(void);
00065
00066
00067
00068
00069
00070
00071
00072
00073 REGISTER Process *CurrentProcess;
00074 REGISTER List ProcReadyList;
00075
00076
00077 #if CONFIG_KERN_PREEMPTIVE
00078
00079
00080
00081
00082 uint16_t Quantum;
00083 #endif
00084
00085
00086
00087 #if (ARCH & ARCH_EMUL)
00088 extern List StackFreeList;
00089 #endif
00090
00092 struct Process MainProcess;
00093
00094
00095 static void proc_init_struct(Process *proc)
00096 {
00097
00098 (void)proc;
00099
00100 #if CONFIG_KERN_SIGNALS
00101 proc->sig_recv = 0;
00102 #endif
00103
00104 #if CONFIG_KERN_PREEMPTIVE
00105 proc->forbid_cnt = 0;
00106 #endif
00107
00108 #if CONFIG_KERN_HEAP
00109 proc->flags = 0;
00110 #endif
00111 }
00112
00113 MOD_DEFINE(proc);
00114
00115 void proc_init(void)
00116 {
00117 LIST_INIT(&ProcReadyList);
00118
00119 #if CONFIG_KERN_MONITOR
00120 monitor_init();
00121 #endif
00122
00123
00124
00125
00126
00127 proc_init_struct(&MainProcess);
00128 CurrentProcess = &MainProcess;
00129
00130
00131 ASSERT(asm_switch_version() == 1);
00132 MOD_INIT(proc);
00133 }
00134
00135
00142 struct Process *proc_new_with_name(UNUSED(const char *, name), void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack_base)
00143 {
00144 Process *proc;
00145 size_t i;
00146 size_t proc_size_words = ROUND2(sizeof(Process), sizeof(cpustack_t)) / sizeof(cpustack_t);
00147 #if CONFIG_KERN_HEAP
00148 bool free_stack = false;
00149 #endif
00150
00151 #if (ARCH & ARCH_EMUL)
00152
00153 stack_base = (cpustack_t *)LIST_HEAD(&StackFreeList);
00154 REMOVE(LIST_HEAD(&StackFreeList));
00155 stacksize = CONFIG_PROC_DEFSTACKSIZE;
00156 #elif CONFIG_KERN_HEAP
00157
00158 if (!stack_base)
00159 {
00160
00161 if (!stacksize)
00162 stacksize = CONFIG_PROC_DEFSTACKSIZE + sizeof(Process);
00163
00164
00165 if (!(stack_base = heap_alloc(stacksize)))
00166 return NULL;
00167
00168 free_stack = true;
00169 }
00170 #else
00171
00172 ASSERT(stack_base);
00173 ASSERT(stacksize);
00174 #endif
00175
00176 #if CONFIG_KERN_MONITOR
00177
00178 memset(stack_base, CONFIG_KERN_STACKFILLCODE, stacksize / sizeof(cpustack_t));
00179 #endif
00180
00181
00182 if (CPU_STACK_GROWS_UPWARD)
00183 {
00184 proc = (Process*)stack_base;
00185 proc->stack = stack_base + proc_size_words;
00186 if (CPU_SP_ON_EMPTY_SLOT)
00187 proc->stack++;
00188 }
00189 else
00190 {
00191 proc = (Process*)(stack_base + stacksize / sizeof(cpustack_t) - proc_size_words);
00192 proc->stack = (cpustack_t*)proc;
00193 if (CPU_SP_ON_EMPTY_SLOT)
00194 proc->stack--;
00195 }
00196
00197 proc_init_struct(proc);
00198 proc->user_data = data;
00199
00200 #if CONFIG_KERN_HEAP
00201 proc->stack_base = stack_base;
00202 proc->stack_size = stack_size;
00203 if (free_stack)
00204 proc->flags |= PF_FREESTACK;
00205 #endif
00206
00207
00208 CPU_PUSH_CALL_CONTEXT(proc->stack, proc_exit);
00209 CPU_PUSH_CALL_CONTEXT(proc->stack, entry);
00210
00211
00212 for (i = 0; i < CPU_SAVED_REGS_CNT; i++)
00213 CPU_PUSH_WORD(proc->stack, CPU_REG_INIT_VALUE(i));
00214
00215
00216 ATOMIC(SCHED_ENQUEUE(proc));
00217
00218 #if CONFIG_KERN_MONITOR
00219 monitor_add(proc, name, stack_base, stacksize);
00220 #endif
00221
00222 return proc;
00223 }
00224
00226 void proc_rename(struct Process *proc, const char *name)
00227 {
00228 #if CONFIG_KERN_MONITOR
00229 monitor_rename(proc, name);
00230 #else
00231 (void)proc; (void)name;
00232 #endif
00233 }
00234
00235
00244 void proc_schedule(void)
00245 {
00246 struct Process *old_process;
00247 cpuflags_t flags;
00248
00249
00250 old_process = CurrentProcess;
00251
00252 #ifdef IRQ_RUNNING
00253
00254 ASSERT(!IRQ_RUNNING());
00255 #endif
00256
00257
00258 IRQ_SAVE_DISABLE(flags);
00259 while (!(CurrentProcess = (struct Process *)list_remHead(&ProcReadyList)))
00260 {
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 IRQ_ENABLE;
00277 CPU_IDLE;
00278 MEMORY_BARRIER;
00279 IRQ_DISABLE;
00280 }
00281 IRQ_RESTORE(flags);
00282
00283
00284
00285
00286
00287 if (CurrentProcess != old_process)
00288 {
00289 cpustack_t *dummy;
00290
00291 #if CONFIG_KERN_PREEMPTIVE
00292
00293 Quantum = CONFIG_KERN_QUANTUM;
00294 #endif
00295
00296
00297
00298
00299
00300
00301
00302
00303 asm_switch_context(&CurrentProcess->stack, old_process ? &old_process->stack : &dummy);
00304 }
00305
00306
00307 }
00308
00309
00313 void proc_exit(void)
00314 {
00315 #if CONFIG_KERN_MONITOR
00316 monitor_remove(CurrentProcess);
00317 #endif
00318
00319 #if CONFIG_KERN_HEAP
00320
00321
00322
00323
00324
00325
00326
00327 if (CurrentProcess->flags & PF_FREESTACK)
00328 heap_free(CurrentProcess->stack_base, CurrentProcess->stack_size);
00329 heap_free(CurrentProcess);
00330 #endif
00331
00332 #if (ARCH & ARCH_EMUL)
00333 #warning This is wrong
00334
00335 ADDHEAD(&StackFreeList, (Node *)(CurrentProcess->stack
00336 - (CONFIG_PROC_DEFSTACKSIZE / sizeof(cpustack_t))));
00337
00338
00339
00340
00341
00342
00343 #endif
00344
00345 CurrentProcess = NULL;
00346 proc_schedule();
00347
00348 }
00349
00350
00354 void proc_switch(void)
00355 {
00356 cpuflags_t flags;
00357
00358 IRQ_SAVE_DISABLE(flags);
00359 SCHED_ENQUEUE(CurrentProcess);
00360 IRQ_RESTORE(flags);
00361
00362 proc_schedule();
00363 }
00364
00365
00369 struct Process *proc_current(void)
00370 {
00371 return CurrentProcess;
00372 }
00373
00377 iptr_t proc_current_user_data(void)
00378 {
00379 return CurrentProcess->user_data;
00380 }
00381
00382
00383 #if CONFIG_KERN_PREEMPTIVE
00384
00399 void proc_forbid(void)
00400 {
00401
00402 ++CurrentProcess->forbid_cnt;
00403 }
00404
00410 void proc_permit(void)
00411 {
00412
00413 --CurrentProcess->forbid_cnt;
00414 }
00415
00416 #endif