Add linux-next specific files for 20110831
[linux-2.6/next.git] / tools / kvm / threadpool.c
blobfdc5fa746e114d5f67d0007012863b54b20283b6
1 #include "kvm/threadpool.h"
2 #include "kvm/mutex.h"
4 #include <linux/kernel.h>
5 #include <linux/list.h>
6 #include <pthread.h>
7 #include <stdbool.h>
9 static pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER;
10 static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
11 static pthread_cond_t job_cond = PTHREAD_COND_INITIALIZER;
13 static LIST_HEAD(head);
15 static pthread_t *threads;
16 static long threadcount;
18 static struct thread_pool__job *thread_pool__job_pop(void)
20 struct thread_pool__job *job;
22 if (list_empty(&head))
23 return NULL;
25 job = list_first_entry(&head, struct thread_pool__job, queue);
26 list_del(&job->queue);
28 return job;
31 static void thread_pool__job_push(struct thread_pool__job *job)
33 list_add_tail(&job->queue, &head);
36 static struct thread_pool__job *thread_pool__job_pop_locked(void)
38 struct thread_pool__job *job;
40 mutex_lock(&job_mutex);
41 job = thread_pool__job_pop();
42 mutex_unlock(&job_mutex);
43 return job;
46 static void thread_pool__job_push_locked(struct thread_pool__job *job)
48 mutex_lock(&job_mutex);
49 thread_pool__job_push(job);
50 mutex_unlock(&job_mutex);
53 static void thread_pool__handle_job(struct thread_pool__job *job)
55 while (job) {
56 job->callback(job->kvm, job->data);
58 mutex_lock(&job->mutex);
60 if (--job->signalcount > 0)
61 /* If the job was signaled again while we were working */
62 thread_pool__job_push_locked(job);
64 mutex_unlock(&job->mutex);
66 job = thread_pool__job_pop_locked();
70 static void thread_pool__threadfunc_cleanup(void *param)
72 mutex_unlock(&job_mutex);
75 static void *thread_pool__threadfunc(void *param)
77 pthread_cleanup_push(thread_pool__threadfunc_cleanup, NULL);
79 for (;;) {
80 struct thread_pool__job *curjob;
82 mutex_lock(&job_mutex);
83 pthread_cond_wait(&job_cond, &job_mutex);
84 curjob = thread_pool__job_pop();
85 mutex_unlock(&job_mutex);
87 if (curjob)
88 thread_pool__handle_job(curjob);
91 pthread_cleanup_pop(0);
93 return NULL;
96 static int thread_pool__addthread(void)
98 int res;
99 void *newthreads;
101 mutex_lock(&thread_mutex);
102 newthreads = realloc(threads, (threadcount + 1) * sizeof(pthread_t));
103 if (newthreads == NULL) {
104 mutex_unlock(&thread_mutex);
105 return -1;
108 threads = newthreads;
110 res = pthread_create(threads + threadcount, NULL,
111 thread_pool__threadfunc, NULL);
113 if (res == 0)
114 threadcount++;
115 mutex_unlock(&thread_mutex);
117 return res;
120 int thread_pool__init(unsigned long thread_count)
122 unsigned long i;
124 for (i = 0; i < thread_count; i++)
125 if (thread_pool__addthread() < 0)
126 return i;
128 return i;
131 void thread_pool__do_job(struct thread_pool__job *job)
133 struct thread_pool__job *jobinfo = job;
135 if (jobinfo == NULL || jobinfo->callback == NULL)
136 return;
138 mutex_lock(&jobinfo->mutex);
139 if (jobinfo->signalcount++ == 0)
140 thread_pool__job_push_locked(job);
141 mutex_unlock(&jobinfo->mutex);
143 mutex_lock(&job_mutex);
144 pthread_cond_signal(&job_cond);
145 mutex_unlock(&job_mutex);