1 /* 2 * Copyright 2008 Google Inc. All Rights Reserved. 3 * Author: md (at) 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 */ 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 */ 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 */ 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 */ 115 void join_threads(void) 116 { 117 while (num_threads > 0) 118 pthread_join(threads[--num_threads].thread, NULL); 119 } 120 121