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 19typedef struct thread { 20 pthread_t thread; 21 cpu_set_t cpus; 22 thread_func_t func; 23 void *arg; 24} thread_t; 25 26static thread_t threads[MAX_THREADS]; 27static int num_threads; 28 29 30/* 31 * Helper function to run a thread on a specific set of CPUs. 32 */ 33static 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 */ 52int 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 */ 86int 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 */ 115void join_threads(void) 116{ 117 while (num_threads > 0) 118 pthread_join(threads[--num_threads].thread, NULL); 119} 120 121