int main() { SIM_SLEEP_OFF(); // some variables int corenum = RigelGetCoreNum(); int threadnum = RigelGetThreadNum(); int numcores = RigelGetNumCores(); int numthreads = RigelGetNumThreads(); int th_per_core = RigelGetNumThreadsPerCore(); int th_per_cluster = RigelGetNumThreadsPerCluster(); int rows_per_thread = SIZE / numthreads; // statically divide work up int start = rows_per_thread * threadnum; int end = start + rows_per_thread; int i=0, j=0; // setup on thread 0 if(threadnum == 0) { BARRIER_INIT(&bi); // init values for(i=0;i<SIZE;i++){ for(j=0;j<SIZE;j++){ MATRIX[j][i] = j; } VECTOR[i] = i; RESULT[i] = 0xbeef; } //printf("rpf:%d numthreads:%d\n", rows_per_thread, numthreads); ClearTimer(0); // get started StartTimer(0); atomic_flag_set(&Init_Flag); } // wait for core 0 to finish setup atomic_flag_spin_until_set(&Init_Flag); // do the work for( i=start; i<end; i++ ) { RESULT[i] = MVM(i); } BARRIER_ENTER(&bi); // cleanup on thread 0 if(threadnum == 0) { StopTimer(0); // print results for(i=0; i<SIZE; i++) { RigelPrint(RESULT[i]); } } return 1; }
//NOTE: I'm omitting the key checks in get/setspecific b/c they're not //required by the standard (behavior is undefined). void *pthread_getspecific(pthread_key_t key) { //if(key > __MAX_KEYS_PER_THREAD) // return -EINVAL; __pthread_tls_t * const tls = &(pthread_tls[RigelGetThreadNum()]); //const unsigned int mask = 1U << key; //if(!(tls->valid & (1U << key))) // return -EINVAL; return tls->data[key]; }
//TODO: Need some global structure to track joiners, in order to: //1) Detect deadlock (2 thread try to join() each other) //2) Detect if multiple threads are trying to join() the same thread //Both of these are required for this function by the POSIX standard. int pthread_join(pthread_t thread, void **retval) { if(thread == RigelGetThreadNum()) return EDEADLK; if(thread >= RigelGetNumThreads()) return ESRCH; while(_pt[thread].funcptr != NULL) { //spin } if(retval != NULL) { *retval = _pt[thread].retval; } return 0; }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { for(int i = 0; i < (__MAX_NUM_CORES*___MAX_THREADS_PER_CORE); i++) { if(_pt[i].funcptr == NULL) { //Thread is available *thread = i; RigelBroadcastUpdate(arg, _pt[i].funcarg); RigelBroadcastUpdate(_pt[RigelGetThreadNum()].tid, _pt[i].callingtid); RigelBroadcastUpdate(i, _pt[i].tid); RigelBroadcastUpdate(start_routine, _pt[i].funcptr); //The thread will be polling on this, so it should be the last thing to update. return 0; } } //No threads are available. return EAGAIN; }
int pthread_key_delete(pthread_key_t key) { if(key > __MAX_KEYS_PER_THREAD) return -EINVAL; __pthread_tls_t * const tls = &(pthread_tls[RigelGetThreadNum()]); const unsigned int mask = 1U << key; if(!(tls->valid & mask)) return -EINVAL; tls->valid &= ~mask; unsigned int tries = 0; while((tls->data[key] != NULL) && (tries < PTHREAD_MAX_DESTRUCTOR_ITERATIONS)) { tls->destructors[key](tls->data[key]); tries++; } return 0; }
int pthread_key_create(pthread_key_t *key, void(*destructor)(void *)) { __pthread_tls_t * const tls = &(pthread_tls[RigelGetThreadNum()]); for(unsigned int i = 0; i < __MAX_KEYS_PER_THREAD; i++) { const unsigned int mask = 1U << i; if(!(tls->valid & mask)) { tls->valid |= mask; tls->destructors[i] = destructor; *key = i; return 0; } } return -EAGAIN; //Out of keys. }
void __rigel_premain(void) { int tid = RigelGetThreadNum(); if(tid == 0) { SIM_SLEEP_ON(); SIM_SLEEP_OFF(); _pt[tid].funcptr = (void *)0xFFFFFFFF; //Make sure we don't get a thread spawned on us by accident } else { RigelPrint(0xFEDC); while(1) { while(_pt[tid].funcptr == NULL); void *retval = _pt[tid].funcptr(_pt[tid].funcarg); RigelBroadcastUpdate(retval, _pt[tid].retval); RigelBroadcastUpdate(NULL, _pt[tid].funcptr); } } }
int main(int argc, char *argv[]) { if(RigelGetThreadNum() == 0) { SIM_SLEEP_OFF(); } void *mallocs[100]; for(int i = 0; i < 100; i++) { mallocs[i] = malloc(RigelRandUInt(4, 2000)*4); RigelPrint(i); } for(int i = 0; i < 100; i++) { free(mallocs[i]); RigelPrint(0xFFFF0000 | i); } //SIM_SLEEP_OFF(); //} return 0; }
struct _reent * __getreent (void) { return __reent_ptrs[RigelGetThreadNum()]; }