http://www.cs.wisc.edu/~markhill/cs838/Fall2005/handouts/hw2.html
especially, the example code
http://www.cs.wisc.edu/~markhill/cs838/Fall2005/handouts/eg_pthread.zip
/* **************************************************************** * *
Example pthread code * *
Each thread increments a shared counter * * **************************************************************** */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_NUMP 16
// use /usr/platform/sun4u/sbin/prtdiag -v on cabernet to get these
int ProcessorIds[MAX_NUMP] = {0, 1, 4, 5, 8 , 9, 12, 13, 16, 17, 20, 21, 24, 25, 28, 29};
int NumProcs;
pthread_mutex_t SyncLock;
/* mutex */
pthread_cond_t SyncCV;
/* condition variable */
int SyncCount; /* number of processors at the barrier so far */
pthread_mutex_t ThreadLock;
/* mutex */
hrtime_t StartTime;
hrtime_t EndTime;
int Count;
/* the shared counter */
/* Ad-hoc Barrier Code. This function will cause all the threads to synchronize
* with each other. What happens is that the mutex lock is used to control
* access to the condition variable & SyncCount variable. SyncCount is
* initialized to 0 in the beginning, and when barrier is called by each
* thread, SyncCount is incremented. When it reaches NumProcs, the
* number of threads/processors, a conditional broadcast is sent out which
* wakes up all the threads. The bad part is that each thread will then
* contend over the mutex lock, SyncLock, and will be released sequentially.
* * see man for further descriptions about cond_broadcast, cond_wait, etc.
* * Created to be called only once.. things are re-initialized
* * Barrier locks could also be implemented in many other ways, using
* semaphores, and other sync. functions
*/
void Barrier(){
int ret;
pthread_mutex_lock(&SyncLock); /* Get the thread lock */
SyncCount++;
if(SyncCount == NumProcs) {
ret = pthread_cond_broadcast(&SyncCV);
assert(ret == 0);
} else {
ret = pthread_cond_wait(&SyncCV, &SyncLock);
assert(ret == 0);
}
pthread_mutex_unlock(&SyncLock);}
/* The function which is called once the thread is allocated */
void* ThreadLoop(void* tmp){
/* each thread has a private version of local variables */
int threadId = (int) tmp;
int ret;
int startTime, endTime;
/* ********************** Thread Initialization *********************** */
/* Bind the thread to a processor. This will make sure that each of
* threads are on a different processor. ProcessorIds[threadId]
* specifies the processor ID which the thread is binding to.
*/
ret = processor_bind(P_LWPID, P_MYID, ProcessorIds[threadId], NULL);
assert(ret == 0);
/* ********************** Thread Synchronization*********************** */
Barrier();
/* ********************** Execute Job ********************************* */
pthread_mutex_lock(&ThreadLock);
/* Get the thread lock */
Count++;
pthread_mutex_unlock(&ThreadLock);
/* Release the lock */
}
int main(int argc, char** argv){
pthread_t* threads;
pthread_attr_t attr;
int ret;
int dx;
if(argc != 2) {
fprintf(stderr, "USAGE: %s
exit(-1);
}
assert(argc == 2);
NumProcs = atoi(argv[1]);
assert(NumProcs > 0 && NumProcs <= MAX_NUMP); /* Initialize array of thread structures */ threads = (pthread_t *) malloc(sizeof(pthread_t) * NumProcs); assert(threads != NULL); /* Initialize thread attribute */ pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); // sys manages contention /* Initialize mutexs */ ret = pthread_mutex_init(&SyncLock, NULL); assert(ret == 0); ret = pthread_mutex_init(&ThreadLock, NULL); assert(ret == 0); /* Init condition variable */ ret = pthread_cond_init(&SyncCV, NULL); assert(ret == 0); SyncCount = 0; Count = 0; /* get high resolution timer, timer is expressed in nanoseconds, relative * to some arbitrary time.. so to get delta time must call gethrtime at * the end of operation and subtract the two times. */ StartTime = gethrtime(); for(dx=0; dx < ret =" pthread_create(&threads[dx]," ret ="="" dx="0;" ret =" pthread_join(threads[dx]," ret ="="" endtime =" gethrtime();" count =" %d\n" time =" %lld">
CC = cc
LD = cc
CCFLAGS = -mt -lpthread
DEBUGFLAGS = -g
BINARIES = eg_pthread
all: $(BINARIES)
eg_pthread: eg_pthread.c
$(CC) $(CCFLAGS) $(DEBUGFLAGS) -o eg_pthread eg_pthread.c
clean:
rm -f $(BINARIES) core* *.o *~
No comments:
Post a Comment