status_t Mutex::unlock() { int result = pthread_mutex_unlock ( & getMutexData() ); switch ( result ) { case 0: /* It worked */ return ::SUCCESS; case EINVAL: FLUSHALL(); cerr << "[Mutex:unlock] Error: [EINVAL] " << "Unable to unlock improperly initialized mutex." << endl; break; case EPERM: /* Mutex::ERROR_CHECK only */ FLUSHALL(); cerr << "[Mutex:unlock] Error: [EPERM] " << "Unable to unlock Mutex: Calling thread does not own the mutex." << endl; break; default: FLUSHALL(); cerr << "[Mutex:lock] Error: pthread_mutex_unlock(.) returned: " << result << "." << endl; break; } return ::FAILURE; }
status_t Mutex::lock() { int result = pthread_mutex_lock ( & getMutexData() ); switch ( result ) { case 0: /* It worked */ return ::SUCCESS; case EINVAL: FLUSHALL(); cerr << "[Mutex:lock] Error: [EINVAL] " << "Unable to lock improperly initialized mutex." << endl; break; case EDEADLK: /* Mutex::ERROR_CHECK only */ FLUSHALL(); cerr << "[Mutex:lock] Error: [EDEADLK] " << "Unable to lock mutex: Mutex already locked by calling thread." << endl; break; default: FLUSHALL(); cerr << "[Mutex:lock] Error: pthread_mutex_lock(.) returned: " << result << "." << endl; break; } return ::FAILURE; }
Mutex::TRY_LOCK_STATUS_T Mutex::trylock() { int result = pthread_mutex_trylock ( & getMutexData() ); switch ( result ) { case 0: /* It worked */ return Mutex::SUCCESS; case EINVAL: FLUSHALL(); cerr << "[Mutex:trylock] Error: [EINVAL] " << "Unable to lock improperly initialized mutex." << endl; break; case EBUSY: /* Already locked */ return Mutex::ALREADY_LOCKED; default: FLUSHALL(); cerr << "[Mutex:lock] Error: pthread_mutex_trylock(.) returned: " << result << "." << endl; break; } return Mutex::FAILURE; }
/*virtual*/ Mutex::~Mutex() { int result; pthread_mutexattr_destroy ( & getMutexAttributes() ); result = pthread_mutex_destroy ( & getMutexData() ); switch ( result ) { case 0: /* It worked */ break; case EBUSY: FLUSHALL(); cerr << "[Mutex:~Mutex] Error: (" << (void*)this << ") [EBUSY] " << "Unable to properly destroy currently lock()'ed Mutex!." << endl; break; default: FLUSHALL(); cerr << "[Mutex:~Mutex] Error: (" << (void *)this << ") pthread_mutex_destroy(.) returned: " << result << "." << endl; break; } }
double benchmark_cache_memory_set(REGISTER void *x, REGISTER long bytes, long *oloops, double *ous) { REGISTER long loops = 0; FLUSHALL(1); keepgoing = 1; assert(signal(SIGALRM,handler) != SIG_ERR); alarm(duration); TIMER_START; while (keepgoing) { memset(x,0xf0,bytes); loops++; } TIMER_STOP; fake_out_optimizations(x,bytes); *ous = TIMER_ELAPSED; *oloops = loops; return((double)loops*(double)bytes); }
double benchmark_cache(REGISTER DATATYPE *x, REGISTER long limit, long *oloops, double *ous) { REGISTER long index = 0, loops = 0; FLUSHALL(1); keepgoing = 1; assert(signal(SIGALRM,handler) != SIG_ERR); alarm(duration); TIMER_START; while (keepgoing) { for (index = 0; index < limit; index++) x[index]++; loops++; } TIMER_STOP; fake_out_optimizations(x,limit*sizeof(DATATYPE)); *oloops = loops; *ous = TIMER_ELAPSED; { double refcnt = ((double)loops*(double)limit); DBG(fprintf(stderr,"T: %ld loops at limit %ld took %f us, %f refs.\n",loops,limit,*ous,refcnt)); return(refcnt); } }
/* Thread two calls this method, which wakes up thread one. * This method does **NOT** block! * * Use wakeupOtherThread(TRUE) if one is uncertain as to * whether another thread is already waiting. Do not do: * if ( getIsThreadWaiting() == TRUE ) wakeupOtherThread(); * As this could lead to a race condition wherein a thread * starts waiting after the getIsThreadWaiting() function. * * The argument name is complex. But I wanted to be able * to use TRUE/TRUE for waitForSignal()/wakeupOtherThread() * in the case where waitForSignal() occurs prior to * the wakeupOtherThread(). * * So, use FALSE to report when no other thread is present, * and TRUE to prevent such reporting. */ status_t Semaphore::wakeupOtherThread( BOOLEAN theDoNotReportIfNoOtherThread /*=FALSE*/) { lock("Semaphore:wakeupOtherThread"); setWakeupAlreadyReceivedNoMutex(); /* Race conditions are a bitch! */ if ( getIsThreadWaitingNoMutex() == FALSE ) { if ( theDoNotReportIfNoOtherThread == FALSE ) { FLUSHALL(); cerr << "[Semaphore:waitForSignal] Warning: " << "No thread is waiting on this Semaphore." << endl; } unlock("Semaphore::waitForSignal"); return FAILURE; } /* Only doing sem_post if we have a thread waiting... */ if ( sem_post ( & getSemaphoreDataNoMutex() ) != 0 ) { PERROR ( "[Semaphore:waitForSignal] Error: sem_post() failed. " ); unlock("Semaphore:wakeupOtherThread"); return FAILURE; } unlock("Semaphore:wakeupOtherThread"); return SUCCESS; }
int main(int argc, char **argv) { DATATYPE *x; long *sizes; double *times, *bws, *percents; type = usage(argc, argv); assert(sizes = (long *)malloc(timeslots*sizeof(long))); memset(sizes,0x00,(timeslots*sizeof(long))); assert(times = (double *)malloc(timeslots*repeat_count*sizeof(double))); memset(times,0x00,(timeslots*repeat_count*sizeof(double))); assert(bws = (double *)malloc(timeslots*repeat_count*sizeof(double))); memset(bws,0x00,(timeslots*repeat_count*sizeof(double))); assert(percents = (double *)malloc(timeslots*repeat_count*sizeof(double))); memset(percents,0x00,(timeslots*repeat_count*sizeof(double))); assert(x = (DATATYPE *)malloc((size_t)memsize)); memset((void *)x,0x00,memsize); initialize_sizes(sizes); /* Measure cache */ if (type & MEMORYSET) { do_memory_set(sizes,x,times,bws,percents); } if (type & MEMORYCOPY) { do_memory_copy(sizes,x,times,bws,percents); } if (type & READONLY) { do_read_only(sizes,x,times,bws,percents); } if (type & WRITEONLY) { do_write_only(sizes,x,times,bws,percents); } if (type & READWRITE) { do_read_write(sizes,x,times,bws,percents); } FLUSHALL(0); exit(0); }
BOOLEAN Mutex::isLocked() { Mutex::TRY_LOCK_STATUS_T tryLockStatus; switch ( tryLockStatus = trylock() ) { case Mutex::SUCCESS: /* We just locked ourself. If unlock fails... * * Well, we are locked... And probably hosed. */ switch ( unlock() ) { case ::SUCCESS: return FALSE; /* If this happens, something truly odd is going on... */ case ::FAILURE: default: FLUSHALL(); cerr << "[Mutex:isLocked] Internal Failure: " << "trylock() returned SUCCESS. unlock() returned FAILURE. " << "(So we've just locked the mutex.)" << endl; return TRUE; } case Mutex::FAILURE: return FALSE; case Mutex::ALREADY_LOCKED: return TRUE; default: FLUSHALL(); cerr << "[Mutex:isLocked] Impossible Error: tryLock() returned: " << int4(tryLockStatus) << ". Assuming we are locked..." << endl; return TRUE; /* Worst case scenario: Assume we are locked. */ } }
/* Convenience method */ Mutex::TRY_LOCK_STATUS_T Mutex::trylock ( const char * theErrorLocation ) { Mutex::TRY_LOCK_STATUS_T returnValue = trylock(); if ( returnValue == Mutex::FAILURE ) { if ( theErrorLocation == (const char *) NULL ) theErrorLocation = ""; FLUSHALL(); cerr << "[" << theErrorLocation << "] Error: " << "Problems while trylock()'ing mutex." << endl; } return returnValue; }
/* Convenience method */ status_t Mutex::unlock( const char * theErrorLocation) { status_t returnValue = unlock(); if ( returnValue != ::SUCCESS ) { if ( theErrorLocation == (const char *) NULL ) theErrorLocation = ""; FLUSHALL(); cerr << "[" << theErrorLocation << "] Error: " << "Unable to unlock mutex." << endl; } return returnValue; }
double hand_benchmark_cache_wonly(REGISTER DATATYPE *x, REGISTER long limit, long *oloops, double *ous) { REGISTER long index = 0, loops = 0; REGISTER DATATYPE wval = (DATATYPE)0xf; FLUSHALL(1); keepgoing = 1; assert(signal(SIGALRM,handler) != SIG_ERR); limit -= 8; wval = (DATATYPE)limit; alarm(duration); TIMER_START; again: x[index] = wval; x[index+1] = wval; x[index+2] = wval; x[index+3] = wval; x[index+4] = wval; x[index+5] = wval; x[index+6] = wval; x[index+7] = wval; if ((index+=8) < limit) goto again; else if (keepgoing) { index = 0; loops++; goto again; } TIMER_STOP; index += 8; fake_out_optimizations(x,limit*sizeof(DATATYPE)); *oloops = loops; *ous = TIMER_ELAPSED; { double refcnt = ((double)loops*(double)limit); DBG(fprintf(stderr,"T: %ld loops at limit %ld took %f us, %f refs.\n",loops,limit,*ous,refcnt)); return(refcnt); } }
double benchmark_cache_ronly(REGISTER DATATYPE *x, REGISTER long limit, long *oloops, double *ous) { REGISTER long index = 0, loops = 0; REGISTER DATATYPE sum = (DATATYPE)0; FLUSHALL(1); keepgoing = 1; assert(signal(SIGALRM,handler) != SIG_ERR); alarm(duration); TIMER_START; #ifdef SOLARIS while (go(-1)) #else while (keepgoing) #endif { for (index = 0; index < limit; index++) { sum += x[index]; } loops++; } TIMER_STOP; x[0] = (DATATYPE)sum; x[1] = (DATATYPE)index; fake_out_optimizations(x,2*sizeof(DATATYPE)); *oloops = loops; *ous = TIMER_ELAPSED; { double refcnt = ((double)loops*(double)limit); DBG(fprintf(stderr,"T: %ld loops at limit %ld took %f us, %f refs.\n",loops,limit,*ous,refcnt)); return(refcnt); } }
Mutex::Mutex ( Mutex::TYPE theMutexType /* = Mutex::RECURSIVE */ ) : threadIostreamBase ( ), mutexType ( theMutexType ) { int mutexAttributeKind; int result; /* It's not paranoia if the computer is really out to get you... */ memset ( & getMutexAttributes(), 0, sizeof(pthread_mutexattr_t) ); memset ( & getMutexData(), 0, sizeof(pthread_mutex_t) ); /* Create the Mutex Attributes */ pthread_mutexattr_init ( & getMutexAttributes() ); /* Decide how we are configuring it. */ switch ( theMutexType ) { case Mutex::FAST: mutexAttributeKind = PTHREAD_MUTEX_FAST_NP; break; case Mutex::RECURSIVE: mutexAttributeKind = PTHREAD_MUTEX_RECURSIVE_NP; break; case Mutex::ERROR_CHECK: mutexAttributeKind = PTHREAD_MUTEX_ERRORCHECK_NP; break; default: FLUSHALL(); cerr << "[Mutex:Mutex] Error: Bad MutexType value: " << int4(theMutexType) << ". Defaulting to RECURSIVE Mutex." << endl; mutexType = Mutex::RECURSIVE; mutexAttributeKind = PTHREAD_MUTEX_RECURSIVE_NP; } /* Configure it appropriately. * * PTHREAD_MUTEX_SETKIND is defined in Mutex.H. */ result = PTHREAD_MUTEX_SETKIND ( & getMutexAttributes(), mutexAttributeKind ); switch ( result ) { case 0: /* It worked */ break; case EINVAL: FLUSHALL(); cerr << "[Mutex:Mutex(Mutex::TYPE)] Programmer Error: " << "pthread_mutexattr_setkind_np(., " << mutexAttributeKind << ") failed with EINVAL. Attempting to continue as FAST MUTEX." << endl; mutexType = Mutex::FAST; break; default: /* What the hell? */ FLUSHALL(); cerr << "[Mutex:Mutex(Mutex::TYPE)] UNKNOWN Error: " << "pthread_mutexattr_setkind_np(., " << mutexAttributeKind << ") failed with: " << result << ". Attempting to continue as FAST MUTEX." << endl; mutexType = Mutex::FAST; break; } /* And finally, initialize the mutex itself... */ pthread_mutex_init ( & getMutexData(), ( (result == 0) ? & getMutexAttributes() : (const pthread_mutexattr_t *)NULL ) ); }