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 }