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     #include <kern/preempt.h>
00058 #endif
00059 
00060 #include <cpu/types.h> // cpu_stack_t
00061 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT
00062 
00063 /*
00064  * WARNING: struct Process is considered private, so its definition can change any time
00065  * without notice. DO NOT RELY on any field defined here, use only the interface
00066  * functions below.
00067  *
00068  * You have been warned.
00069  */
00070 typedef struct Process
00071 {
00072 #if CONFIG_KERN_PRI
00073     PriNode      link;        
00074 #else
00075     Node         link;        
00076 #endif
00077     cpu_stack_t  *stack;       
00078     iptr_t       user_data;   
00080 #if CONFIG_KERN_SIGNALS
00081     sigmask_t    sig_wait;    
00082     sigmask_t    sig_recv;    
00083 #endif
00084 
00085 #if CONFIG_KERN_HEAP
00086     uint16_t     flags;       
00087 #endif
00088 
00089 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR
00090     cpu_stack_t  *stack_base;  
00091     size_t       stack_size;  
00092 #endif
00093 
00094     /* The actual process entry point */
00095     void (*user_entry)(void);
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 
00148 void proc_yield(void);
00149 void proc_preempt(void);
00150 int proc_needPreempt(void);
00151 void proc_wakeup(Process *proc);
00152 
00156 INLINE void __proc_noop(void)
00157 {
00158 }
00159 
00160 #if CONFIG_KERN_PREEMPT
00161 
00164     #define preempt_yield       proc_yield
00165     #define preempt_needPreempt proc_needPreempt
00166     #define preempt_preempt     proc_preempt
00167 
00170     #define preempt_switch      proc_switch
00171     #define preempt_wakeup      proc_wakeup
00172 #else
00173 
00176     #define coop_yield      proc_yield
00177     #define proc_needPreempt    __proc_noop
00178     #define proc_preempt        __proc_noop
00179 
00182     #define coop_switch     proc_switch
00183     #define coop_wakeup     proc_wakeup
00184 #endif
00185 
00186 void proc_rename(struct Process *proc, const char *name);
00187 const char *proc_name(struct Process *proc);
00188 const char *proc_currentName(void);
00189 
00197 INLINE iptr_t proc_currentUserData(void)
00198 {
00199     extern struct Process *current_process;
00200     return current_process->user_data;
00201 }
00202 
00203 int proc_testSetup(void);
00204 int proc_testRun(void);
00205 int proc_testTearDown(void);
00206 
00214 INLINE struct Process *proc_current(void)
00215 {
00216     extern struct Process *current_process;
00217     return current_process;
00218 }
00219 
00220 #if CONFIG_KERN_PRI
00221     void proc_setPri(struct Process *proc, int pri);
00222 #else
00223     INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri))
00224     {
00225     }
00226 #endif
00227 
00228 #if CONFIG_KERN_PREEMPT
00229 
00247     INLINE void proc_forbid(void)
00248     {
00249         extern cpu_atomic_t preempt_count;
00250         /*
00251          * We don't need to protect the counter against other processes.
00252          * The reason why is a bit subtle.
00253          *
00254          * If a process gets here, preempt_forbid_cnt can be either 0,
00255          * or != 0.  In the latter case, preemption is already disabled
00256          * and no concurrency issues can occur.
00257          *
00258          * In the former case, we could be preempted just after reading the
00259          * value 0 from memory, and a concurrent process might, in fact,
00260          * bump the value of preempt_forbid_cnt under our nose!
00261          *
00262          * BUT: if this ever happens, then we won't get another chance to
00263          * run until the other process calls proc_permit() to re-enable
00264          * preemption.  At this point, the value of preempt_forbid_cnt
00265          * must be back to 0, and thus what we had originally read from
00266          * memory happens to be valid.
00267          *
00268          * No matter how hard you think about it, and how complicated you
00269          * make your scenario, the above holds true as long as
00270          * "preempt_forbid_cnt != 0" means that no task switching is
00271          * possible.
00272          */
00273         ++preempt_count;
00274 
00275         /*
00276          * Make sure preempt_count is flushed to memory so the preemption
00277          * softirq will see the correct value from now on.
00278          */
00279         MEMORY_BARRIER;
00280     }
00281 
00287     INLINE void proc_permit(void)
00288     {
00289         extern cpu_atomic_t preempt_count;
00290 
00291         /*
00292          * This is to ensure any global state changed by the process gets
00293          * flushed to memory before task switching is re-enabled.
00294          */
00295         MEMORY_BARRIER;
00296         /* No need to protect against interrupts here. */
00297         ASSERT(preempt_count > 0);
00298         --preempt_count;
00299         /*
00300          * This ensures preempt_count is flushed to memory immediately so the
00301          * preemption interrupt sees the correct value.
00302          */
00303         MEMORY_BARRIER;
00304     }
00305 
00311     INLINE bool proc_preemptAllowed(void)
00312     {
00313         extern cpu_atomic_t preempt_count;
00314         return (preempt_count == 0);
00315     }
00316 #else /* CONFIG_KERN_PREEMPT */
00317     #define proc_forbid() /* NOP */
00318     #define proc_permit() /* NOP */
00319     #define proc_preemptAllowed() (true)
00320 #endif /* CONFIG_KERN_PREEMPT */
00321 
00323 #define proc_allowed() proc_preemptAllowed()
00324 
00328 #define PROC_ATOMIC(CODE) \
00329     do { \
00330         proc_forbid(); \
00331         CODE; \
00332         proc_permit(); \
00333     } while(0)
00334 
00353 #if (ARCH & ARCH_EMUL)
00354     /* We need a large stack because system libraries are bloated */
00355     #define KERN_MINSTACKSIZE 65536
00356 #else
00357     #if CONFIG_KERN_PREEMPT
00358         /*
00359          * A preemptible kernel needs a larger stack compared to the
00360          * cooperative case. A task can be interrupted anytime in each
00361          * node of the call graph, at any level of depth. This may
00362          * result in a higher stack consumption, to call the ISR, save
00363          * the current user context and to execute the kernel
00364          * preemption routines implemented as ISR prologue and
00365          * epilogue. All these calls are nested into the process stack.
00366          *
00367          * So, to reduce the risk of stack overflow/underflow problems
00368          * add a x2 to the portion stack reserved to the user process.
00369          */
00370         #define KERN_MINSTACKSIZE \
00371             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00372             + 32 * sizeof(int) * 2)
00373     #else
00374         #define KERN_MINSTACKSIZE \
00375             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00376             + 32 * sizeof(int))
00377     #endif /* CONFIG_KERN_PREEMPT */
00378 
00379 #endif
00380 
00381 #ifndef CONFIG_KERN_MINSTACKSIZE
00382     /* For backward compatibility */
00383     #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE
00384 #else
00385     #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead
00386 #endif
00387 
00399 #define PROC_DEFINE_STACK(name, size) \
00400     cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \
00401     STATIC_ASSERT((size) >= KERN_MINSTACKSIZE);
00402 
00403 /* Memory fill codes to help debugging */
00404 #if CONFIG_KERN_MONITOR
00405     #include <cpu/types.h>
00406     #if (SIZEOF_CPUSTACK_T == 1)
00407         /* 8bit cpu_stack_t */
00408         #define CONFIG_KERN_STACKFILLCODE  0xA5
00409         #define CONFIG_KERN_MEMFILLCODE    0xDB
00410     #elif (SIZEOF_CPUSTACK_T == 2)
00411         /* 16bit cpu_stack_t */
00412         #define CONFIG_KERN_STACKFILLCODE  0xA5A5
00413         #define CONFIG_KERN_MEMFILLCODE    0xDBDB
00414     #elif (SIZEOF_CPUSTACK_T == 4)
00415         /* 32bit cpu_stack_t */
00416         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5UL
00417         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBUL
00418     #elif (SIZEOF_CPUSTACK_T == 8)
00419         /* 64bit cpu_stack_t */
00420         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5A5A5A5A5ULL
00421         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBDBDBDBDBULL
00422     #else
00423         #error No cpu_stack_t size supported!
00424     #endif
00425 #endif
00426 
00427 #endif /* KERN_PROC_H */