Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members

trt.h

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------
00002  *
00003  * (C) Copyright Koninklijke Philips Electronics NV 2006. 
00004  * All rights reserved. This software is licensed under the terms of
00005  * version 2.1 of the GNU Lesser General Public License as published 
00006  * by the Free Software Foundation. For licensing and warranty
00007  * information, see the file COPYING in the main directory.
00008  *
00009  *------------------------------------------------------------------*/
00010 
00011 #ifndef TRT_H
00012 #define TRT_H
00013 
00014 #include <setjmp.h>
00015 #include <stdlib.h>
00016 #include <assert.h>
00017 #include <time.h>
00018 #include <atomic.h>
00019 
00020 /* limits and configuration settings ******************************************/
00021 
00022 #define TRT_MAX_NUM_PROCESSORS_PER_TILE   16
00023 
00024 #define TRT_SCHEDULER_STACK_SIZE  128
00025 #define TRT_STACK_OVERFLOW_MAGIC  0x02742312
00026 
00027 #define TRT_STATISTICS    1
00028 
00029 #define TRT_ISA_MIPS      0
00030 #define TRT_ISA_I386      1
00031 #define TRT_ISA_SPARC     2
00032 #define TRT_ISA_HPPA      3
00033 
00034 #define WHERE serial_out("line %d of %s\n", __LINE__, __FILE__);
00035 
00036 /* settings from trtconfig.c **************************************************/
00037 
00038 extern int trt_config_stack_size;
00039 
00040 /* data structures ************************************************************/
00041 
00042 typedef struct thread_s thread_t;
00043 typedef struct semaphore_s semaphore_t;
00044 typedef struct processor_s processor_t;
00045 typedef struct mutex_s mutex_t;
00046 typedef struct cond_s cond_t;
00047 typedef struct atexit_s atexit_t;
00048 typedef struct domain_s domain_t;
00049 typedef union  context_s context_t;
00050 typedef struct sym_s sym_t;
00051 typedef struct sym_table_s sym_table_t;
00052 typedef struct thread_table_s thread_table_t;
00053 
00054 struct semaphore_s
00055 {
00056   int count;              /* value of semaphore */
00057   thread_t *blocked_head; /* list of blocked threads */
00058   thread_t *blocked_tail;
00059   int blocked_lock;       /* spin lock for blocked list */
00060   char *name;             /* its name (for debuging) */
00061 };
00062 
00063 struct atexit_s
00064 {
00065   void (*fun[5])(int);    /* functions to be called */
00066   int arg[5];             /* their args */
00067   short count;            /* number of functions */
00068   char free_desc;         /* free thread_t on exit */
00069   char free_stack;        /* free stack on exit */
00070 };
00071 
00072 union context_s
00073 {
00074   jmp_buf context;
00075 };
00076 
00077 struct thread_s
00078 {
00079   context_t context;      /* registers, stack pointer, pc */
00080   int (*start_fun)(int);  /* start function and its argument */
00081   int start_arg;    
00082   int *stack;             /* malloced memory for stack */
00083   int *stack_init_sp;     /* initial sp */
00084   int *stack_magic;       /* for stack overflow testing */
00085   semaphore_t exit;       /* waiting for a thr_join() */
00086   char *name;             /* thread name, is not strdup'ed */
00087   int exit_status;        /* status passed from exit -> join */
00088   int suspension_mode;    /* SUSPEND_DISABLE/SUSPEND_ENABLE */
00089   semaphore_t *suspend_point_sem;
00090   processor_t *processor; /* (last time) running on this proc. */
00091   thread_t *next;         /* to put threads in lists */
00092   semaphore_t *blocked_on;/* blocked on which sem? NULL if not */
00093   atexit_t atexit;        /* things to do on exit */
00094   void (*block_handler)();/* to be called when blocked */
00095   unsigned int id;        /* thread ID: 0, 1, 2, ... */
00096   thread_t *next_table;   /* to put thread in trt_thread_table */
00097   thread_t *prev_table;
00098   unsigned int task_id;   /* written to TRT_TASK_ID on ctx sw */
00099 };
00100 
00101 struct domain_s           /* scheduling domain */
00102 {
00103   int isa;                /* instruction set architecture */
00104   long num_context_switches;/* statistics */
00105   long num_thread_migrates; /* statistics */
00106 };
00107 
00108 struct processor_s
00109 {
00110   int index;                /* unique id: 0, 1, 2, ... */
00111   domain_t *domain;         /* scheduling domain */
00112   int purpose;              /* general or special purpose? */
00113   thread_t *running_thread; /* currently running thread */
00114   thread_t *ready_list_head;/* ready list */
00115   thread_t *ready_list_tail;
00116   int ready_list_lock;
00117   thread_t *schedule_me;    /* "one element ready list" */
00118   thread_t crt0_thread;
00119   int scheduler_stack[TRT_SCHEDULER_STACK_SIZE];  /* stack for scheduler */
00120   void (*volatile idle_handler)(void);            /* called when idle */
00121   unsigned long idle_spin_count;                  /* used for thread stealing heuristic */
00122 };
00123 
00124 struct thread_table_s
00125 {
00126   thread_t *head;     /* first thread */
00127   thread_t *tail;     /* last thread */
00128   int lock;           /* lock for mutual exclusion */
00129 };
00130 
00131 struct mutex_s
00132 {
00133   semaphore_t lock;
00134 };
00135 
00136 struct cond_s
00137 {
00138   semaphore_t queue;
00139 };
00140 
00141 enum suspend_modes
00142 {
00143   SUSPEND_ENABLE = 0, SUSPEND_DISABLE
00144 };
00145 
00146 struct sym_s
00147 {
00148   int isa;        /* which architecture */
00149   int hash;       /* hash value */
00150   char *name;     /* symbol name */
00151   void *addr;     /* symbol value */
00152   sym_t *next;    /* to put symbols in lists */
00153 };
00154 
00155 struct sym_table_s
00156 {
00157   int lock;
00158   sym_t *list[19];
00159 };
00160 
00161 extern processor_t *current_processor;
00162 #define get_current_processor()   (current_processor)
00163 #define set_current_processor(p)  (current_processor = (p))
00164 
00165 extern int trt_tile_idx;
00166 
00167 /* semaphore/mutex/condition variable initializers */
00168 #define SEM_INITIALIZER(c, n)     {(c), 0, 0, 0, (n)}
00169 #define MUT_INITIALIZER           {SEM_INITIALIZER(1, "mut")}
00170 #define CND_INITIALIZER           {SEM_INITIALIZER(0, "cnd")}
00171 
00172 /* force load of volatile thread_t * variable (which is not declared as volatile) 
00173  */
00174 #define force_load(var)                   \
00175 (                 \
00176   *(thread_t * volatile *) &(var)         \
00177 )
00178 
00179 #if __cplusplus
00180 extern "C" {
00181 #endif
00182 
00183 /* system functions ***********************************************************/
00184 
00185 /*
00186  * initialize processor for trt. should be called on every processor.
00187  */
00188 void trt_init(int *stack_bot, int *stack_top);
00189 
00190 /*
00191  * return number of tiles in system.
00192  */
00193 int trt_num_tiles();
00194 
00195 /*
00196  * set scheduling domain for a processor.
00197  */
00198 void trt_set_scheduling_domain(int processor_index, domain_t *domain);
00199 
00200 /*
00201  * return scheduling domain for a processor.
00202  */
00203 domain_t *trt_scheduling_domain(int processor_index);
00204 
00205 /*
00206  * move thread to processor of specified scheduling domain.
00207  */
00208 void thr_migrate_domain(thread_t *thread, domain_t *domain);
00209 
00210 /*
00211  * initialize scheduling domain.
00212  */
00213 void trt_init_scheduling_domain(domain_t *domain, int isa);
00214 
00215 /*
00216  * return index of processor on which this function is called.
00217  */
00218 static inline int trt_processor_index()
00219 {
00220   return get_current_processor()->index;
00221 }
00222 
00223 /*
00224  * return index of the tile on which this function is called.
00225  */
00226 static inline int trt_tile_index()
00227 {
00228   return trt_tile_idx;
00229 }
00230 
00231 /* thread management functions ************************************************/
00232 
00233 /*
00234  * create a new thread. parameters are start function and its argument.
00235  * the thread has to be started with thr_start and will be executed on
00236  * the same architecture as the calling processor.
00237  */
00238 void thr_create(thread_t *new_thread, int (*fun)(int), int arg);
00239 
00240 /*
00241  * destroy a thread. it is only necessary to call this function if
00242  * the thread did not do an thr_exit() itself. you should only call this
00243  * function when the thread is blocked or suspended.
00244  */
00245 void thr_destroy(thread_t *thread);
00246 
00247 /*
00248  * create a new thread for specified architecture.
00249  */
00250 //void thr_create_isa(thread_t *new_thread, int isa, char *fun_name, int arg);
00251 
00252 void thr_stack_size(thread_t *thread, int size);
00253 
00254 void thr_stack_addr(thread_t *thread, void *addr);
00255 
00256 /*
00257  * lookup thread in trt_thread_table.
00258  */
00259 thread_t *thr_lookup(int id);
00260 
00261 /*
00262  * set cache and ddr domain of thread
00263  */
00264 void thr_set_cache_ddr_domain(thread_t *thread, int cache_domain, 
00265                                                 int ddr_domain);
00266 
00267 /*
00268  * exit current thread. exit status is passed to thread that joins this thread.
00269  */
00270 void thr_exit(int exit_status);
00271 
00272 /*
00273  * call fun(arg) on exit of this thread.
00274  */
00275 void thr_atexit(thread_t *thread, void (*fun)(int), int arg);
00276 
00277 /*
00278  * remote function from at exit list. execute it optionally.
00279  */
00280 void thr_atexit_pop(thread_t *thread, int execute);
00281 
00282 /*
00283  * call this function on blocking of this thread.
00284  */
00285 void thr_onblock(thread_t *thread, void (*fun)(void));
00286 
00287 /*
00288  * call this function when tile is idle.
00289  */
00290 void trt_onidle(void (*fun)(void));
00291 
00292 /*
00293  * return load on tile (number of running/ready threads).
00294  */
00295 int trt_load();
00296 
00297 /*
00298  * return number of (general purpose) processors of type ISA.
00299  */
00300 int trt_num_procs(int isa);
00301 
00302 /*
00303  * are there no running threads?
00304  */
00305 int trt_is_idle();
00306 
00307 /*
00308  * start newly created thread.
00309  */
00310 void thr_start(thread_t *thread);
00311 
00312 /*
00313  * stop thread. thread has to be suspended first.
00314  */
00315 void thr_stop(thread_t *thread, int status);
00316 
00317 /*
00318  * suspend thread execution.
00319  */
00320 void thr_suspend(thread_t *thread);
00321 
00322 /*
00323  * resume thread execution.
00324  */
00325 void thr_resume(thread_t *thread);
00326 
00327 /*
00328  * restart process with specified function and argument. thread has to be
00329  * suspended first.
00330  */
00331 void thr_restart(thread_t *thread, int (*fun)(int), int arg);
00332 
00333 /*
00334  * suspend myself (helper function for thr_suspend_point)
00335  */
00336 void thr_suspend_me();
00337 
00338 /*
00339  * suspend in case there is a suspension request pending. 
00340  */
00341 static inline void thr_suspend_point()
00342 {
00343   if(get_current_processor()->running_thread->suspend_point_sem)
00344     thr_suspend_me(); 
00345 }
00346 
00347 /*
00348  * set suspend mode (SUSPEND_ENABLE, SUSPEND_DISABLE). return prev mode.
00349  */
00350 int thr_suspend_mode(thread_t *thread, int mode);
00351 
00352 /*
00353  * wait until specified thread exits. 
00354  */
00355 void thr_join(thread_t *thread, int *exit_status);
00356 
00357 /*
00358  * do a context switch, ie. give up processor.
00359  */
00360 void thr_switch();
00361 
00362 /*
00363  * specify thread name.
00364  */
00365 void thr_set_name(thread_t *thread, char *name);
00366 
00367 
00368 /* 
00369  * return thread name.
00370  */
00371 static inline char *thr_name(thread_t *thread)
00372 {
00373         return thread->name;
00374 }
00375 
00376 /*
00377  * return start argument of thread.
00378  */
00379 static inline int thr_argument(thread_t *thread)
00380 {
00381         return thread->start_arg;
00382 }
00383 
00384 /*
00385  * who am i?
00386  */
00387 static inline thread_t *thr_self()
00388 {
00389         return get_current_processor()->running_thread;
00390 }
00391 
00392 /*
00393  * return processor index on which thread is running ([0..N-1]).
00394  */
00395 static inline int thr_processor_index(thread_t *thread)
00396 {
00397   return thread->processor->index;
00398 }
00399 
00400 int thr_isa(thread_t *thread);
00401 char *thr_isa_name(thread_t *thread);
00402 
00403 /* semaphore functions ********************************************************/
00404 
00405 /* 
00406  * initialize semaphore with specified value.
00407  */
00408 void sem_init(semaphore_t *semaphore, int init, char *name);
00409 
00410 /* 
00411  * do a Pn on semaphore.
00412  */
00413 int sem_Pn(semaphore_t *semaphore, int n);
00414 
00415 /*
00416  * reset value of semaphore, return previous value.
00417  */
00418 static inline int sem_reset(semaphore_t *semaphore)
00419 {
00420   return atomic_seti(semaphore->count, 0);
00421 }
00422 
00423 /* 
00424  * do a Vn on semaphore.
00425  */
00426 void sem_Vn(semaphore_t *semaphore, int n);
00427 
00428 /* 
00429  * add me to blocked list of semaphore.
00430  */
00431 void sem_block_me(semaphore_t *semaphore);
00432 
00433 /* 
00434  * remove someone from blocked list of semaphore.
00435  */
00436 void sem_unblock_someone(semaphore_t *semaphore);
00437 
00438 /* 
00439  * do a P on semaphore.
00440  */
00441 static inline void sem_P(semaphore_t *semaphore)
00442 {
00443   if(atomic_subi(semaphore->count, 1) <= 0)
00444     sem_block_me(semaphore);
00445 }
00446 
00447 /* 
00448  * do a V on semaphore.
00449  */
00450 static inline void sem_V(semaphore_t *semaphore)
00451 {
00452   if(atomic_addi(semaphore->count, 1) < 0)
00453     sem_unblock_someone(semaphore);
00454 }
00455 
00456 /* 
00457  * do a Pn on semaphore which should not block (nb = nonblocking).
00458  */
00459 static inline void sem_Pn_nb(semaphore_t *semaphore, int n)
00460 {
00461   atomic_sub(semaphore->count, n);
00462 }
00463 
00464 /* 
00465  * do a Vn on a private semaphore (max one thread blocked).
00466  */
00467 static inline void sem_Vn_priv(semaphore_t *semaphore, int n)
00468 {
00469   if(atomic_add(semaphore->count, n) < 0)
00470     sem_unblock_someone(semaphore);
00471 }
00472 
00473 /*
00474  * try to do a P without blocking. returns true if successful.
00475  */
00476 static inline int sem_tryP(semaphore_t *semaphore)
00477 {
00478   if(atomic_subi(semaphore->count, 1) <= 0)
00479   {
00480     atomic_addi(semaphore->count, 1);
00481 
00482     return 0;
00483   }
00484   
00485   return 1;
00486 }
00487 
00488 /*
00489  * return value of semaphore.
00490  */
00491 static inline int sem_value(semaphore_t *semaphore)
00492 {
00493   return *(volatile int *) &semaphore->count;
00494 }
00495 
00496 
00497 /* mutexes and condition variables functions **********************************/
00498 
00499 /*
00500  * initialize a mutex.
00501  */
00502 static inline void mut_init(mutex_t *mutex)
00503 {
00504   sem_init(&mutex->lock, 1, "mutex");
00505 }
00506 
00507 /*
00508  * lock a mutex.
00509  */
00510 static inline void mut_lock(mutex_t *mutex)
00511 {
00512   sem_P(&mutex->lock);
00513 }
00514 
00515 /*
00516  * unlock a mutex.
00517  */
00518 static inline void mut_unlock(mutex_t *mutex)
00519 {
00520   sem_V(&mutex->lock);
00521 }
00522 
00523 /*
00524  * initialize a condition variable.
00525  */
00526 static inline void cnd_init(cond_t *cond)
00527 {
00528   sem_init(&cond->queue, 0, "cond");
00529 }
00530 
00531 /*
00532  * wait on a condition.
00533  */
00534 static inline void cnd_wait(cond_t *cond, mutex_t *mutex)
00535 {
00536   sem_V(&mutex->lock);
00537   sem_P(&cond->queue);
00538   sem_P(&mutex->lock);
00539 }
00540 
00541 /*
00542  * signal a condition.
00543  */
00544 static inline void cnd_signal(cond_t *cond)
00545 {
00546   if(cond->queue.count < 0)
00547     sem_V(&cond->queue);
00548 }
00549 
00550 /*
00551  * signal a condition to all waiting threads.
00552  */
00553 static inline void cnd_broadcast(cond_t *cond)
00554 {
00555   int count = cond->queue.count;
00556 
00557   while(count-- > 0)
00558     sem_V(&cond->queue);
00559 }
00560 
00561 /* symbol exchange between executables ****************************************/
00562 
00563 void sym_register(char *name, void *addr);
00564 void *sym_query(int isa, char *name, int wait);
00565 void sym_dump();
00566 
00567 /* serial out *****************************************************************/
00568 
00569 void serial_out(char *format, ...);
00570 void trt_putc(int port, char c);
00571 int trt_getc(int port);
00572 
00573 /* panic **********************************************************************/
00574 
00575 void trt_panic(char *error_message);
00576 void trt_panic_d(char *error_message, int arg);
00577 void trt_panic_s(char *error_message, char *arg);
00578 
00579 /* debug stuff ****************************************************************/
00580 
00581 void trt_debug_handler(char *name, void (*handler)(char *), char *help);
00582 void thr_dump_info(thread_t *thread, int header);
00583 
00584 /* our own malloc *************************************************************/
00585 
00586 void *trt_malloc(unsigned int);
00587 void trt_free(void *p);
00588 
00589 #if __cplusplus
00590 }
00591 #endif
00592 #endif

Generated on Wed Feb 15 14:52:39 2006 for yapi by doxygen 1.3.2