@@ -88,6 +88,7 @@ task_queue_pull(struct task_queue *queue)
88
88
89
89
tmp = TAILQ_LAST (queue , task_queue );
90
90
TAILQ_REMOVE (queue , tmp , next );
91
+ pr_op_debug ("Pulling a task from the pool" );
91
92
92
93
return tmp ;
93
94
}
@@ -97,6 +98,7 @@ static void
97
98
task_queue_push (struct task_queue * queue , struct task * task )
98
99
{
99
100
TAILQ_INSERT_HEAD (queue , task , next );
101
+ pr_op_debug ("Pushing a task to the pool" );
100
102
}
101
103
102
104
/*
@@ -115,13 +117,12 @@ tasks_poll(void *arg)
115
117
/* The thread has started, send the signal */
116
118
thread_pool_lock (pool );
117
119
pthread_cond_signal (& (pool -> waiting_cond ));
118
- thread_pool_unlock (pool );
119
120
120
121
while (true) {
121
- thread_pool_lock (pool );
122
-
123
- while (TAILQ_EMPTY (& (pool -> queue )) && !pool -> stop )
122
+ while (TAILQ_EMPTY (& (pool -> queue )) && !pool -> stop ) {
123
+ pr_op_debug ("Thread waiting for work..." );
124
124
pthread_cond_wait (& (pool -> working_cond ), & (pool -> lock ));
125
+ }
125
126
126
127
if (pool -> stop )
127
128
break ;
@@ -144,8 +145,6 @@ tasks_poll(void *arg)
144
145
if (!pool -> stop && pool -> working_count == 0 &&
145
146
TAILQ_EMPTY (& (pool -> queue )))
146
147
pthread_cond_signal (& (pool -> waiting_cond ));
147
-
148
- thread_pool_unlock (pool );
149
148
}
150
149
151
150
/* The thread will cease to exist */
@@ -173,52 +172,61 @@ thread_pool_thread_wait_start(struct thread_pool *pool)
173
172
clock_gettime (CLOCK_REALTIME , & tmout );
174
173
tmout .tv_sec += 2 ;
175
174
175
+ thread_pool_lock (pool );
176
176
error = pthread_cond_timedwait (& (pool -> waiting_cond ), & (pool -> lock ),
177
177
& tmout );
178
- if (error )
178
+ if (error ) {
179
+ thread_pool_unlock (pool );
179
180
return pr_op_errno (error , "Waiting thread to start" );
181
+ }
182
+ thread_pool_unlock (pool );
180
183
181
184
return 0 ;
182
185
}
183
186
184
187
static int
185
- tpool_thread_spawn ( struct thread_pool * pool , thread_pool_task_cb entry_point )
188
+ thread_pool_attr_create ( pthread_attr_t * attr )
186
189
{
187
- pthread_attr_t attr ;
188
- pthread_t thread_id ;
189
190
int error ;
190
191
191
- memset (& thread_id , 0 , sizeof (pthread_t ));
192
-
193
- error = pthread_attr_init (& attr );
192
+ error = pthread_attr_init (attr );
194
193
if (error )
195
194
return pr_op_errno (error , "Calling pthread_attr_init()" );
196
195
197
196
/* Use 2MB (default in most 64 bits systems) */
198
- error = pthread_attr_setstacksize (& attr , 1024 * 1024 * 2 );
199
- if (error )
197
+ error = pthread_attr_setstacksize (attr , 1024 * 1024 * 2 );
198
+ if (error ) {
199
+ pthread_attr_destroy (attr );
200
200
return pr_op_errno (error ,
201
201
"Calling pthread_attr_setstacksize()" );
202
+ }
202
203
203
- error = pthread_attr_setdetachstate (& attr , PTHREAD_CREATE_DETACHED );
204
- if (error )
204
+ error = pthread_attr_setdetachstate (attr , PTHREAD_CREATE_DETACHED );
205
+ if (error ) {
206
+ pthread_attr_destroy (attr );
205
207
return pr_op_errno (error ,
206
208
"Calling pthread_attr_setdetachstate()" );
209
+ }
207
210
208
- thread_pool_lock (pool );
209
- error = pthread_create (& thread_id , & attr , entry_point , pool );
210
- pthread_attr_destroy (& attr );
211
- if (error ) {
212
- thread_pool_unlock (pool );
211
+ return 0 ;
212
+ }
213
+
214
+ static int
215
+ tpool_thread_spawn (struct thread_pool * pool , pthread_attr_t * attr ,
216
+ thread_pool_task_cb entry_point )
217
+ {
218
+ pthread_t thread_id ;
219
+ int error ;
220
+
221
+ memset (& thread_id , 0 , sizeof (pthread_t ));
222
+
223
+ error = pthread_create (& thread_id , attr , entry_point , pool );
224
+ if (error )
213
225
return pr_op_errno (error , "Spawning pool thread" );
214
- }
215
226
216
227
error = thread_pool_thread_wait_start (pool );
217
- if (error ) {
218
- thread_pool_unlock (pool );
228
+ if (error )
219
229
return error ;
220
- }
221
- thread_pool_unlock (pool );
222
230
223
231
return 0 ;
224
232
}
227
235
thread_pool_create (unsigned int threads , struct thread_pool * * pool )
228
236
{
229
237
struct thread_pool * tmp ;
238
+ pthread_attr_t attr ;
230
239
unsigned int i ;
231
240
int error ;
232
241
@@ -260,19 +269,28 @@ thread_pool_create(unsigned int threads, struct thread_pool **pool)
260
269
TAILQ_INIT (& (tmp -> queue ));
261
270
tmp -> stop = false;
262
271
tmp -> working_count = 0 ;
263
- tmp -> thread_count = threads ;
272
+ tmp -> thread_count = 0 ;
273
+
274
+ error = thread_pool_attr_create (& attr );
275
+ if (error )
276
+ goto free_waiting_cond ;
264
277
265
278
for (i = 0 ; i < threads ; i ++ ) {
266
- error = tpool_thread_spawn (tmp , tasks_poll );
279
+ error = tpool_thread_spawn (tmp , & attr , tasks_poll );
267
280
if (error ) {
281
+ pthread_attr_destroy (& attr );
268
282
thread_pool_destroy (tmp );
269
283
return error ;
270
284
}
285
+ tmp -> thread_count ++ ;
271
286
pr_op_debug ("Pool thread #%u spawned" , i );
272
287
}
288
+ pthread_attr_destroy (& attr );
273
289
274
290
* pool = tmp ;
275
291
return 0 ;
292
+ free_waiting_cond :
293
+ pthread_cond_destroy (& (tmp -> waiting_cond ));
276
294
free_working_cond :
277
295
pthread_cond_destroy (& (tmp -> working_cond ));
278
296
free_mutex :
@@ -326,15 +344,14 @@ thread_pool_push(struct thread_pool *pool, thread_pool_task_cb cb, void *arg)
326
344
327
345
thread_pool_lock (pool );
328
346
task_queue_push (& (pool -> queue ), task );
329
- thread_pool_unlock (pool );
330
-
331
347
/* There's work to do! */
332
- pthread_cond_broadcast (& (pool -> working_cond ));
348
+ pthread_cond_signal (& (pool -> working_cond ));
349
+ thread_pool_unlock (pool );
333
350
334
351
return 0 ;
335
352
}
336
353
337
- /* Are there available threads to work? */
354
+ /* There are available threads to work? */
338
355
bool
339
356
thread_pool_avail_threads (struct thread_pool * pool )
340
357
{
@@ -354,7 +371,13 @@ thread_pool_wait(struct thread_pool *pool)
354
371
thread_pool_lock (pool );
355
372
while (true) {
356
373
pr_op_debug ("Waiting all tasks from the pool to end" );
357
- if ((!pool -> stop && pool -> working_count != 0 ) ||
374
+ pr_op_debug ("- Stop: %s" , pool -> stop ? "true" : "false" );
375
+ pr_op_debug ("- Working count: %u" , pool -> working_count );
376
+ pr_op_debug ("- Thread count: %u" , pool -> thread_count );
377
+ pr_op_debug ("- Empty queue: %s" ,
378
+ TAILQ_EMPTY (& (pool -> queue )) ? "true" : "false" );
379
+ if ((!pool -> stop &&
380
+ (pool -> working_count != 0 || !TAILQ_EMPTY (& (pool -> queue )))) ||
358
381
(pool -> stop && pool -> thread_count != 0 ))
359
382
pthread_cond_wait (& (pool -> waiting_cond ), & (pool -> lock ));
360
383
else
0 commit comments