proc.h

Go to the documentation of this file.
00001 
00044 #ifndef KERN_PROC_H
00045 #define KERN_PROC_H
00046 
00047 #include "cfg/cfg_proc.h"
00048 #include "cfg/cfg_signal.h"
00049 #include "cfg/cfg_monitor.h"
00050 
00051 #include <struct/list.h> // Node, PriNode
00052 
00053 #include <cfg/compiler.h>
00054 
00055 #if CONFIG_KERN_PREEMPT
00056     #include <cfg/debug.h> // ASSERT()
00057 #endif
00058 
00059 #include <cpu/types.h> // cpu_stack_t
00060 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT
00061 
00062 /*
00063  * WARNING: struct Process is considered private, so its definition can change any time
00064  * without notice. DO NOT RELY on any field defined here, use only the interface
00065  * functions below.
00066  *
00067  * You have been warned.
00068  */
00069 typedef struct Process
00070 {
00071 #if CONFIG_KERN_PRI
00072     PriNode      link;        
00073 #else
00074     Node         link;        
00075 #endif
00076     cpu_stack_t  *stack;       
00077     iptr_t       user_data;   
00079 #if CONFIG_KERN_SIGNALS
00080     sigmask_t    sig_wait;    
00081     sigmask_t    sig_recv;    
00082 #endif
00083 
00084 #if CONFIG_KERN_HEAP
00085     uint16_t     flags;       
00086 #endif
00087 
00088 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR | (ARCH & ARCH_EMUL)
00089     cpu_stack_t  *stack_base;  
00090     size_t       stack_size;  
00091 #endif
00092 
00093 #if CONFIG_KERN_PREEMPT
00094     ucontext_t   context;
00095 #endif
00096 
00097 #if CONFIG_KERN_MONITOR
00098     struct ProcMonitor
00099     {
00100         Node        link;
00101         const char *name;
00102     } monitor;
00103 #endif
00104 
00105 } Process;
00106 
00111 void proc_init(void);
00112 
00113 struct Process *proc_new_with_name(const char *name, void (*entry)(void), iptr_t data, size_t stacksize, cpu_stack_t *stack);
00114 
00115 #if !CONFIG_KERN_MONITOR
00116 
00135     #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack))
00136 #else
00137     #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack))
00138 #endif
00139 
00143 void proc_exit(void);
00144 
00154 void proc_yield(void);
00155 
00156 void proc_rename(struct Process *proc, const char *name);
00157 const char *proc_name(struct Process *proc);
00158 const char *proc_currentName(void);
00159 
00167 iptr_t proc_currentUserData(void);
00168 
00169 int proc_testSetup(void);
00170 int proc_testRun(void);
00171 int proc_testTearDown(void);
00172 
00180 INLINE struct Process *proc_current(void)
00181 {
00182     extern struct Process *CurrentProcess;
00183     return CurrentProcess;
00184 }
00185 
00186 #if CONFIG_KERN_PRI
00187     void proc_setPri(struct Process *proc, int pri);
00188 #else
00189     INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri))
00190     {
00191     }
00192 #endif
00193 
00214 INLINE void proc_forbid(void)
00215 {
00216     #if CONFIG_KERN_PREEMPT
00217         extern cpu_atomic_t _preempt_forbid_cnt;
00218         /*
00219          * We don't need to protect the counter against other processes.
00220          * The reason why is a bit subtle.
00221          *
00222          * If a process gets here, preempt_forbid_cnt can be either 0,
00223          * or != 0.  In the latter case, preemption is already disabled
00224          * and no concurrency issues can occur.
00225          *
00226          * In the former case, we could be preempted just after reading the
00227          * value 0 from memory, and a concurrent process might, in fact,
00228          * bump the value of preempt_forbid_cnt under our nose!
00229          *
00230          * BUT: if this ever happens, then we won't get another chance to
00231          * run until the other process calls proc_permit() to re-enable
00232          * preemption.  At this point, the value of preempt_forbid_cnt
00233          * must be back to 0, and thus what we had originally read from
00234          * memory happens to be valid.
00235          *
00236          * No matter how hard you think about it, and how complicated you
00237          * make your scenario, the above holds true as long as
00238          * "preempt_forbid_cnt != 0" means that no task switching is
00239          * possible.
00240          */
00241         ++_preempt_forbid_cnt;
00242 
00243         /*
00244          * Make sure _preempt_forbid_cnt is flushed to memory so the
00245          * preemption softirq will see the correct value from now on.
00246          */
00247         MEMORY_BARRIER;
00248     #endif
00249 }
00250 
00256 INLINE void proc_permit(void)
00257 {
00258     #if CONFIG_KERN_PREEMPT
00259 
00260         /*
00261          * This is to ensure any global state changed by the process gets
00262          * flushed to memory before task switching is re-enabled.
00263          */
00264         MEMORY_BARRIER;
00265         extern cpu_atomic_t _preempt_forbid_cnt;
00266         /* No need to protect against interrupts here. */
00267         ASSERT(_preempt_forbid_cnt != 0);
00268         --_preempt_forbid_cnt;
00269 
00270         /*
00271          * This ensures _preempt_forbid_cnt is flushed to memory immediately
00272          * so the preemption interrupt sees the correct value.
00273          */
00274         MEMORY_BARRIER;
00275 
00276     #endif
00277 }
00278 
00284 INLINE bool proc_allowed(void)
00285 {
00286     #if CONFIG_KERN_PREEMPT
00287         extern cpu_atomic_t _preempt_forbid_cnt;
00288         return (_preempt_forbid_cnt == 0);
00289     #else
00290         return true;
00291     #endif
00292 }
00293 
00297 #define PROC_ATOMIC(CODE) \
00298     do { \
00299         proc_forbid(); \
00300         CODE; \
00301         proc_permit(); \
00302     } while(0)
00303 
00322 #if (ARCH & ARCH_EMUL)
00323     /* We need a large stack because system libraries are bloated */
00324     #define KERN_MINSTACKSIZE 65536
00325 #else
00326     #define KERN_MINSTACKSIZE \
00327         (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00328         + 32 * sizeof(int))
00329 #endif
00330 
00331 #ifndef CONFIG_KERN_MINSTACKSIZE
00332     /* For backward compatibility */
00333     #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE
00334 #else
00335     #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead
00336 #endif
00337 
00349 #define PROC_DEFINE_STACK(name, size) \
00350     STATIC_ASSERT((size) >= KERN_MINSTACKSIZE); \
00351     cpu_stack_t name[(size) / sizeof(cpu_stack_t)];
00352 
00353 /* Memory fill codes to help debugging */
00354 #if CONFIG_KERN_MONITOR
00355     #include <cpu/types.h>
00356     #if (SIZEOF_CPUSTACK_T == 1)
00357         /* 8bit cpu_stack_t */
00358         #define CONFIG_KERN_STACKFILLCODE  0xA5
00359         #define CONFIG_KERN_MEMFILLCODE    0xDB
00360     #elif (SIZEOF_CPUSTACK_T == 2)
00361         /* 16bit cpu_stack_t */
00362         #define CONFIG_KERN_STACKFILLCODE  0xA5A5
00363         #define CONFIG_KERN_MEMFILLCODE    0xDBDB
00364     #elif (SIZEOF_CPUSTACK_T == 4)
00365         /* 32bit cpu_stack_t */
00366         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5UL
00367         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBUL
00368     #elif (SIZEOF_CPUSTACK_T == 8)
00369         /* 64bit cpu_stack_t */
00370         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5A5A5A5A5ULL
00371         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBDBDBDBDBULL
00372     #else
00373         #error No cpu_stack_t size supported!
00374     #endif
00375 #endif
00376 
00377 #endif /* KERN_PROC_H */