proc.h

Go to the documentation of this file.
00001 
00043 #ifndef KERN_PROC_H
00044 #define KERN_PROC_H
00045 
00046 #include "cfg/cfg_proc.h"
00047 #include "cfg/cfg_signal.h"
00048 #include "cfg/cfg_monitor.h"
00049 
00050 #include <struct/list.h> // Node, PriNode
00051 
00052 #include <cfg/compiler.h>
00053 #include <cfg/debug.h> // ASSERT()
00054 
00055 #include <cpu/types.h> // cpu_stack_t
00056 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT
00057 
00058 /*
00059  * WARNING: struct Process is considered private, so its definition can change any time
00060  * without notice. DO NOT RELY on any field defined here, use only the interface
00061  * functions below.
00062  *
00063  * You have been warned.
00064  */
00065 typedef struct Process
00066 {
00067 #if CONFIG_KERN_PRI
00068     PriNode      link;        
00069 #else
00070     Node         link;        
00071 #endif
00072     cpu_stack_t  *stack;       
00073     iptr_t       user_data;   
00075 #if CONFIG_KERN_SIGNALS
00076     sigmask_t    sig_wait;    
00077     sigmask_t    sig_recv;    
00078 #endif
00079 
00080 #if CONFIG_KERN_HEAP
00081     uint16_t     flags;       
00082 #endif
00083 
00084 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR
00085     cpu_stack_t  *stack_base;  
00086     size_t       stack_size;  
00087 #endif
00088 
00089     /* The actual process entry point */
00090     void (*user_entry)(void);
00091 
00092 #if CONFIG_KERN_MONITOR
00093     struct ProcMonitor
00094     {
00095         Node        link;
00096         const char *name;
00097     } monitor;
00098 #endif
00099 
00100 } Process;
00101 
00106 void proc_init(void);
00107 
00108 struct Process *proc_new_with_name(const char *name, void (*entry)(void), iptr_t data, size_t stacksize, cpu_stack_t *stack);
00109 
00110 #if !CONFIG_KERN_MONITOR
00111 
00130     #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack))
00131 #else
00132     #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack))
00133 #endif
00134 
00138 void proc_exit(void);
00139 
00143 void proc_yield(void);
00144 
00145 #if CONFIG_KERN_PREEMPT
00146 bool proc_needPreempt(void);
00147 void proc_preempt(void);
00148 #else
00149 INLINE bool proc_needPreempt(void)
00150 {
00151     return false;
00152 }
00153 
00154 INLINE void proc_preempt(void)
00155 {
00156 }
00157 #endif
00158 
00159 void proc_rename(struct Process *proc, const char *name);
00160 const char *proc_name(struct Process *proc);
00161 const char *proc_currentName(void);
00162 
00170 INLINE iptr_t proc_currentUserData(void)
00171 {
00172     extern struct Process *current_process;
00173     return current_process->user_data;
00174 }
00175 
00176 int proc_testSetup(void);
00177 int proc_testRun(void);
00178 int proc_testTearDown(void);
00179 
00187 INLINE struct Process *proc_current(void)
00188 {
00189     extern struct Process *current_process;
00190     return current_process;
00191 }
00192 
00193 #if CONFIG_KERN_PRI
00194     void proc_setPri(struct Process *proc, int pri);
00195 #else
00196     INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri))
00197     {
00198     }
00199 #endif
00200 
00201 #if CONFIG_KERN_PREEMPT
00202 
00220     INLINE void proc_forbid(void)
00221     {
00222         extern cpu_atomic_t preempt_count;
00223         /*
00224          * We don't need to protect the counter against other processes.
00225          * The reason why is a bit subtle.
00226          *
00227          * If a process gets here, preempt_forbid_cnt can be either 0,
00228          * or != 0.  In the latter case, preemption is already disabled
00229          * and no concurrency issues can occur.
00230          *
00231          * In the former case, we could be preempted just after reading the
00232          * value 0 from memory, and a concurrent process might, in fact,
00233          * bump the value of preempt_forbid_cnt under our nose!
00234          *
00235          * BUT: if this ever happens, then we won't get another chance to
00236          * run until the other process calls proc_permit() to re-enable
00237          * preemption.  At this point, the value of preempt_forbid_cnt
00238          * must be back to 0, and thus what we had originally read from
00239          * memory happens to be valid.
00240          *
00241          * No matter how hard you think about it, and how complicated you
00242          * make your scenario, the above holds true as long as
00243          * "preempt_forbid_cnt != 0" means that no task switching is
00244          * possible.
00245          */
00246         ++preempt_count;
00247 
00248         /*
00249          * Make sure preempt_count is flushed to memory so the preemption
00250          * softirq will see the correct value from now on.
00251          */
00252         MEMORY_BARRIER;
00253     }
00254 
00260     INLINE void proc_permit(void)
00261     {
00262         extern cpu_atomic_t preempt_count;
00263 
00264         /*
00265          * This is to ensure any global state changed by the process gets
00266          * flushed to memory before task switching is re-enabled.
00267          */
00268         MEMORY_BARRIER;
00269         /* No need to protect against interrupts here. */
00270         ASSERT(preempt_count > 0);
00271         --preempt_count;
00272         /*
00273          * This ensures preempt_count is flushed to memory immediately so the
00274          * preemption interrupt sees the correct value.
00275          */
00276         MEMORY_BARRIER;
00277     }
00278 
00284     INLINE bool proc_preemptAllowed(void)
00285     {
00286         extern cpu_atomic_t preempt_count;
00287         return (preempt_count == 0);
00288     }
00289 #else /* CONFIG_KERN_PREEMPT */
00290     #define proc_forbid() /* NOP */
00291     #define proc_permit() /* NOP */
00292     #define proc_preemptAllowed() (true)
00293 #endif /* CONFIG_KERN_PREEMPT */
00294 
00296 #define proc_allowed() proc_preemptAllowed()
00297 
00301 #define PROC_ATOMIC(CODE) \
00302     do { \
00303         proc_forbid(); \
00304         CODE; \
00305         proc_permit(); \
00306     } while(0)
00307 
00326 #if (ARCH & ARCH_EMUL)
00327     /* We need a large stack because system libraries are bloated */
00328     #define KERN_MINSTACKSIZE 65536
00329 #else
00330     #if CONFIG_KERN_PREEMPT
00331         /*
00332          * A preemptible kernel needs a larger stack compared to the
00333          * cooperative case. A task can be interrupted anytime in each
00334          * node of the call graph, at any level of depth. This may
00335          * result in a higher stack consumption, to call the ISR, save
00336          * the current user context and to execute the kernel
00337          * preemption routines implemented as ISR prologue and
00338          * epilogue. All these calls are nested into the process stack.
00339          *
00340          * So, to reduce the risk of stack overflow/underflow problems
00341          * add a x2 to the portion stack reserved to the user process.
00342          */
00343         #define KERN_MINSTACKSIZE \
00344             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00345             + 32 * sizeof(int) * 2)
00346     #else
00347         #define KERN_MINSTACKSIZE \
00348             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00349             + 32 * sizeof(int))
00350     #endif /* CONFIG_KERN_PREEMPT */
00351 
00352 #endif
00353 
00354 #ifndef CONFIG_KERN_MINSTACKSIZE
00355     /* For backward compatibility */
00356     #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE
00357 #else
00358     #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead
00359 #endif
00360 
00372 #define PROC_DEFINE_STACK(name, size) \
00373     cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \
00374     STATIC_ASSERT((size) >= KERN_MINSTACKSIZE);
00375 
00376 /* Memory fill codes to help debugging */
00377 #if CONFIG_KERN_MONITOR
00378     #include <cpu/types.h>
00379     #if (SIZEOF_CPUSTACK_T == 1)
00380         /* 8bit cpu_stack_t */
00381         #define CONFIG_KERN_STACKFILLCODE  0xA5
00382         #define CONFIG_KERN_MEMFILLCODE    0xDB
00383     #elif (SIZEOF_CPUSTACK_T == 2)
00384         /* 16bit cpu_stack_t */
00385         #define CONFIG_KERN_STACKFILLCODE  0xA5A5
00386         #define CONFIG_KERN_MEMFILLCODE    0xDBDB
00387     #elif (SIZEOF_CPUSTACK_T == 4)
00388         /* 32bit cpu_stack_t */
00389         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5UL
00390         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBUL
00391     #elif (SIZEOF_CPUSTACK_T == 8)
00392         /* 64bit cpu_stack_t */
00393         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5A5A5A5A5ULL
00394         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBDBDBDBDBULL
00395     #else
00396         #error No cpu_stack_t size supported!
00397     #endif
00398 #endif
00399 
00400 #endif /* KERN_PROC_H */