void * testThreadWithMeasurement (void * arg) { thread_arg_t * my_arg; my_arg = (thread_arg_t *)arg; Huint tid; tid = hthread_self(); // Atomically increment counter (protected by data_mutex) dbg_printf("LOAD w/ measure TID %d, incrementing counter (%d -> %d) \n",tid,my_arg->counter,my_arg->counter+1); hthread_mutex_lock(&my_arg->data_mutex); my_arg->counter = my_arg->counter + 1; hthread_mutex_unlock(&my_arg->data_mutex); // Grab and release block mutex (protected by block_mutex) - should be pre-locked by main thread dbg_printf("LOAD w/ measure TID %d, locking block mutex\n",tid); my_arg->measure_lock_start = readTimer( ); hthread_mutex_lock(&my_arg->block_mutex); my_arg->measure_lock_stop = readTimer( ); dbg_printf("LOAD w/ measure TID %d, unlocking block mutex\n",tid); hthread_mutex_unlock(&my_arg->block_mutex); //hthread_exit( NULL ); return NULL; }
int main(int argc, char *argv[]) { hthread_mutexattr_t mutexAttr; hthread_mutex_t mutex; hthread_attr_t threadAttr; hthread_t thread; Huint arg; log_t log; //Initialize Log log_create( &log, 1024 ); //Mutex operations printf( "Starting mutex operations\n" ); hthread_mutexattr_init( &mutexAttr ); hthread_mutexattr_setnum( &mutexAttr, 0 ); hthread_mutexattr_getnum( &mutexAttr, &arg ); hthread_mutexattr_destroy( &mutexAttr ); hthread_mutex_init(&mutex, NULL); hthread_mutex_lock( &mutex ); hthread_mutex_unlock( &mutex ); hthread_mutex_trylock( &mutex ); hthread_mutex_unlock( &mutex ); hthread_mutex_destroy( &mutex ); //Condition Variable operations /* printf( "Starting condition variable operations\n" ); hthread_condattr_init( &condvarAttr ); hthread_condattr_setnum( &condvarAttr, 0 ); hthread_condattr_getnum( &condvarAttr, &arg ); hthread_condattr_destroy( &condvarAttr ); hthread_cond_init( &condvar, NULL ); hthread_mutex_lock( &mutex ); hthread_cond_wait( &condvar, &mutex ); hthread_mutex_unlock( &mutex ); hthread_cond_signal( &condvar ); hthread_cond_broadcast( &condvar ); hthread_cond_destroy( &condvar ); */ //Thread operations printf( "Starting thread operations\n" ); hthread_attr_init( &threadAttr ); hthread_create( &thread, &threadAttr, foo, &log ); hthread_attr_destroy( &threadAttr ); hthread_join( thread, NULL ); printf( " -- End of Program --\n" ); log_close_ascii( &log ); return 0; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int hthread_release_lock( LOCK* plk, const char* location ) { int rc; ILOCK* ilk; ilk = (ILOCK*) plk->ilk; rc = hthread_mutex_unlock( &ilk->lock ); PTTRACE( "unlock", plk, NULL, location, rc ); if (rc) loglock( ilk, rc, "release_lock", location ); hthread_mutex_lock( &ilk->locklock ); ilk->location = "null:0"; ilk->tid = 0; hthread_mutex_unlock( &ilk->locklock ); return rc; }
void cons_start( cons_struct *cons ) { hthread_mutex_lock( cons->mutex ); while( *cons->ready == 0 ) hthread_cond_wait( cons->start, cons->mutex ); *cons->ready = 0; hthread_mutex_unlock( cons->mutex ); }
void* thread_dispatcher( void *a ) { Huint tid; argument *arg; tid = hthread_self(); arg = (argument*)a; printf( "Starting Dispatcher Thread: (TID=%u)\n", tid ); while( 1 ) { hthread_mutex_lock( arg->mutex ); while( arg->jobs >= 10 ) { //printf( "Queue Full: (JOBS=%u)\n", arg->jobs ); hthread_cond_wait( arg->cond_notfull, arg->mutex ); } printf( "Creating Job: (TID=%u) (JOBS=%u)\n", tid, arg->jobs ); arg->jobs = arg->jobs + 1; //printf( "Queue Not Empty: (TID=%u) (JOBS=%u)\n", tid, arg->jobs ); hthread_cond_signal( arg->cond_notempty ); hthread_yield(); hthread_mutex_unlock( arg->mutex ); } printf( "Exiting Dispatcher Thread: (TID=%u)\n", tid ); return NULL; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int hthread_obtain_wrlock( RWLOCK* plk, const char* location ) { int rc; U64 waitdur; ILOCK* ilk; TIMEVAL tv; ilk = (ILOCK*) plk->ilk; PTTRACE( "wrlock before", plk, NULL, location, PTT_MAGIC ); rc = hthread_rwlock_trywrlock( &ilk->rwlock ); if (EBUSY == rc) { waitdur = host_tod(); rc = hthread_rwlock_wrlock( &ilk->rwlock ); gettimeofday( &tv, NULL ); waitdur = host_tod() - waitdur; } else { gettimeofday( &tv, NULL ); waitdur = 0; } PTTRACE2( "wrlock after", plk, (void*) waitdur, location, rc, &tv ); if (rc) loglock( ilk, rc, "obtain_wrlock", location ); if (!rc || EOWNERDEAD == rc) { hthread_mutex_lock( &ilk->locklock ); ilk->location = location; ilk->tid = hthread_self(); memcpy( &ilk->time, &tv, sizeof( TIMEVAL )); hthread_mutex_unlock( &ilk->locklock ); } return rc; }
void * measureThread (void * arg) { thread_arg_t * my_arg; my_arg = (thread_arg_t *)arg; Huint tid; volatile Hint * counter = &my_arg->counter; tid = hthread_self(); // Pre-lock blocking mutex dbg_printf("MEASURE THREAD : Timing lock of block mutex\n"); my_arg->lock_start = readTimer( ); hthread_mutex_lock(&my_arg->block_mutex); my_arg->lock_stop = readTimer( ); // Wait for all threads to block (i.e. wait for counter to reach limit) dbg_printf("### Waiting for counter value to be reached ###\n"); while (*counter < my_arg->num_load_threads) { dbg_printf("Measurement thread yielding...(counter = %d)\n",my_arg->counter); //hthread_yield(); } dbg_printf("### Counter value reached ###\n"); // (**B**) Unlock blocking mutex dbg_printf("MEASURE THREAD : Timing unlock of block mutex\n"); my_arg->unlock_start = readTimer( ); hthread_mutex_unlock(&my_arg->block_mutex); my_arg->unlock_stop = readTimer( ); //hthread_exit( NULL ); return NULL; }
/*-------------------------------------------------------------------*/ static void* ptt_timeout( void* arg ) { struct timeval now; struct timespec tm; UNREFERENCED( arg ); // "Thread id "TIDPAT", prio %2d, name %s started" WRMSG( HHC00100, "I", thread_id(), get_thread_priority(0),"PTT timeout timer"); hthread_mutex_lock( &ptttolock ); /* Wait for timeout period to expire */ gettimeofday( &now, NULL ); tm.tv_sec = now.tv_sec + pttto; tm.tv_nsec = now.tv_usec * 1000; hthread_cond_timedwait( &ptttocond, &ptttolock, &tm ); /* Print the trace table automatically */ if (hthread_equal( thread_id(), ptttotid )) { ptt_pthread_print(); pttto = 0; ptttotid = 0; } hthread_mutex_unlock( &ptttolock ); // "Thread id "TIDPAT", prio %2d, name %s ended" WRMSG( HHC00101, "I", thread_id(), get_thread_priority(0), "PTT timeout timer"); return NULL; }
void * min_thread(void * arg) { targ_t * targ = (targ_t *)(arg); // Calculate local minimum int i,end; float local_min = 10000000; float val; end = targ->num_items; for (i = 0; i < end; i++) { val = targ->data_ptr[i]; if (val < local_min) local_min = val; } /* get permission, update min, and unlock */ hthread_mutex_lock(targ->min_mutex); if ( local_min < *(targ->min)) { *(targ->min) = local_min; } hthread_mutex_unlock(targ->min_mutex); return (void*)(10); }
void* thread_worker( void *a ) { Huint tid; argument *arg; tid = hthread_self(); arg = (argument*)a; printf( "Starting Worker Thread: (TID=%u)\n", tid ); while( 1 ) { hthread_mutex_lock( arg->mutex ); while( arg->jobs == 0 ) { //printf( "Queue Empty: (TID=%u)\n", tid ); hthread_cond_wait( arg->cond_notempty, arg->mutex ); } arg->jobs = arg->jobs - 1; //printf( "Queue Not Full: (TID=%u) (JOBS=%u)\n",tid, arg->jobs ); hthread_cond_signal( arg->cond_notfull ); printf( "Running Job: (TID=%u) (JOBS=%u)\n",tid,arg->jobs ); hthread_yield(); hthread_mutex_unlock( arg->mutex ); } printf( "Exiting Worker Thread: (TID=%u)\n", tid ); return NULL; }
void* child( void *arg ) { Huint i; hthread_t self; hthread_mutex_t *mutex; mutex = (hthread_mutex_t*)arg; self = hthread_self(); for( i = 0; i < LOOP; i++ ) { hthread_mutex_lock( mutex ); #ifdef PRINT printf( "Locked Mutex: %u %u\n", self, i ); #endif // hthread_yield(); hthread_mutex_unlock( mutex ); printf( "Yielding: %u ...\n", self ); hthread_yield(); } return NULL; }
void * a_thread_function(void * arg) { struct test_data * data = (struct test_data *) arg; hthread_mutex_lock( data->mutex ); hthread_cond_signal( data->cond ); hthread_mutex_unlock( data->mutex); return NULL; }
void *handle_requests_loop(void *data) { int rs; struct task *task; struct threadpool * tp = (struct threadpool *)data; // Pre-lock mutex rs = hthread_mutex_lock(tp->task_queue_mutex); while (1) { // Check to see if there are any tasks to execute if (tp->total_tasks > 0) { // If so, then grab one task = get_task(tp); aprintf("TID %d, got task!\n",hthread_self()); if (task) { // If the task is valid, then release lock rs = hthread_mutex_unlock(tp->task_queue_mutex); // Execute task execute_task(task); free(task); // Yield to allow another thread to do some work if possible hthread_yield(); // Re-acquire for next round rs = hthread_mutex_lock(tp->task_queue_mutex); } else { // Otherwise, wait for tasks rs = hthread_cond_wait(tp->active_task, tp->task_queue_mutex); } } else { // Release lock and processor, let someone else do some work hthread_mutex_unlock(tp->task_queue_mutex); hthread_yield(); // Re-acquire hthread_mutex_lock(tp->task_queue_mutex); } } return (void*)99; }
// An "atomic" printf function. Any process calling this function spins // on the global print_mutex; this prevents the output from printfs by // physically concurrent threads from being interleaved. void aprintf(char* fmt, ...) { va_list args; va_start(args, fmt); wait_on_lock(&print_mutex); vprintf(fmt, args); hthread_mutex_unlock(&print_mutex); va_end(args); }
void * thread( void * arg ) { struct arguments * myArgs = (struct arguments*) arg; Hint retval; retval = hthread_mutex_lock( myArgs->mutex ); myArgs->value += 10; retval = hthread_mutex_unlock( myArgs->mutex ); return NULL; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int hthread_test_lock( LOCK* plk, const char* location ) { int rc; ILOCK* ilk; UNREFERENCED( location ); ilk = (ILOCK*) plk->ilk; rc = hthread_mutex_trylock( &ilk->lock ); if (rc) return rc; hthread_mutex_unlock( &ilk->lock ); return 0; }
void * a_thread_function(void * arg) { struct testdata * data = (struct testdata *) arg; printf( "Thread %d Running\n", (int)hthread_self() ); hthread_mutex_lock( data->mutex ); *(data->start_num) += 1; hthread_cond_wait( data->cond, data->mutex ); *(data->waken_num) += 1; hthread_mutex_unlock( data->mutex); return NULL; }
void * testThread ( void * arg ) { int retVal; struct test_data * data = (struct test_data *) arg; hthread_mutex_lock( data->mutex ); hthread_create( &data->thread, NULL, data->function, (void *) data ); retVal = hthread_cond_wait( data->cond, data->mutex ); hthread_mutex_unlock( data->mutex ); hthread_join( data->thread, NULL ); hthread_exit( (void *) retVal ); return NULL; }
void* findFibonacci(void * arg) { hthread_attr_t attrBase; hthread_t threadBase; hthread_t threadOne; hthread_t threadTwo; struct fibonacci * fib; struct fibonacci fibOne; struct fibonacci fibTwo; fib = (struct fibonacci *) arg; if (fib->fibNum == 0 || fib->fibNum == 1) { //Set up the attr for a HW thread hthread_attr_init( &attrBase ); hthread_attr_sethardware( &attrBase, HWTI_BASEADDR ); //since there is only one HWTI, perform a mutex lock on it. //then create the HW thread hthread_mutex_lock( &hwtiMutex ); //hthread_create(&threadBase, NULL, findFibHWTI, (void*)fib); //readHWTStatus(); //resetHWT(); //printf( "fibVal is %d\n", fib->fibVal ); printf( "fib address is %x, %x, %x\n", (Huint)fib, (Huint)(&fib->fibNum), (Huint)(&fib->fibVal) ); hthread_create(&threadBase, &attrBase, NULL, arg); //Clean up the attr hthread_attr_destroy( &attrBase ); //Wait for HW thread to finish ... and unlock mutex hthread_join(threadBase, NULL); //readHWTStatus(); printf( "fibVal is %d\n", fib->fibVal ); hthread_mutex_unlock( &hwtiMutex ); } else { fibOne.fibNum = fib->fibNum - 1; fibTwo.fibNum = fib->fibNum - 2; hthread_create(&threadOne, NULL, findFibonacci, (void*)&fibOne); hthread_create(&threadTwo, NULL, findFibonacci, (void*)&fibTwo); hthread_join(threadOne, NULL); hthread_join(threadTwo, NULL); fib->fibVal = fibOne.fibVal + fibTwo.fibVal; } return NULL; }
int main( int argc, char *argv[] ) { hthread_t tid, sw1, sw2; hthread_attr_t hw1Attr, sw1Attr, sw2Attr; hthread_mutex_t mutex; Huint retval; struct arguments myArgs; hthread_attr_init( &hw1Attr ); hthread_attr_init( &sw1Attr ); hthread_attr_init( &sw2Attr ); hthread_attr_sethardware( &hw1Attr, HWTI_BASEADDR ); hthread_mutex_init( &mutex, NULL ); myArgs.mutex = &mutex; retval = hthread_mutex_lock( myArgs.mutex ); // Set the thread's argument data to some value myArgs.value = 1000; // Create two software threads hthread_create( &tid, &hw1Attr, NULL, (void*)(&myArgs) ); hthread_create( &sw1, &sw1Attr, thread, (void*)(&myArgs) ); hthread_create( &sw2, &sw2Attr, thread, (void*)(&myArgs) ); hthread_yield(); // HWT should be blocked readHWTStatus(); retval = hthread_mutex_unlock( myArgs.mutex ); hthread_join( tid, (void*)(&retval) ); hthread_join( sw1, (void*)(&retval) ); hthread_join( sw2, (void*)(&retval) ); readHWTStatus(); // Clean up the attribute structure hthread_attr_destroy( &hw1Attr ); hthread_attr_destroy( &sw1Attr ); hthread_attr_destroy( &sw2Attr ); // Print out value of arg, and a successful exit message printf( "After joins arg = %d\n", myArgs.value); printf( "-- QED --\n" ); // Return from main return 1; }
void * testThread ( void * arg ) { int retVal; hthread_mutex_t * mutex = (hthread_mutex_t *) arg; //Test that after trylock returns, on an unlocked mutex, the calling thread owns the mutex hthread_mutex_trylock( mutex ); if ( _mutex_owner( mutex->num ) == hthread_self() ) retVal = SUCCESS; else retVal = FAILURE; hthread_mutex_unlock( mutex ); hthread_exit( (void *) retVal ); return NULL; }
void * testThread ( void * arg ) { int retVal, i; struct testdata * data = (struct testdata *) arg; for( i=0; i<THREAD_NUM; i++ ) hthread_create( &data->thread[i], NULL, data->function, (void *) data ); while( *(data->start_num) != THREAD_NUM ) hthread_yield(); hthread_mutex_lock( data->mutex ); hthread_cond_broadcast( data->cond ); hthread_mutex_unlock( data->mutex ); for( i=0; i<THREAD_NUM; i++ ) hthread_join( data->thread[i], NULL ); retVal = *(data->waken_num); hthread_exit( (void *) retVal ); return NULL; }
/*-------------------------------------------------------------------*/ DLL_EXPORT int hthread_try_obtain_wrlock( RWLOCK* plk, const char* location ) { int rc; ILOCK* ilk; TIMEVAL tv; ilk = (ILOCK*) plk->ilk; PTTRACE( "trywr before", plk, NULL, location, PTT_MAGIC ); rc = hthread_rwlock_trywrlock( &ilk->rwlock ); gettimeofday( &tv, NULL ); PTTRACE2( "trywr after", plk, NULL, location, rc, &tv ); if (rc && EBUSY != rc) loglock( ilk, rc, "try_obtain_wrlock", location ); if (!rc) { hthread_mutex_lock( &ilk->locklock ); ilk->location = location; ilk->tid = hthread_self(); memcpy( &ilk->time, &tv, sizeof( TIMEVAL )); hthread_mutex_unlock( &ilk->locklock ); } return rc; }
void* child( void *arg ) { hthread_t self; hthread_mutex_t *mutex; mutex = (hthread_mutex_t*)arg; self = hthread_self(); printf( "Starting Child: %u\n", self ); while( 1 ) { hthread_mutex_lock( mutex ); hthread_yield(); printf( "Locked Mutex: %u\n", self ); hthread_yield(); hthread_mutex_unlock( mutex ); hthread_yield(); } return NULL; }
void add_task(struct threadpool * tp, int task_num, void (*fp) (void *), void * data) { struct task *enqueue_task; int rs; // Create task structure to add to work queue enqueue_task = (struct task *) malloc(sizeof(struct task)); if (!enqueue_task) { tp->request_errors++; return; } enqueue_task->task_id = task_num; enqueue_task->function_pointer = fp; enqueue_task->data = data; enqueue_task->next = NULL; // Lock mutex to update shared queue info rs = hthread_mutex_lock(tp->task_queue_mutex); if (tp->total_tasks == 0) { tp->head_ptr = enqueue_task; tp->tail_ptr = enqueue_task; } else { tp->tail_ptr->next = enqueue_task; tp->tail_ptr = enqueue_task; } tp->total_tasks++; // Release mutex and signal worker threads rs = hthread_mutex_unlock(tp->task_queue_mutex); rs = hthread_cond_signal(tp->active_task); }
/*-------------------------------------------------------------------*/ DLL_EXPORT int ptt_cmd(int argc, char *argv[], char* cmdline) { int rc = 0; int n, to = -1; char c; UNREFERENCED(cmdline); if (argc > 1) { /* process arguments; last arg can be trace table size */ for (--argc, argv++; argc; --argc, ++argv) { if (strcasecmp("opts", argv[0]) == 0) continue; else if (strcasecmp("error", argv[0]) == 0) { pttclass |= PTT_CL_ERR; continue; } else if (strcasecmp("noerror", argv[0]) == 0) { pttclass &= ~PTT_CL_ERR; continue; } else if (strcasecmp("control", argv[0]) == 0) { pttclass |= PTT_CL_INF; continue; } else if (strcasecmp("nocontrol", argv[0]) == 0) { pttclass &= ~PTT_CL_INF; continue; } else if (strcasecmp("prog", argv[0]) == 0) { pttclass |= PTT_CL_PGM; continue; } else if (strcasecmp("noprog", argv[0]) == 0) { pttclass &= ~PTT_CL_PGM; continue; } else if (strcasecmp("inter", argv[0]) == 0) { pttclass |= PTT_CL_CSF; continue; } else if (strcasecmp("nointer", argv[0]) == 0) { pttclass &= ~PTT_CL_CSF; continue; } else if (strcasecmp("sie", argv[0]) == 0) { pttclass |= PTT_CL_SIE; continue; } else if (strcasecmp("nosie", argv[0]) == 0) { pttclass &= ~PTT_CL_SIE; continue; } else if (strcasecmp("signal", argv[0]) == 0) { pttclass |= PTT_CL_SIG; continue; } else if (strcasecmp("nosignal", argv[0]) == 0) { pttclass &= ~PTT_CL_SIG; continue; } else if (strcasecmp("io", argv[0]) == 0) { pttclass |= PTT_CL_IO; continue; } else if (strcasecmp("noio", argv[0]) == 0) { pttclass &= ~PTT_CL_IO; continue; } else if (strcasecmp("timer", argv[0]) == 0) { pttclass |= PTT_CL_TMR; continue; } else if (strcasecmp("notimer", argv[0]) == 0) { pttclass &= ~PTT_CL_TMR; continue; } else if (strcasecmp("logger", argv[0]) == 0) { pttclass |= PTT_CL_LOG; continue; } else if (strcasecmp("nologger", argv[0]) == 0) { pttclass &= ~PTT_CL_LOG; continue; } else if (strcasecmp("nothreads", argv[0]) == 0) { pttclass &= ~PTT_CL_THR; continue; } else if (strcasecmp("threads", argv[0]) == 0) { pttclass |= PTT_CL_THR; continue; } else if (strcasecmp("nolock", argv[0]) == 0) { pttnolock = 1; continue; } else if (strcasecmp("lock", argv[0]) == 0) { pttnolock = 0; continue; } else if (strcasecmp("notod", argv[0]) == 0) { pttnotod = 1; continue; } else if (strcasecmp("tod", argv[0]) == 0) { pttnotod = 0; continue; } else if (strcasecmp("nowrap", argv[0]) == 0) { pttnowrap = 1; continue; } else if (strcasecmp("wrap", argv[0]) == 0) { pttnowrap = 0; continue; } else if (strncasecmp("to=", argv[0], 3) == 0 && strlen(argv[0]) > 3 && (sscanf(&argv[0][3], "%d%c", &to, &c) == 1 && to >= 0)) { pttto = to; continue; } else if (argc == 1 && sscanf(argv[0], "%d%c", &n, &c) == 1 && n >= 0) { OBTAIN_PTTLOCK; if (pttracen == 0) { if (pttrace != NULL) { RELEASE_PTTLOCK; WRMSG(HHC90010, "E"); return -1; } } else if (pttrace) { pttracen = 0; RELEASE_PTTLOCK; usleep(1000); OBTAIN_PTTLOCK; free (pttrace); pttrace = NULL; } ptt_trace_init (n, 0); RELEASE_PTTLOCK; } else { WRMSG(HHC90011, "E", argv[0]); rc = -1; break; } } /* for each ptt argument */ /* wakeup timeout thread if to= specified */ if (to >= 0 && ptttotid) { hthread_mutex_lock (&ptttolock); ptttotid = 0; hthread_cond_signal (&ptttocond); hthread_mutex_unlock (&ptttolock); } /* start timeout thread if positive to= specified */ if (to > 0) { hthread_mutex_lock (&ptttolock); ptttotid = 0; rc = hthread_create (&ptttotid, NULL, ptt_timeout, NULL, "ptt_timeout"); if (rc) WRMSG(HHC00102, "E", strerror(rc)); hthread_mutex_unlock (&ptttolock); } } else { if (pttracen) rc = ptt_pthread_print(); WRMSG(HHC90012, "I", (pttclass & PTT_CL_INF) ? "control " : "", (pttclass & PTT_CL_ERR) ? "error " : "", (pttclass & PTT_CL_PGM) ? "prog " : "", (pttclass & PTT_CL_CSF) ? "inter " : "", (pttclass & PTT_CL_SIE) ? "sie " : "", (pttclass & PTT_CL_SIG) ? "signal " : "", (pttclass & PTT_CL_IO) ? "io " : "", (pttclass & PTT_CL_TMR) ? "timer " : "", (pttclass & PTT_CL_THR) ? "threads " : "", (pttclass & PTT_CL_LOG) ? "logger " : "", pttnolock ? "nolock" : "lock", pttnotod ? "notod" : "tod", pttnowrap ? "nowrap" : "wrap", pttto, pttracen); } return rc; }
int run_tests() { // Timer variables xps_timer_t timer; int time_create, time_start, time_unlock, time_stop; // Mutex hthread_mutex_t * mutex = (hthread_mutex_t*)malloc( sizeof(hthread_mutex_t) ); hthread_mutex_init( mutex, NULL ); float min; // Thread attribute structures Huint sta[NUM_THREADS]; void* retval[NUM_THREADS]; hthread_t tid[NUM_THREADS]; hthread_attr_t attr[NUM_THREADS]; targ_t thread_arg[NUM_THREADS]; // Setup Cache XCache_DisableDCache(); XCache_EnableICache(0xc0000801); // Create timer xps_timer_create(&timer, (int*)0x20400000); // Start timer xps_timer_start(&timer); // ************************************************************************************* extern unsigned char intermediate[]; extern unsigned int min_handle_offset; unsigned int min_handle = (min_handle_offset) + (unsigned int)(&intermediate); // ************************************************************************************* printf("Code start address = 0x%08x\n", (unsigned int)&intermediate); int i = 0; float main_array[ARRAY_LENGTH]; printf("Addr of array = 0x%08x\n",(unsigned int)&main_array[0]); for (i = 0; i < ARRAY_LENGTH; i++) { main_array[i] = (i+2)*3.14f; } int num_items = ARRAY_LENGTH/NUM_THREADS; int extra_items = ARRAY_LENGTH - (num_items*NUM_THREADS); float * start_addr = &main_array[0]; for (i = 0; i < NUM_THREADS; i++) { // Initialize the attributes for the hardware threads hthread_attr_init( &attr[i] ); hthread_attr_sethardware( &attr[i], (void*)base_array[i] ); // Initialize thread arguments thread_arg[i].num_items = num_items; thread_arg[i].data_ptr = start_addr; thread_arg[i].min_mutex = mutex; thread_arg[i].min = &min; start_addr+=num_items; } // Add in extra items for the last thread if needed thread_arg[i-1].num_items += extra_items; int num_ops = 0; for( num_ops = 0; num_ops < 2; num_ops = num_ops + 1) { printf("******* Round %d ********\n",num_ops); #ifdef USE_MB_THREAD printf("**** MB-based Threads ****\n"); #else printf("**** PPC-based Threads ****\n"); #endif min = 9999999; // Lock mutex before hand so that timing will not include thread creation time hthread_mutex_lock(mutex); // Start timing thread create time_create = xps_timer_read_counter(&timer); for (i = 0; i < NUM_THREADS; i++) { // Create the worker threads #ifdef USE_MB_THREAD // Create MB Thread sta[i] = hthread_create( &tid[i], &attr[i], (void*)(min_handle), (void*)(&thread_arg[i]) ); #else // Create SW Thread sta[i] = hthread_create( &tid[i], NULL, min_thread, (void*)(&thread_arg[i]) ); #endif } // Allow created threads to begin running and start timer time_start = xps_timer_read_counter(&timer); hthread_mutex_unlock(mutex); time_unlock = xps_timer_read_counter(&timer); // Wait for the threads to exit //printf( "Waiting for thread(s) to complete... \n" ); for (i = 0; i < NUM_THREADS; i++) { hthread_join( tid[i], &retval[i] ); } time_stop = xps_timer_read_counter(&timer); // Display results printf("Min = %f\n",min); for (i = 0; i < NUM_THREADS; i++) { printf("TID = 0x%08x, status = 0x%08x, retval = 0x%08x\n",tid[i],sta[i],(Huint)retval[i]); } printf("*********************************\n"); printf("Create time = %u\n",time_create); printf("Start time = %u\n",time_start); printf("Unlock time = %u\n",time_unlock); printf("Stop time = %u\n",time_stop); printf("*********************************\n"); printf("Creation time (|Start - Create|) = %u\n",time_start - time_create); printf("Unlock time (|Unlock - Start|) = %u\n",time_unlock - time_start); printf("Elapsed time (|Stop - Start|) = %u\n",time_stop - time_start); } hthread_mutex_destroy( mutex ); free( mutex ); // Clean up the attribute structures for (i = 0; i < NUM_THREADS; i++) { hthread_attr_destroy( &attr[i] ); } printf ("-- Complete --\n"); // Return from main return 0; }