BeRTOS
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 
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 */