00001
00002
00003
00004
00005
00006
00007
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
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
00037
00038 extern int trt_config_stack_size;
00039
00040
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;
00057 thread_t *blocked_head;
00058 thread_t *blocked_tail;
00059 int blocked_lock;
00060 char *name;
00061 };
00062
00063 struct atexit_s
00064 {
00065 void (*fun[5])(int);
00066 int arg[5];
00067 short count;
00068 char free_desc;
00069 char free_stack;
00070 };
00071
00072 union context_s
00073 {
00074 jmp_buf context;
00075 };
00076
00077 struct thread_s
00078 {
00079 context_t context;
00080 int (*start_fun)(int);
00081 int start_arg;
00082 int *stack;
00083 int *stack_init_sp;
00084 int *stack_magic;
00085 semaphore_t exit;
00086 char *name;
00087 int exit_status;
00088 int suspension_mode;
00089 semaphore_t *suspend_point_sem;
00090 processor_t *processor;
00091 thread_t *next;
00092 semaphore_t *blocked_on;
00093 atexit_t atexit;
00094 void (*block_handler)();
00095 unsigned int id;
00096 thread_t *next_table;
00097 thread_t *prev_table;
00098 unsigned int task_id;
00099 };
00100
00101 struct domain_s
00102 {
00103 int isa;
00104 long num_context_switches;
00105 long num_thread_migrates;
00106 };
00107
00108 struct processor_s
00109 {
00110 int index;
00111 domain_t *domain;
00112 int purpose;
00113 thread_t *running_thread;
00114 thread_t *ready_list_head;
00115 thread_t *ready_list_tail;
00116 int ready_list_lock;
00117 thread_t *schedule_me;
00118 thread_t crt0_thread;
00119 int scheduler_stack[TRT_SCHEDULER_STACK_SIZE];
00120 void (*volatile idle_handler)(void);
00121 unsigned long idle_spin_count;
00122 };
00123
00124 struct thread_table_s
00125 {
00126 thread_t *head;
00127 thread_t *tail;
00128 int lock;
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;
00149 int hash;
00150 char *name;
00151 void *addr;
00152 sym_t *next;
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
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
00173
00174 #define force_load(var) \
00175 ( \
00176 *(thread_t * volatile *) &(var) \
00177 )
00178
00179 #if __cplusplus
00180 extern "C" {
00181 #endif
00182
00183
00184
00185
00186
00187
00188 void trt_init(int *stack_bot, int *stack_top);
00189
00190
00191
00192
00193 int trt_num_tiles();
00194
00195
00196
00197
00198 void trt_set_scheduling_domain(int processor_index, domain_t *domain);
00199
00200
00201
00202
00203 domain_t *trt_scheduling_domain(int processor_index);
00204
00205
00206
00207
00208 void thr_migrate_domain(thread_t *thread, domain_t *domain);
00209
00210
00211
00212
00213 void trt_init_scheduling_domain(domain_t *domain, int isa);
00214
00215
00216
00217
00218 static inline int trt_processor_index()
00219 {
00220 return get_current_processor()->index;
00221 }
00222
00223
00224
00225
00226 static inline int trt_tile_index()
00227 {
00228 return trt_tile_idx;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238 void thr_create(thread_t *new_thread, int (*fun)(int), int arg);
00239
00240
00241
00242
00243
00244
00245 void thr_destroy(thread_t *thread);
00246
00247
00248
00249
00250
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
00258
00259 thread_t *thr_lookup(int id);
00260
00261
00262
00263
00264 void thr_set_cache_ddr_domain(thread_t *thread, int cache_domain,
00265 int ddr_domain);
00266
00267
00268
00269
00270 void thr_exit(int exit_status);
00271
00272
00273
00274
00275 void thr_atexit(thread_t *thread, void (*fun)(int), int arg);
00276
00277
00278
00279
00280 void thr_atexit_pop(thread_t *thread, int execute);
00281
00282
00283
00284
00285 void thr_onblock(thread_t *thread, void (*fun)(void));
00286
00287
00288
00289
00290 void trt_onidle(void (*fun)(void));
00291
00292
00293
00294
00295 int trt_load();
00296
00297
00298
00299
00300 int trt_num_procs(int isa);
00301
00302
00303
00304
00305 int trt_is_idle();
00306
00307
00308
00309
00310 void thr_start(thread_t *thread);
00311
00312
00313
00314
00315 void thr_stop(thread_t *thread, int status);
00316
00317
00318
00319
00320 void thr_suspend(thread_t *thread);
00321
00322
00323
00324
00325 void thr_resume(thread_t *thread);
00326
00327
00328
00329
00330
00331 void thr_restart(thread_t *thread, int (*fun)(int), int arg);
00332
00333
00334
00335
00336 void thr_suspend_me();
00337
00338
00339
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
00349
00350 int thr_suspend_mode(thread_t *thread, int mode);
00351
00352
00353
00354
00355 void thr_join(thread_t *thread, int *exit_status);
00356
00357
00358
00359
00360 void thr_switch();
00361
00362
00363
00364
00365 void thr_set_name(thread_t *thread, char *name);
00366
00367
00368
00369
00370
00371 static inline char *thr_name(thread_t *thread)
00372 {
00373 return thread->name;
00374 }
00375
00376
00377
00378
00379 static inline int thr_argument(thread_t *thread)
00380 {
00381 return thread->start_arg;
00382 }
00383
00384
00385
00386
00387 static inline thread_t *thr_self()
00388 {
00389 return get_current_processor()->running_thread;
00390 }
00391
00392
00393
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
00404
00405
00406
00407
00408 void sem_init(semaphore_t *semaphore, int init, char *name);
00409
00410
00411
00412
00413 int sem_Pn(semaphore_t *semaphore, int n);
00414
00415
00416
00417
00418 static inline int sem_reset(semaphore_t *semaphore)
00419 {
00420 return atomic_seti(semaphore->count, 0);
00421 }
00422
00423
00424
00425
00426 void sem_Vn(semaphore_t *semaphore, int n);
00427
00428
00429
00430
00431 void sem_block_me(semaphore_t *semaphore);
00432
00433
00434
00435
00436 void sem_unblock_someone(semaphore_t *semaphore);
00437
00438
00439
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
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
00458
00459 static inline void sem_Pn_nb(semaphore_t *semaphore, int n)
00460 {
00461 atomic_sub(semaphore->count, n);
00462 }
00463
00464
00465
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
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
00490
00491 static inline int sem_value(semaphore_t *semaphore)
00492 {
00493 return *(volatile int *) &semaphore->count;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502 static inline void mut_init(mutex_t *mutex)
00503 {
00504 sem_init(&mutex->lock, 1, "mutex");
00505 }
00506
00507
00508
00509
00510 static inline void mut_lock(mutex_t *mutex)
00511 {
00512 sem_P(&mutex->lock);
00513 }
00514
00515
00516
00517
00518 static inline void mut_unlock(mutex_t *mutex)
00519 {
00520 sem_V(&mutex->lock);
00521 }
00522
00523
00524
00525
00526 static inline void cnd_init(cond_t *cond)
00527 {
00528 sem_init(&cond->queue, 0, "cond");
00529 }
00530
00531
00532
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
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
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
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
00568
00569 void serial_out(char *format, ...);
00570 void trt_putc(int port, char c);
00571 int trt_getc(int port);
00572
00573
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
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
00585
00586 void *trt_malloc(unsigned int);
00587 void trt_free(void *p);
00588
00589 #if __cplusplus
00590 }
00591 #endif
00592 #endif