1 #include "kvm/threadpool.h"
4 #include <linux/kernel.h>
5 #include <linux/list.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
))
25 job
= list_first_entry(&head
, struct thread_pool__job
, queue
);
26 list_del(&job
->queue
);
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
);
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
)
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
);
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
);
88 thread_pool__handle_job(curjob
);
91 pthread_cleanup_pop(0);
96 static int thread_pool__addthread(void)
101 mutex_lock(&thread_mutex
);
102 newthreads
= realloc(threads
, (threadcount
+ 1) * sizeof(pthread_t
));
103 if (newthreads
== NULL
) {
104 mutex_unlock(&thread_mutex
);
108 threads
= newthreads
;
110 res
= pthread_create(threads
+ threadcount
, NULL
,
111 thread_pool__threadfunc
, NULL
);
115 mutex_unlock(&thread_mutex
);
120 int thread_pool__init(unsigned long thread_count
)
124 for (i
= 0; i
< thread_count
; i
++)
125 if (thread_pool__addthread() < 0)
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
)
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
);