Home | History | Annotate | Download | only in src
      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