1 #include <pthread.h> // P-Threads Library Headers 2 #include <stdlib.h> 3 #include <stdio.h> 4 5 /* These headers will allow us to use processor_bind() */ 6 #include <sys/types.h> 7 #include <sys/processor.h> 8 #include <sys/procset.h> 9 10 11 /*-------------------------------------------------------------+ 12 | This array specifies the physical processor identifiers... | 13 | it is used to force binding of threads to processors-- the | 14 | identifiers can usually be found by executing: | 15 | /usr/platform/sun4v/sbin/prtdiag -v | 16 | (older platforms use sun4u instead of sun4v) | 17 +-------------------------------------------------------------*/ 18 int g_ProcessorIDs[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}; 19 20 /*-------------------------------------------------------------+ 21 | This struct is used to package multiple parameters to each | 22 | thread. | 23 +-------------------------------------------------------------*/ 24 typedef struct { 25 int tid; 26 int myProcessor; 27 void * myReturnValue; 28 } thread_param_t; 29 30 /*-------------------------------------------------------------+ 31 | Each thread's start point is this function. All pthreads | 32 | start functions take a single argument of type void* and | 33 | return a single argument of type void* -- this example | 34 | passes a poitner to a struct that includes all necessary | 35 | thread information, like the thread identifier. | 36 +-------------------------------------------------------------*/ 37 void* SayHello(void *foo) { 38 thread_param_t * myParams = (thread_param_t*) foo; 39 40 /*-------------------------------------------------------------+ 41 | Binding threads to processors forces each thread to run on | 42 | a given processor and encourages the scheduler to run all | 43 | threads at the same time and on different CPUs. Binding is | 44 | technically "just a hint" but it is almost always followed. | 45 +-------------------------------------------------------------*/ 46 myParams->myProcessor = g_ProcessorIDs[myParams->tid]; 47 if( processor_bind( P_LWPID, P_MYID, myParams->myProcessor, NULL ) ) { 48 fprintf(stderr, "Couldn't bind thread %i to processor %i!\n", myParams->tid, myParams->myProcessor ); 49 } 50 51 printf("Hello from thread %i!\n", myParams->tid); 52 53 return myParams->myReturnValue; 54 } 55 56 #define NUM_THREADS 16 57 58 int main() { 59 int thread_number; 60 61 /*-------------------------------------------------------------+ 62 | This is needed for every pthreads program to iniailzie the | 63 | pthreads library -- see the pthreads man page for details. | 64 +-------------------------------------------------------------*/ 65 pthread_attr_t attr; 66 pthread_t* threads = (pthread_t*) malloc( sizeof(pthread_t) * NUM_THREADS); 67 pthread_attr_init(&attr); 68 pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM); 69 70 71 /*-------------------------------------------------------------+ 72 | Next, we set up the parameters for each thread--parameters | 73 | are ensconced in a struct so they can be handed to the | 74 | thread as a single void* | 75 +-------------------------------------------------------------*/ 76 thread_param_t * thread_params = (thread_param_t*) malloc( sizeof(thread_param_t) * NUM_THREADS); 77 for(thread_number=0;thread_number<NUM_THREADS;thread_number++) { 78 thread_params[thread_number].tid = thread_number; 79 thread_params[thread_number].myReturnValue = NULL; // just have all the threads return NULL 80 } 81 82 /*-------------------------------------------------------------+ 83 | Here we're actually going to fork off the threads to the | 84 | start function above. | 85 +-------------------------------------------------------------*/ 86 for(thread_number=0;thread_number<NUM_THREADS;thread_number++) { 87 pthread_create(&threads[thread_number], &attr, SayHello, (void*) &thread_params[thread_number]); 88 } 89 90 /*-------------------------------------------------------------+ 91 | Last, we wait for all threads to finish execution. The call | 92 | to pthread_join blocks until the specified thread finishes, | 93 | analagous to waitpid() in multiprocess programming. | 94 +-------------------------------------------------------------*/ 95 for(thread_number=0;thread_number<NUM_THREADS;thread_number++) { 96 pthread_join(threads[thread_number], NULL); 97 } 98 99 return 0; 100 }