proc.h
Go to the documentation of this file.
00001 00092 #ifndef KERN_PROC_H 00093 #define KERN_PROC_H 00094 00095 #include "cfg/cfg_proc.h" 00096 #include "cfg/cfg_signal.h" 00097 #include "cfg/cfg_monitor.h" 00098 #include "sem.h" 00099 00100 #include <struct/list.h> // Node, PriNode 00101 00102 #include <cfg/compiler.h> 00103 #include <cfg/debug.h> // ASSERT() 00104 00105 #include <cpu/types.h> // cpu_stack_t 00106 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT 00107 00108 /* The following silents warnings on nightly tests. We need to regenerate 00109 * all the projects before this can be removed. 00110 */ 00111 #ifndef CONFIG_KERN_PRI_INHERIT 00112 #define CONFIG_KERN_PRI_INHERIT 0 00113 #endif 00114 00115 /* 00116 * WARNING: struct Process is considered private, so its definition can change any time 00117 * without notice. DO NOT RELY on any field defined here, use only the interface 00118 * functions below. 00119 * 00120 * You have been warned. 00121 */ 00122 typedef struct Process 00123 { 00124 #if CONFIG_KERN_PRI 00125 PriNode link; 00126 # if CONFIG_KERN_PRI_INHERIT 00127 PriNode inh_link; 00128 List inh_list; 00129 Semaphore *inh_blocked_by; 00130 int orig_pri; 00131 # endif 00132 #else 00133 Node link; 00134 #endif 00135 cpu_stack_t *stack; 00136 iptr_t user_data; 00138 #if CONFIG_KERN_SIGNALS 00139 Signal sig; 00140 #endif 00141 00142 #if CONFIG_KERN_HEAP 00143 uint16_t flags; 00144 #endif 00145 00146 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR 00147 cpu_stack_t *stack_base; 00148 size_t stack_size; 00149 #endif 00150 00151 /* The actual process entry point */ 00152 void (*user_entry)(void); 00153 00154 #if CONFIG_KERN_MONITOR 00155 struct ProcMonitor 00156 { 00157 Node link; 00158 const char *name; 00159 } monitor; 00160 #endif 00161 00162 } Process; 00163 00168 void proc_init(void); 00169 00170 struct Process *proc_new_with_name(const char *name, void (*entry)(void), iptr_t data, size_t stacksize, cpu_stack_t *stack); 00171 00172 #if !CONFIG_KERN_MONITOR 00173 00192 #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack)) 00193 #else 00194 #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack)) 00195 #endif 00196 00200 void proc_exit(void); 00201 00202 /* 00203 * Public scheduling class methods. 00204 */ 00205 void proc_yield(void); 00206 00207 #if CONFIG_KERN_PREEMPT 00208 bool proc_needPreempt(void); 00209 void proc_preempt(void); 00210 #else 00211 INLINE bool proc_needPreempt(void) 00212 { 00213 return false; 00214 } 00215 00216 INLINE void proc_preempt(void) 00217 { 00218 } 00219 #endif 00220 00221 void proc_rename(struct Process *proc, const char *name); 00222 const char *proc_name(struct Process *proc); 00223 const char *proc_currentName(void); 00224 00232 INLINE iptr_t proc_currentUserData(void) 00233 { 00234 extern struct Process *current_process; 00235 return current_process->user_data; 00236 } 00237 00238 int proc_testSetup(void); 00239 int proc_testRun(void); 00240 int proc_testTearDown(void); 00241 00249 INLINE struct Process *proc_current(void) 00250 { 00251 extern struct Process *current_process; 00252 return current_process; 00253 } 00254 00255 #if CONFIG_KERN_PRI 00256 void proc_setPri(struct Process *proc, int pri); 00257 00258 INLINE int proc_pri(struct Process *proc) 00259 { 00260 return proc->link.pri; 00261 } 00262 #else 00263 INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri)) 00264 { 00265 } 00266 00267 INLINE int proc_pri(UNUSED_ARG(struct Process *, proc)) 00268 { 00269 return 0; 00270 } 00271 #endif 00272 00273 #if CONFIG_KERN_PREEMPT 00274 00292 INLINE void proc_forbid(void) 00293 { 00294 extern cpu_atomic_t preempt_count; 00295 /* 00296 * We don't need to protect the counter against other processes. 00297 * The reason why is a bit subtle. 00298 * 00299 * If a process gets here, preempt_forbid_cnt can be either 0, 00300 * or != 0. In the latter case, preemption is already disabled 00301 * and no concurrency issues can occur. 00302 * 00303 * In the former case, we could be preempted just after reading the 00304 * value 0 from memory, and a concurrent process might, in fact, 00305 * bump the value of preempt_forbid_cnt under our nose! 00306 * 00307 * BUT: if this ever happens, then we won't get another chance to 00308 * run until the other process calls proc_permit() to re-enable 00309 * preemption. At this point, the value of preempt_forbid_cnt 00310 * must be back to 0, and thus what we had originally read from 00311 * memory happens to be valid. 00312 * 00313 * No matter how hard you think about it, and how complicated you 00314 * make your scenario, the above holds true as long as 00315 * "preempt_forbid_cnt != 0" means that no task switching is 00316 * possible. 00317 */ 00318 ++preempt_count; 00319 00320 /* 00321 * Make sure preempt_count is flushed to memory so the preemption 00322 * softirq will see the correct value from now on. 00323 */ 00324 MEMORY_BARRIER; 00325 } 00326 00332 INLINE void proc_permit(void) 00333 { 00334 extern cpu_atomic_t preempt_count; 00335 00336 /* 00337 * This is to ensure any global state changed by the process gets 00338 * flushed to memory before task switching is re-enabled. 00339 */ 00340 MEMORY_BARRIER; 00341 /* No need to protect against interrupts here. */ 00342 ASSERT(preempt_count > 0); 00343 --preempt_count; 00344 /* 00345 * This ensures preempt_count is flushed to memory immediately so the 00346 * preemption interrupt sees the correct value. 00347 */ 00348 MEMORY_BARRIER; 00349 } 00350 00356 INLINE bool proc_preemptAllowed(void) 00357 { 00358 extern cpu_atomic_t preempt_count; 00359 return (preempt_count == 0); 00360 } 00361 #else /* CONFIG_KERN_PREEMPT */ 00362 #define proc_forbid() /* NOP */ 00363 #define proc_permit() /* NOP */ 00364 #define proc_preemptAllowed() (true) 00365 #endif /* CONFIG_KERN_PREEMPT */ 00366 00368 #define proc_allowed() proc_preemptAllowed() 00369 00373 #define PROC_ATOMIC(CODE) \ 00374 do { \ 00375 proc_forbid(); \ 00376 CODE; \ 00377 proc_permit(); \ 00378 } while(0) 00379 00398 #if (ARCH & ARCH_EMUL) 00399 /* We need a large stack because system libraries are bloated */ 00400 #define KERN_MINSTACKSIZE 65536 00401 #else 00402 #if CONFIG_KERN_PREEMPT 00403 /* 00404 * A preemptible kernel needs a larger stack compared to the 00405 * cooperative case. A task can be interrupted anytime in each 00406 * node of the call graph, at any level of depth. This may 00407 * result in a higher stack consumption, to call the ISR, save 00408 * the current user context and to execute the kernel 00409 * preemption routines implemented as ISR prologue and 00410 * epilogue. All these calls are nested into the process stack. 00411 * 00412 * So, to reduce the risk of stack overflow/underflow problems 00413 * add a x2 to the portion stack reserved to the user process. 00414 */ 00415 #define KERN_MINSTACKSIZE \ 00416 (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \ 00417 + 32 * sizeof(int) * 2) 00418 #else 00419 #define KERN_MINSTACKSIZE \ 00420 (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \ 00421 + 32 * sizeof(int)) 00422 #endif /* CONFIG_KERN_PREEMPT */ 00423 00424 #endif 00425 00426 #ifndef CONFIG_KERN_MINSTACKSIZE 00427 /* For backward compatibility */ 00428 #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE 00429 #else 00430 #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead 00431 #endif 00432 00444 #define PROC_DEFINE_STACK(name, size) \ 00445 cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \ 00446 STATIC_ASSERT((size) >= KERN_MINSTACKSIZE); 00447 00448 /* Memory fill codes to help debugging */ 00449 #if CONFIG_KERN_MONITOR 00450 #include <cpu/types.h> 00451 #if (SIZEOF_CPUSTACK_T == 1) 00452 /* 8bit cpu_stack_t */ 00453 #define CONFIG_KERN_STACKFILLCODE 0xA5 00454 #define CONFIG_KERN_MEMFILLCODE 0xDB 00455 #elif (SIZEOF_CPUSTACK_T == 2) 00456 /* 16bit cpu_stack_t */ 00457 #define CONFIG_KERN_STACKFILLCODE 0xA5A5 00458 #define CONFIG_KERN_MEMFILLCODE 0xDBDB 00459 #elif (SIZEOF_CPUSTACK_T == 4) 00460 /* 32bit cpu_stack_t */ 00461 #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5UL 00462 #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBUL 00463 #elif (SIZEOF_CPUSTACK_T == 8) 00464 /* 64bit cpu_stack_t */ 00465 #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5A5A5A5A5ULL 00466 #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBDBDBDBDBULL 00467 #else 00468 #error No cpu_stack_t size supported! 00469 #endif 00470 #endif 00471 //defgroup kern_proc 00472 00473 #endif /* KERN_PROC_H */
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)