1 /*
2 * Copyright 2008 Google Inc. All Rights Reserved.
3 * Author: md@google.com (Michael Davidson)
4 */
5 #define _GNU_SOURCE
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <sched.h>
11 #include <pthread.h>
12
13 #include "logging.h"
14 #include "threads.h"
15
16 #define MAX_CPUS CPU_SETSIZE
17 #define MAX_THREADS MAX_CPUS
18
19 typedef struct thread {
20 pthread_t thread;
21 cpu_set_t cpus;
22 thread_func_t func;
23 void *arg;
24 } thread_t;
25
26 static thread_t threads[MAX_THREADS];
27 static int num_threads;
28
29
30 /*
31 * Helper function to run a thread on a specific set of CPUs.
32 */
run_thread(void * arg)33 static void *run_thread(void *arg)
34 {
35 thread_t *thread = arg;
36 void *result;
37
38 if (sched_setaffinity(0, sizeof thread->cpus, &thread->cpus) < 0)
39 WARN(errno, "sched_setaffinity() failed");
40
41 result = thread->func(thread->arg);
42
43 return result;
44 }
45
46
47 /*
48 * Create a set of threads each of which is bound to one of
49 * the CPUs specified by cpus.
50 * Returns the number of threads created.
51 */
create_per_cpu_threads(cpu_set_t * cpus,thread_func_t func,void * arg)52 int create_per_cpu_threads(cpu_set_t *cpus, thread_func_t func, void *arg)
53 {
54 int cpu;
55
56 for (cpu = 0; cpu < MAX_CPUS; cpu++) {
57 int err;
58 thread_t *thread;
59 if (!CPU_ISSET(cpu, cpus))
60 continue;
61 if (num_threads >= MAX_THREADS)
62 break;
63
64 thread = &threads[num_threads++];
65 thread->func = func;
66 thread->arg = arg;
67 CPU_ZERO(&thread->cpus);
68 CPU_SET(cpu, &thread->cpus);
69
70 err = pthread_create(&thread->thread, NULL, run_thread, thread);
71 if (err) {
72 WARN(err, "pthread_create() failed");
73 --num_threads;
74 break;
75 }
76 }
77
78 return num_threads;
79 }
80
81
82 /*
83 * Create nthreads threads.
84 * Returns the number of threads created.
85 */
create_threads(int nthreads,thread_func_t func,void * arg)86 int create_threads(int nthreads, thread_func_t func, void *arg)
87 {
88 if (nthreads > MAX_THREADS)
89 nthreads = MAX_THREADS;
90
91 while (--nthreads >= 0) {
92 int err;
93 thread_t *thread;
94
95 thread = &threads[num_threads++];
96 thread->func = func;
97 thread->arg = arg;
98 CPU_ZERO(&thread->cpus);
99
100 err = pthread_create(&thread->thread, NULL, func, arg);
101 if (err) {
102 WARN(err, "pthread_create() failed");
103 --num_threads;
104 break;
105 }
106 }
107
108 return num_threads;
109 }
110
111
112 /*
113 * Join with the set of previsouly created threads.
114 */
join_threads(void)115 void join_threads(void)
116 {
117 while (num_threads > 0)
118 pthread_join(threads[--num_threads].thread, NULL);
119 }
120
121