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 }