proc.c
Go to the documentation of this file.00001
00039 #include "proc_p.h"
00040 #include "proc.h"
00041
00042 #include "cfg/cfg_proc.h"
00043 #define LOG_LEVEL KERN_LOG_LEVEL
00044 #define LOG_FORMAT KERN_LOG_FORMAT
00045 #include <cfg/log.h>
00046
00047 #include "cfg/cfg_monitor.h"
00048 #include <cfg/macros.h>
00049 #include <cfg/module.h>
00050 #include <cfg/depend.h>
00051
00052 #include <cpu/irq.h>
00053 #include <cpu/types.h>
00054 #include <cpu/attr.h>
00055 #include <cpu/frame.h>
00056
00057 #if CONFIG_KERN_HEAP
00058 #include <struct/heap.h>
00059 #endif
00060
00061 #include <string.h>
00062
00063 #define PROC_SIZE_WORDS (ROUND_UP2(sizeof(Process), sizeof(cpu_stack_t)) / sizeof(cpu_stack_t))
00064
00065
00066
00067
00068
00069
00070
00071 REGISTER List proc_ready_list;
00072
00073
00074
00075
00076
00077
00078 REGISTER Process *current_process;
00079
00081 static struct Process main_process;
00082
00083 #if CONFIG_KERN_HEAP
00084
00088 static HEAP_DEFINE_BUF(heap_buf, CONFIG_KERN_HEAP_SIZE);
00089 static Heap proc_heap;
00090
00091
00092
00093
00094
00095
00096
00097 static List zombie_list;
00098
00099 #endif
00100
00101 static void proc_initStruct(Process *proc)
00102 {
00103
00104 (void)proc;
00105
00106 #if CONFIG_KERN_SIGNALS
00107 proc->sig_recv = 0;
00108 proc->sig_wait = 0;
00109 #endif
00110
00111 #if CONFIG_KERN_HEAP
00112 proc->flags = 0;
00113 #endif
00114
00115 #if CONFIG_KERN_PRI
00116 proc->link.pri = 0;
00117 #endif
00118 }
00119
00120 MOD_DEFINE(proc);
00121
00122 void proc_init(void)
00123 {
00124 LIST_INIT(&proc_ready_list);
00125
00126 #if CONFIG_KERN_HEAP
00127 LIST_INIT(&zombie_list);
00128 heap_init(&proc_heap, heap_buf, sizeof(heap_buf));
00129 #endif
00130
00131
00132
00133
00134
00135 proc_initStruct(&main_process);
00136 current_process = &main_process;
00137
00138 #if CONFIG_KERN_MONITOR
00139 monitor_init();
00140 monitor_add(current_process, "main");
00141 #endif
00142 MOD_INIT(proc);
00143 }
00144
00145
00146 #if CONFIG_KERN_HEAP
00147
00152 static void proc_freeZombies(void)
00153 {
00154 Process *proc;
00155
00156 while (1)
00157 {
00158 PROC_ATOMIC(proc = (Process *)list_remHead(&zombie_list));
00159 if (proc == NULL)
00160 return;
00161
00162 if (proc->flags & PF_FREESTACK)
00163 {
00164 PROC_ATOMIC(heap_freemem(&proc_heap, proc->stack_base,
00165 proc->stack_size + PROC_SIZE_WORDS * sizeof(cpu_stack_t)));
00166 }
00167 }
00168 }
00169
00173 static void proc_addZombie(Process *proc)
00174 {
00175 Node *node;
00176 #if CONFIG_KERN_PREEMPT
00177 ASSERT(!proc_preemptAllowed());
00178 #endif
00179
00180 #if CONFIG_KERN_PRI
00181 node = &(proc)->link.link;
00182 #else
00183 node = &(proc)->link;
00184 #endif
00185 LIST_ASSERT_VALID(&zombie_list);
00186 ADDTAIL(&zombie_list, node);
00187 }
00188
00189 #endif
00190
00205 struct Process *proc_new_with_name(UNUSED_ARG(const char *, name), void (*entry)(void), iptr_t data, size_t stack_size, cpu_stack_t *stack_base)
00206 {
00207 Process *proc;
00208 LOG_INFO("name=%s", name);
00209 #if CONFIG_KERN_HEAP
00210 bool free_stack = false;
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 proc_freeZombies();
00227
00228
00229 if (!stack_base)
00230 {
00231
00232 if (!stack_size)
00233 stack_size = KERN_MINSTACKSIZE;
00234
00235
00236 PROC_ATOMIC(stack_base =
00237 (cpu_stack_t *)heap_allocmem(&proc_heap, stack_size));
00238 if (stack_base == NULL)
00239 return NULL;
00240
00241 free_stack = true;
00242 }
00243
00244 #else // CONFIG_KERN_HEAP
00245
00246
00247 ASSERT_VALID_PTR(stack_base);
00248 ASSERT(stack_size);
00249
00250 #endif // CONFIG_KERN_HEAP
00251
00252 #if CONFIG_KERN_MONITOR
00253
00254
00255
00256
00257
00258
00259 memset(stack_base, (int)CONFIG_KERN_STACKFILLCODE, stack_size);
00260 #endif
00261
00262
00263 if (CPU_STACK_GROWS_UPWARD)
00264 {
00265 proc = (Process *)stack_base;
00266 proc->stack = stack_base + PROC_SIZE_WORDS;
00267
00268 proc->stack = (cpu_stack_t *)((uintptr_t)proc->stack + (sizeof(cpu_aligned_stack_t) - ((uintptr_t)proc->stack % sizeof(cpu_aligned_stack_t))));
00269 if (CPU_SP_ON_EMPTY_SLOT)
00270 proc->stack++;
00271 }
00272 else
00273 {
00274 proc = (Process *)(stack_base + stack_size / sizeof(cpu_stack_t) - PROC_SIZE_WORDS);
00275
00276 proc->stack = (cpu_stack_t *)((uintptr_t)proc - ((uintptr_t)proc % sizeof(cpu_aligned_stack_t)));
00277 if (CPU_SP_ON_EMPTY_SLOT)
00278 proc->stack--;
00279 }
00280
00281 ASSERT((uintptr_t)proc->stack % sizeof(cpu_aligned_stack_t) == 0);
00282
00283 stack_size -= PROC_SIZE_WORDS * sizeof(cpu_stack_t);
00284 proc_initStruct(proc);
00285 proc->user_data = data;
00286
00287 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR
00288 proc->stack_base = stack_base;
00289 proc->stack_size = stack_size;
00290 #if CONFIG_KERN_HEAP
00291 if (free_stack)
00292 proc->flags |= PF_FREESTACK;
00293 #endif
00294 #endif
00295 proc->user_entry = entry;
00296 CPU_CREATE_NEW_STACK(proc->stack);
00297
00298 #if CONFIG_KERN_MONITOR
00299 monitor_add(proc, name);
00300 #endif
00301
00302
00303 ATOMIC(SCHED_ENQUEUE(proc));
00304
00305 return proc;
00306 }
00307
00313 const char *proc_name(struct Process *proc)
00314 {
00315 #if CONFIG_KERN_MONITOR
00316 return proc ? proc->monitor.name : "<NULL>";
00317 #else
00318 (void)proc;
00319 return "---";
00320 #endif
00321 }
00322
00324 const char *proc_currentName(void)
00325 {
00326 return proc_name(proc_current());
00327 }
00328
00330 void proc_rename(struct Process *proc, const char *name)
00331 {
00332 #if CONFIG_KERN_MONITOR
00333 monitor_rename(proc, name);
00334 #else
00335 (void)proc; (void)name;
00336 #endif
00337 }
00338
00339
00340 #if CONFIG_KERN_PRI
00341
00360 void proc_setPri(struct Process *proc, int pri)
00361 {
00362 if (proc->link.pri == pri)
00363 return;
00364
00365 proc->link.pri = pri;
00366
00367 if (proc != current_process)
00368 ATOMIC(sched_reenqueue(proc));
00369 }
00370 #endif // CONFIG_KERN_PRI
00371
00372 INLINE void proc_run(void)
00373 {
00374 void (*entry)(void) = current_process->user_entry;
00375
00376 LOG_INFO("New process starting at %p", entry);
00377 entry();
00378 }
00379
00383 void proc_entry(void)
00384 {
00385
00386
00387
00388
00389 IRQ_ENABLE;
00390
00391 proc_run();
00392 proc_exit();
00393 }
00394
00398 void proc_exit(void)
00399 {
00400 LOG_INFO("%p:%s", current_process, proc_currentName());
00401
00402 #if CONFIG_KERN_MONITOR
00403 monitor_remove(current_process);
00404 #endif
00405
00406 proc_forbid();
00407 #if CONFIG_KERN_HEAP
00408
00409
00410
00411
00412 proc_addZombie(current_process);
00413 #endif
00414 current_process = NULL;
00415 proc_permit();
00416
00417 proc_switch();
00418
00419
00420 ASSERT(0);
00421 }
00422
00426 void proc_schedule(void)
00427 {
00428 Process *old_process = current_process;
00429
00430 IRQ_ASSERT_DISABLED();
00431
00432
00433 LIST_ASSERT_VALID(&proc_ready_list);
00434 while (!(current_process = (struct Process *)list_remHead(&proc_ready_list)))
00435 {
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 IRQ_ENABLE;
00452 CPU_IDLE;
00453 MEMORY_BARRIER;
00454 IRQ_DISABLE;
00455 }
00456 proc_switchTo(current_process, old_process);
00457
00458 LOG_INFO("resuming %p:%s\n", current_process, proc_currentName());
00459 }