BeRTOS
|
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 00099 #include <struct/list.h> // Node, PriNode 00100 00101 #include <cfg/compiler.h> 00102 #include <cfg/debug.h> // ASSERT() 00103 00104 #include <cpu/types.h> // cpu_stack_t 00105 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT 00106 00107 /* 00108 * WARNING: struct Process is considered private, so its definition can change any time 00109 * without notice. DO NOT RELY on any field defined here, use only the interface 00110 * functions below. 00111 * 00112 * You have been warned. 00113 */ 00114 typedef struct Process 00115 { 00116 #if CONFIG_KERN_PRI 00117 PriNode link; 00118 #else 00119 Node link; 00120 #endif 00121 cpu_stack_t *stack; 00122 iptr_t user_data; 00124 #if CONFIG_KERN_SIGNALS 00125 Signal sig; 00126 #endif 00127 00128 #if CONFIG_KERN_HEAP 00129 uint16_t flags; 00130 #endif 00131 00132 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR 00133 cpu_stack_t *stack_base; 00134 size_t stack_size; 00135 #endif 00136 00137 /* The actual process entry point */ 00138 void (*user_entry)(void); 00139 00140 #if CONFIG_KERN_MONITOR 00141 struct ProcMonitor 00142 { 00143 Node link; 00144 const char *name; 00145 } monitor; 00146 #endif 00147 00148 } Process; 00149 00154 void proc_init(void); 00155 00156 struct Process *proc_new_with_name(const char *name, void (*entry)(void), iptr_t data, size_t stacksize, cpu_stack_t *stack); 00157 00158 #if !CONFIG_KERN_MONITOR 00159 00178 #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack)) 00179 #else 00180 #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack)) 00181 #endif 00182 00186 void proc_exit(void); 00187 00188 /* 00189 * Public scheduling class methods. 00190 */ 00191 void proc_yield(void); 00192 00193 #if CONFIG_KERN_PREEMPT 00194 bool proc_needPreempt(void); 00195 void proc_preempt(void); 00196 #else 00197 INLINE bool proc_needPreempt(void) 00198 { 00199 return false; 00200 } 00201 00202 INLINE void proc_preempt(void) 00203 { 00204 } 00205 #endif 00206 00207 void proc_rename(struct Process *proc, const char *name); 00208 const char *proc_name(struct Process *proc); 00209 const char *proc_currentName(void); 00210 00218 INLINE iptr_t proc_currentUserData(void) 00219 { 00220 extern struct Process *current_process; 00221 return current_process->user_data; 00222 } 00223 00224 int proc_testSetup(void); 00225 int proc_testRun(void); 00226 int proc_testTearDown(void); 00227 00235 INLINE struct Process *proc_current(void) 00236 { 00237 extern struct Process *current_process; 00238 return current_process; 00239 } 00240 00241 #if CONFIG_KERN_PRI 00242 void proc_setPri(struct Process *proc, int pri); 00243 #else 00244 INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri)) 00245 { 00246 } 00247 #endif 00248 00249 #if CONFIG_KERN_PREEMPT 00250 00268 INLINE void proc_forbid(void) 00269 { 00270 extern cpu_atomic_t preempt_count; 00271 /* 00272 * We don't need to protect the counter against other processes. 00273 * The reason why is a bit subtle. 00274 * 00275 * If a process gets here, preempt_forbid_cnt can be either 0, 00276 * or != 0. In the latter case, preemption is already disabled 00277 * and no concurrency issues can occur. 00278 * 00279 * In the former case, we could be preempted just after reading the 00280 * value 0 from memory, and a concurrent process might, in fact, 00281 * bump the value of preempt_forbid_cnt under our nose! 00282 * 00283 * BUT: if this ever happens, then we won't get another chance to 00284 * run until the other process calls proc_permit() to re-enable 00285 * preemption. At this point, the value of preempt_forbid_cnt 00286 * must be back to 0, and thus what we had originally read from 00287 * memory happens to be valid. 00288 * 00289 * No matter how hard you think about it, and how complicated you 00290 * make your scenario, the above holds true as long as 00291 * "preempt_forbid_cnt != 0" means that no task switching is 00292 * possible. 00293 */ 00294 ++preempt_count; 00295 00296 /* 00297 * Make sure preempt_count is flushed to memory so the preemption 00298 * softirq will see the correct value from now on. 00299 */ 00300 MEMORY_BARRIER; 00301 } 00302 00308 INLINE void proc_permit(void) 00309 { 00310 extern cpu_atomic_t preempt_count; 00311 00312 /* 00313 * This is to ensure any global state changed by the process gets 00314 * flushed to memory before task switching is re-enabled. 00315 */ 00316 MEMORY_BARRIER; 00317 /* No need to protect against interrupts here. */ 00318 ASSERT(preempt_count > 0); 00319 --preempt_count; 00320 /* 00321 * This ensures preempt_count is flushed to memory immediately so the 00322 * preemption interrupt sees the correct value. 00323 */ 00324 MEMORY_BARRIER; 00325 } 00326 00332 INLINE bool proc_preemptAllowed(void) 00333 { 00334 extern cpu_atomic_t preempt_count; 00335 return (preempt_count == 0); 00336 } 00337 #else /* CONFIG_KERN_PREEMPT */ 00338 #define proc_forbid() /* NOP */ 00339 #define proc_permit() /* NOP */ 00340 #define proc_preemptAllowed() (true) 00341 #endif /* CONFIG_KERN_PREEMPT */ 00342 00344 #define proc_allowed() proc_preemptAllowed() 00345 00349 #define PROC_ATOMIC(CODE) \ 00350 do { \ 00351 proc_forbid(); \ 00352 CODE; \ 00353 proc_permit(); \ 00354 } while(0) 00355 00374 #if (ARCH & ARCH_EMUL) 00375 /* We need a large stack because system libraries are bloated */ 00376 #define KERN_MINSTACKSIZE 65536 00377 #else 00378 #if CONFIG_KERN_PREEMPT 00379 /* 00380 * A preemptible kernel needs a larger stack compared to the 00381 * cooperative case. A task can be interrupted anytime in each 00382 * node of the call graph, at any level of depth. This may 00383 * result in a higher stack consumption, to call the ISR, save 00384 * the current user context and to execute the kernel 00385 * preemption routines implemented as ISR prologue and 00386 * epilogue. All these calls are nested into the process stack. 00387 * 00388 * So, to reduce the risk of stack overflow/underflow problems 00389 * add a x2 to the portion stack reserved to the user process. 00390 */ 00391 #define KERN_MINSTACKSIZE \ 00392 (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \ 00393 + 32 * sizeof(int) * 2) 00394 #else 00395 #define KERN_MINSTACKSIZE \ 00396 (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \ 00397 + 32 * sizeof(int)) 00398 #endif /* CONFIG_KERN_PREEMPT */ 00399 00400 #endif 00401 00402 #ifndef CONFIG_KERN_MINSTACKSIZE 00403 /* For backward compatibility */ 00404 #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE 00405 #else 00406 #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead 00407 #endif 00408 00420 #define PROC_DEFINE_STACK(name, size) \ 00421 cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \ 00422 STATIC_ASSERT((size) >= KERN_MINSTACKSIZE); 00423 00424 /* Memory fill codes to help debugging */ 00425 #if CONFIG_KERN_MONITOR 00426 #include <cpu/types.h> 00427 #if (SIZEOF_CPUSTACK_T == 1) 00428 /* 8bit cpu_stack_t */ 00429 #define CONFIG_KERN_STACKFILLCODE 0xA5 00430 #define CONFIG_KERN_MEMFILLCODE 0xDB 00431 #elif (SIZEOF_CPUSTACK_T == 2) 00432 /* 16bit cpu_stack_t */ 00433 #define CONFIG_KERN_STACKFILLCODE 0xA5A5 00434 #define CONFIG_KERN_MEMFILLCODE 0xDBDB 00435 #elif (SIZEOF_CPUSTACK_T == 4) 00436 /* 32bit cpu_stack_t */ 00437 #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5UL 00438 #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBUL 00439 #elif (SIZEOF_CPUSTACK_T == 8) 00440 /* 64bit cpu_stack_t */ 00441 #define CONFIG_KERN_STACKFILLCODE 0xA5A5A5A5A5A5A5A5ULL 00442 #define CONFIG_KERN_MEMFILLCODE 0xDBDBDBDBDBDBDBDBULL 00443 #else 00444 #error No cpu_stack_t size supported! 00445 #endif 00446 #endif 00447 //defgroup kern_proc 00448 00449 #endif /* KERN_PROC_H */