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 #include "sem.h"
00099
00100 #include <struct/list.h> // Node, PriNode
00101
00102 #include <cfg/compiler.h>
00103 #include <cfg/debug.h> // ASSERT()
00104
00105 #include <cpu/types.h> // cpu_stack_t
00106 #include <cpu/frame.h> // CPU_SAVED_REGS_CNT
00107
00108 /* The following silents warnings on nightly tests. We need to regenerate
00109  * all the projects before this can be removed.
00110  */
00111 #ifndef CONFIG_KERN_PRI_INHERIT
00112 #define CONFIG_KERN_PRI_INHERIT 0
00113 #endif
00114 
00115 /*
00116  * WARNING: struct Process is considered private, so its definition can change any time
00117  * without notice. DO NOT RELY on any field defined here, use only the interface
00118  * functions below.
00119  *
00120  * You have been warned.
00121  */
00122 typedef struct Process
00123 {
00124 #if CONFIG_KERN_PRI
00125     PriNode      link;
00126 # if CONFIG_KERN_PRI_INHERIT
00127     PriNode      inh_link;
00128     List         inh_list;
00129     Semaphore    *inh_blocked_by;
00130     int          orig_pri;
00131 # endif
00132 #else
00133     Node         link;
00134 #endif
00135     cpu_stack_t  *stack;
00136     iptr_t       user_data;
00138 #if CONFIG_KERN_SIGNALS
00139     Signal       sig;
00140 #endif
00141 
00142 #if CONFIG_KERN_HEAP
00143     uint16_t     flags;
00144 #endif
00145 
00146 #if CONFIG_KERN_HEAP | CONFIG_KERN_MONITOR
00147     cpu_stack_t  *stack_base;
00148     size_t       stack_size;
00149 #endif
00150 
00151     /* The actual process entry point */
00152     void (*user_entry)(void);
00153
00154 #if CONFIG_KERN_MONITOR
00155     struct ProcMonitor
00156     {
00157         Node        link;
00158         const char *name;
00159     } monitor;
00160 #endif
00161 
00162 } Process;
00163
00168 void proc_init(void);
00169
00170 struct Process *proc_new_with_name(const char *name, void (*entry)(void), iptr_t data, size_t stacksize, cpu_stack_t *stack);
00171
00172 #if !CONFIG_KERN_MONITOR
00173 
00192     #define proc_new(entry,data,size,stack) proc_new_with_name(NULL,(entry),(data),(size),(stack))
00193 #else
00194     #define proc_new(entry,data,size,stack) proc_new_with_name(#entry,(entry),(data),(size),(stack))
00195 #endif
00196 
00200 void proc_exit(void);
00201
00202 /*
00203  * Public scheduling class methods.
00204  */
00205 void proc_yield(void);
00206
00207 #if CONFIG_KERN_PREEMPT
00208 bool proc_needPreempt(void);
00209 void proc_preempt(void);
00210 #else
00211 INLINE bool proc_needPreempt(void)
00212 {
00213     return false;
00214 }
00215
00216 INLINE void proc_preempt(void)
00217 {
00218 }
00219 #endif
00220 
00221 void proc_rename(struct Process *proc, const char *name);
00222 const char *proc_name(struct Process *proc);
00223 const char *proc_currentName(void);
00224
00232 INLINE iptr_t proc_currentUserData(void)
00233 {
00234     extern struct Process *current_process;
00235     return current_process->user_data;
00236 }
00237
00238 int proc_testSetup(void);
00239 int proc_testRun(void);
00240 int proc_testTearDown(void);
00241
00249 INLINE struct Process *proc_current(void)
00250 {
00251     extern struct Process *current_process;
00252     return current_process;
00253 }
00254
00255 #if CONFIG_KERN_PRI
00256     void proc_setPri(struct Process *proc, int pri);
00257
00258     INLINE int proc_pri(struct Process *proc)
00259     {
00260         return proc->link.pri;
00261     }
00262 #else
00263     INLINE void proc_setPri(UNUSED_ARG(struct Process *,proc), UNUSED_ARG(int, pri))
00264     {
00265     }
00266
00267     INLINE int proc_pri(UNUSED_ARG(struct Process *, proc))
00268     {
00269         return 0;
00270     }
00271 #endif
00272 
00273 #if CONFIG_KERN_PREEMPT
00274 
00292     INLINE void proc_forbid(void)
00293     {
00294         extern cpu_atomic_t preempt_count;
00295         /*
00296          * We don't need to protect the counter against other processes.
00297          * The reason why is a bit subtle.
00298          *
00299          * If a process gets here, preempt_forbid_cnt can be either 0,
00300          * or != 0.  In the latter case, preemption is already disabled
00301          * and no concurrency issues can occur.
00302          *
00303          * In the former case, we could be preempted just after reading the
00304          * value 0 from memory, and a concurrent process might, in fact,
00305          * bump the value of preempt_forbid_cnt under our nose!
00306          *
00307          * BUT: if this ever happens, then we won't get another chance to
00308          * run until the other process calls proc_permit() to re-enable
00309          * preemption.  At this point, the value of preempt_forbid_cnt
00310          * must be back to 0, and thus what we had originally read from
00311          * memory happens to be valid.
00312          *
00313          * No matter how hard you think about it, and how complicated you
00314          * make your scenario, the above holds true as long as
00315          * "preempt_forbid_cnt != 0" means that no task switching is
00316          * possible.
00317          */
00318         ++preempt_count;
00319
00320         /*
00321          * Make sure preempt_count is flushed to memory so the preemption
00322          * softirq will see the correct value from now on.
00323          */
00324         MEMORY_BARRIER;
00325     }
00326
00332     INLINE void proc_permit(void)
00333     {
00334         extern cpu_atomic_t preempt_count;
00335
00336         /*
00337          * This is to ensure any global state changed by the process gets
00338          * flushed to memory before task switching is re-enabled.
00339          */
00340         MEMORY_BARRIER;
00341         /* No need to protect against interrupts here. */
00342         ASSERT(preempt_count > 0);
00343         --preempt_count;
00344         /*
00345          * This ensures preempt_count is flushed to memory immediately so the
00346          * preemption interrupt sees the correct value.
00347          */
00348         MEMORY_BARRIER;
00349     }
00350
00356     INLINE bool proc_preemptAllowed(void)
00357     {
00358         extern cpu_atomic_t preempt_count;
00359         return (preempt_count == 0);
00360     }
00361 #else /* CONFIG_KERN_PREEMPT */
00362     #define proc_forbid() /* NOP */
00363     #define proc_permit() /* NOP */
00364     #define proc_preemptAllowed() (true)
00365 #endif /* CONFIG_KERN_PREEMPT */
00366
00368 #define proc_allowed() proc_preemptAllowed()
00369 
00373 #define PROC_ATOMIC(CODE) \
00374     do { \
00375         proc_forbid(); \
00376         CODE; \
00377         proc_permit(); \
00378     } while(0)
00379 
00398 #if (ARCH & ARCH_EMUL)
00399     /* We need a large stack because system libraries are bloated */
00400     #define KERN_MINSTACKSIZE 65536
00401 #else
00402     #if CONFIG_KERN_PREEMPT
00403         /*
00404          * A preemptible kernel needs a larger stack compared to the
00405          * cooperative case. A task can be interrupted anytime in each
00406          * node of the call graph, at any level of depth. This may
00407          * result in a higher stack consumption, to call the ISR, save
00408          * the current user context and to execute the kernel
00409          * preemption routines implemented as ISR prologue and
00410          * epilogue. All these calls are nested into the process stack.
00411          *
00412          * So, to reduce the risk of stack overflow/underflow problems
00413          * add a x2 to the portion stack reserved to the user process.
00414          */
00415         #define KERN_MINSTACKSIZE \
00416             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00417             + 32 * sizeof(int) * 2)
00418     #else
00419         #define KERN_MINSTACKSIZE \
00420             (sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
00421             + 32 * sizeof(int))
00422     #endif /* CONFIG_KERN_PREEMPT */
00423
00424 #endif
00425 
00426 #ifndef CONFIG_KERN_MINSTACKSIZE
00427     /* For backward compatibility */
00428     #define CONFIG_KERN_MINSTACKSIZE KERN_MINSTACKSIZE
00429 #else
00430     #warning FIXME: This macro is deprecated, use KERN_MINSTACKSIZE instead
00431 #endif
00432 
00444 #define PROC_DEFINE_STACK(name, size) \
00445     cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \
00446     STATIC_ASSERT((size) >= KERN_MINSTACKSIZE);
00447 
00448 /* Memory fill codes to help debugging */
00449 #if CONFIG_KERN_MONITOR
00450     #include <cpu/types.h>
00451     #if (SIZEOF_CPUSTACK_T == 1)
00452         /* 8bit cpu_stack_t */
00453         #define CONFIG_KERN_STACKFILLCODE  0xA5
00454         #define CONFIG_KERN_MEMFILLCODE    0xDB
00455     #elif (SIZEOF_CPUSTACK_T == 2)
00456         /* 16bit cpu_stack_t */
00457         #define CONFIG_KERN_STACKFILLCODE  0xA5A5
00458         #define CONFIG_KERN_MEMFILLCODE    0xDBDB
00459     #elif (SIZEOF_CPUSTACK_T == 4)
00460         /* 32bit cpu_stack_t */
00461         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5UL
00462         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBUL
00463     #elif (SIZEOF_CPUSTACK_T == 8)
00464         /* 64bit cpu_stack_t */
00465         #define CONFIG_KERN_STACKFILLCODE  0xA5A5A5A5A5A5A5A5ULL
00466         #define CONFIG_KERN_MEMFILLCODE    0xDBDBDBDBDBDBDBDBULL
00467     #else
00468         #error No cpu_stack_t size supported!
00469     #endif
00470 #endif
00471  //defgroup kern_proc
00472
00473 #endif /* KERN_PROC_H */