proc.c
Go to the documentation of this file.00001
00040 #include "proc_p.h"
00041 #include "proc.h"
00042
00043 #include "cfg/cfg_proc.h"
00044 #define LOG_LEVEL KERN_LOG_LEVEL
00045 #define LOG_FORMAT KERN_LOG_FORMAT
00046 #include <cfg/log.h>
00047
00048 #include "cfg/cfg_arch.h"
00049 #include "cfg/cfg_monitor.h"
00050 #include <cfg/macros.h>
00051 #include <cfg/module.h>
00052 #include <cfg/depend.h>
00053
00054 #include <cpu/irq.h>
00055 #include <cpu/types.h>
00056 #include <cpu/attr.h>
00057 #include <cpu/frame.h>
00058
00059 #if CONFIG_KERN_HEAP
00060 #include <struct/heap.h>
00061 #endif
00062
00063 #include <string.h>
00064
00065
00066
00067
00068
00069
00070
00071 REGISTER List ProcReadyList;
00072
00073
00074
00075
00076
00077
00078 REGISTER Process *CurrentProcess;
00079
00080 #if (ARCH & ARCH_EMUL)
00081
00082
00083
00084
00085
00086
00087
00088 List StackFreeList;
00089
00090 #define NPROC 10
00091 cpu_stack_t proc_stacks[NPROC][(64 * 1024) / sizeof(cpu_stack_t)];
00092 #endif
00093
00095 struct Process MainProcess;
00096
00097
00098 static void proc_init_struct(Process *proc)
00099 {
00100
00101 (void)proc;
00102
00103 #if CONFIG_KERN_SIGNALS
00104 proc->sig_recv = 0;
00105 proc->sig_wait = 0;
00106 #endif
00107
00108 #if CONFIG_KERN_HEAP
00109 proc->flags = 0;
00110 #endif
00111
00112 #if CONFIG_KERN_PRI
00113 proc->link.pri = 0;
00114 #endif
00115
00116 }
00117
00118 MOD_DEFINE(proc);
00119
00120 void proc_init(void)
00121 {
00122 LIST_INIT(&ProcReadyList);
00123
00124 #if ARCH & ARCH_EMUL
00125 LIST_INIT(&StackFreeList);
00126 for (int i = 0; i < NPROC; i++)
00127 ADDTAIL(&StackFreeList, (Node *)proc_stacks[i]);
00128 #endif
00129
00130
00131
00132
00133
00134
00135 proc_init_struct(&MainProcess);
00136 CurrentProcess = &MainProcess;
00137
00138 #if CONFIG_KERN_MONITOR
00139 monitor_init();
00140 monitor_add(CurrentProcess, "main");
00141 #endif
00142
00143 #if CONFIG_KERN_PREEMPT
00144 preempt_init();
00145 #endif
00146
00147 MOD_INIT(proc);
00148 }
00149
00164 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)
00165 {
00166 Process *proc;
00167 const size_t PROC_SIZE_WORDS = ROUND_UP2(sizeof(Process), sizeof(cpu_stack_t)) / sizeof(cpu_stack_t);
00168 #if CONFIG_KERN_HEAP
00169 bool free_stack = false;
00170 #endif
00171 LOG_INFO("name=%s", name);
00172
00173 #if (ARCH & ARCH_EMUL)
00174
00175 PROC_ATOMIC(stack_base = (cpu_stack_t *)list_remHead(&StackFreeList));
00176 ASSERT(stack_base);
00177
00178 stack_size = KERN_MINSTACKSIZE;
00179 #elif CONFIG_KERN_HEAP
00180
00181 if (!stack_base)
00182 {
00183
00184 if (!stack_size)
00185 stack_size = KERN_MINSTACKSIZE;
00186
00187
00188 if (!(stack_base = heap_alloc(stack_size)))
00189 return NULL;
00190
00191 free_stack = true;
00192 }
00193
00194 #else // !ARCH_EMUL && !CONFIG_KERN_HEAP
00195
00196
00197 ASSERT_VALID_PTR(stack_base);
00198 ASSERT(stack_size);
00199
00200 #endif // !ARCH_EMUL && !CONFIG_KERN_HEAP
00201
00202 #if CONFIG_KERN_MONITOR
00203
00204
00205
00206
00207
00208
00209 memset(stack_base, (int)CONFIG_KERN_STACKFILLCODE, stack_size);
00210 #endif
00211
00212
00213 if (CPU_STACK_GROWS_UPWARD)
00214 {
00215 proc = (Process *)stack_base;
00216 proc->stack = stack_base + PROC_SIZE_WORDS;
00217
00218 proc->stack = (cpu_stack_t *)((uintptr_t)proc->stack + (sizeof(cpu_aligned_stack_t) - ((uintptr_t)proc->stack % sizeof(cpu_aligned_stack_t))));
00219 if (CPU_SP_ON_EMPTY_SLOT)
00220 proc->stack++;
00221 }
00222 else
00223 {
00224 proc = (Process *)(stack_base + stack_size / sizeof(cpu_stack_t) - PROC_SIZE_WORDS);
00225
00226 proc->stack = (cpu_stack_t *)((uintptr_t)proc - ((uintptr_t)proc % sizeof(cpu_aligned_stack_t)));
00227 if (CPU_SP_ON_EMPTY_SLOT)
00228 proc->stack--;
00229 }
00230
00231 ASSERT((uintptr_t)proc->stack % sizeof(cpu_aligned_stack_t) == 0);
00232
00233 stack_size -= PROC_SIZE_WORDS * sizeof(cpu_stack_t);
00234 proc_init_struct(proc);
00235 proc->user_data = data;
00236
00237 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR | (ARCH & ARCH_EMUL)
00238 proc->stack_base = stack_base;
00239 proc->stack_size = stack_size;
00240 #if CONFIG_KERN_HEAP
00241 if (free_stack)
00242 proc->flags |= PF_FREESTACK;
00243 #endif
00244 #endif
00245
00246 #if CONFIG_KERN_PREEMPT
00247
00248 getcontext(&proc->context);
00249 proc->context.uc_stack.ss_sp = proc->stack;
00250 proc->context.uc_stack.ss_size = stack_size - 1;
00251 proc->context.uc_link = NULL;
00252 makecontext(&proc->context, (void (*)(void))proc_entry, 1, entry);
00253
00254 #else // !CONFIG_KERN_PREEMPT
00255
00256 CPU_CREATE_NEW_STACK(proc->stack, entry, proc_exit);
00257
00258 #endif // CONFIG_KERN_PREEMPT
00259
00260 #if CONFIG_KERN_MONITOR
00261 monitor_add(proc, name);
00262 #endif
00263
00264
00265 ATOMIC(SCHED_ENQUEUE(proc));
00266
00267 return proc;
00268 }
00269
00275 const char *proc_name(struct Process *proc)
00276 {
00277 #if CONFIG_KERN_MONITOR
00278 return proc ? proc->monitor.name : "<NULL>";
00279 #else
00280 (void)proc;
00281 return "---";
00282 #endif
00283 }
00284
00286 const char *proc_currentName(void)
00287 {
00288 return proc_name(proc_current());
00289 }
00290
00292 void proc_rename(struct Process *proc, const char *name)
00293 {
00294 #if CONFIG_KERN_MONITOR
00295 monitor_rename(proc, name);
00296 #else
00297 (void)proc; (void)name;
00298 #endif
00299 }
00300
00301
00302 #if CONFIG_KERN_PRI
00303
00322 void proc_setPri(struct Process *proc, int pri)
00323 {
00324 if (proc->link.pri == pri)
00325 return;
00326
00327 proc->link.pri = pri;
00328
00329 if (proc != CurrentProcess)
00330 {
00331 proc_forbid();
00332 ATOMIC(sched_reenqueue(proc));
00333 proc_permit();
00334 }
00335 }
00336 #endif // CONFIG_KERN_PRI
00337
00341 void proc_exit(void)
00342 {
00343 LOG_INFO("%p:%s", CurrentProcess, proc_currentName());
00344
00345 #if CONFIG_KERN_MONITOR
00346 monitor_remove(CurrentProcess);
00347 #endif
00348
00349 #if CONFIG_KERN_HEAP
00350
00351
00352
00353
00354
00355
00356
00357 if (CurrentProcess->flags & PF_FREESTACK)
00358 heap_free(CurrentProcess->stack_base, CurrentProcess->stack_size);
00359 heap_free(CurrentProcess);
00360 #endif
00361
00362 #if (ARCH & ARCH_EMUL)
00363
00364 PROC_ATOMIC(ADDHEAD(&StackFreeList, (Node *)CurrentProcess->stack_base));
00365
00366
00367
00368
00369
00370
00371 #endif
00372
00373 CurrentProcess = NULL;
00374 proc_switch();
00375
00376 }
00377
00378
00382 iptr_t proc_currentUserData(void)
00383 {
00384 return CurrentProcess->user_data;
00385 }