@@ -32,6 +32,9 @@ struct data {
3232 size_t num_threads ;
3333 ABTI_thread * p_head ;
3434 ABTI_thread * p_tail ;
35+ /* If the pool is empty, pop() accesses only is_empty so that pop() does not
36+ * slow down a push operation. */
37+ ABTD_atomic_int is_empty ; /* Whether the pool is empty or not. */
3538};
3639typedef struct data data_t ;
3740
@@ -40,6 +43,28 @@ static inline data_t *pool_get_data_ptr(void *p_data)
4043 return (data_t * )p_data ;
4144}
4245
46+ ABTU_ret_err static inline int spinlock_acquire_if_not_empty (data_t * p_data )
47+ {
48+ if (ABTD_atomic_acquire_load_int (& p_data -> is_empty )) {
49+ /* The pool is empty. Lock is not taken. */
50+ return 1 ;
51+ }
52+ while (ABTD_spinlock_try_acquire (& p_data -> mutex )) {
53+ /* Lock acquisition failed. Check the size. */
54+ while (1 ) {
55+ if (ABTD_atomic_acquire_load_int (& p_data -> is_empty )) {
56+ /* The pool becomes empty. Lock is not taken. */
57+ return 1 ;
58+ } else if (!ABTD_spinlock_is_locked (& p_data -> mutex )) {
59+ /* Lock seems released. Let's try to take a lock again. */
60+ break ;
61+ }
62+ }
63+ }
64+ /* Lock is acquired. */
65+ return 0 ;
66+ }
67+
4368/* Obtain the FIFO pool definition according to the access type */
4469ABTU_ret_err int ABTI_pool_get_fifo_def (ABT_pool_access access ,
4570 ABTI_pool_def * p_def )
@@ -105,6 +130,7 @@ static int pool_init(ABT_pool pool, ABT_pool_config config)
105130 p_data -> num_threads = 0 ;
106131 p_data -> p_head = NULL ;
107132 p_data -> p_tail = NULL ;
133+ ABTD_atomic_relaxed_store_int (& p_data -> is_empty , 1 );
108134
109135 p_pool -> data = p_data ;
110136
@@ -141,6 +167,8 @@ static void pool_push_shared(ABT_pool pool, ABT_unit unit)
141167 p_thread -> p_next = p_thread ;
142168 p_data -> p_head = p_thread ;
143169 p_data -> p_tail = p_thread ;
170+ p_data -> num_threads = 1 ;
171+ ABTD_atomic_release_store_int (& p_data -> is_empty , 0 );
144172 } else {
145173 ABTI_thread * p_head = p_data -> p_head ;
146174 ABTI_thread * p_tail = p_data -> p_tail ;
@@ -149,8 +177,8 @@ static void pool_push_shared(ABT_pool pool, ABT_unit unit)
149177 p_thread -> p_prev = p_tail ;
150178 p_thread -> p_next = p_head ;
151179 p_data -> p_tail = p_thread ;
180+ p_data -> num_threads ++ ;
152181 }
153- p_data -> num_threads ++ ;
154182
155183 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 1 );
156184 ABTD_spinlock_release (& p_data -> mutex );
@@ -167,6 +195,8 @@ static void pool_push_private(ABT_pool pool, ABT_unit unit)
167195 p_thread -> p_next = p_thread ;
168196 p_data -> p_head = p_thread ;
169197 p_data -> p_tail = p_thread ;
198+ p_data -> num_threads = 1 ;
199+ ABTD_atomic_release_store_int (& p_data -> is_empty , 0 );
170200 } else {
171201 ABTI_thread * p_head = p_data -> p_head ;
172202 ABTI_thread * p_tail = p_data -> p_tail ;
@@ -175,8 +205,8 @@ static void pool_push_private(ABT_pool pool, ABT_unit unit)
175205 p_thread -> p_prev = p_tail ;
176206 p_thread -> p_next = p_head ;
177207 p_data -> p_tail = p_thread ;
208+ p_data -> num_threads ++ ;
178209 }
179- p_data -> num_threads ++ ;
180210
181211 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 1 );
182212}
@@ -186,148 +216,154 @@ static ABT_unit pool_pop_wait(ABT_pool pool, double time_secs)
186216 ABTI_pool * p_pool = ABTI_pool_get_ptr (pool );
187217 data_t * p_data = pool_get_data_ptr (p_pool -> data );
188218 ABTI_thread * p_thread = NULL ;
189- ABT_unit h_unit = ABT_UNIT_NULL ;
190219
191220 double time_start = 0.0 ;
192221
193- do {
194- ABTD_spinlock_acquire (& p_data -> mutex );
195- if (p_data -> num_threads > 0 ) {
196- p_thread = p_data -> p_head ;
197- if (p_data -> num_threads == 1 ) {
198- p_data -> p_head = NULL ;
199- p_data -> p_tail = NULL ;
200- } else {
201- p_thread -> p_prev -> p_next = p_thread -> p_next ;
202- p_thread -> p_next -> p_prev = p_thread -> p_prev ;
203- p_data -> p_head = p_thread -> p_next ;
222+ while (1 ) {
223+ if (spinlock_acquire_if_not_empty (p_data ) == 0 ) {
224+ ABT_unit h_unit = ABT_UNIT_NULL ;
225+ if (p_data -> num_threads > 0 ) {
226+ p_thread = p_data -> p_head ;
227+ if (p_data -> num_threads == 1 ) {
228+ p_data -> p_head = NULL ;
229+ p_data -> p_tail = NULL ;
230+ p_data -> num_threads = 0 ;
231+ ABTD_atomic_release_store_int (& p_data -> is_empty , 1 );
232+ } else {
233+ p_thread -> p_prev -> p_next = p_thread -> p_next ;
234+ p_thread -> p_next -> p_prev = p_thread -> p_prev ;
235+ p_data -> p_head = p_thread -> p_next ;
236+ p_data -> num_threads -- ;
237+ }
238+
239+ p_thread -> p_prev = NULL ;
240+ p_thread -> p_next = NULL ;
241+ ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
242+
243+ h_unit = (ABT_unit )p_thread ;
204244 }
205- p_data -> num_threads -- ;
206-
207- p_thread -> p_prev = NULL ;
208- p_thread -> p_next = NULL ;
209- ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
210-
211- h_unit = (ABT_unit )p_thread ;
212245 ABTD_spinlock_release (& p_data -> mutex );
246+ if (h_unit != ABT_UNIT_NULL )
247+ return h_unit ;
248+ }
249+ if (time_start == 0.0 ) {
250+ time_start = ABTI_get_wtime ();
213251 } else {
214- ABTD_spinlock_release (& p_data -> mutex );
215- if (time_start == 0.0 ) {
216- time_start = ABTI_get_wtime ();
217- } else {
218- double elapsed = ABTI_get_wtime () - time_start ;
219- if (elapsed > time_secs )
220- break ;
252+ double elapsed = ABTI_get_wtime () - time_start ;
253+ if (elapsed > time_secs )
254+ return ABT_UNIT_NULL ;
255+ }
256+ /* Sleep. */
257+ const int sleep_nsecs = 100 ;
258+ struct timespec ts = { 0 , sleep_nsecs };
259+ nanosleep (& ts , NULL );
260+ }
261+ }
262+
263+ static ABT_unit pool_pop_timedwait (ABT_pool pool , double abstime_secs )
264+ {
265+ ABTI_pool * p_pool = ABTI_pool_get_ptr (pool );
266+ data_t * p_data = pool_get_data_ptr (p_pool -> data );
267+ ABTI_thread * p_thread = NULL ;
268+
269+ while (1 ) {
270+ if (spinlock_acquire_if_not_empty (p_data ) == 0 ) {
271+ ABT_unit h_unit = ABT_UNIT_NULL ;
272+ if (p_data -> num_threads > 0 ) {
273+ p_thread = p_data -> p_head ;
274+ if (p_data -> num_threads == 1 ) {
275+ p_data -> p_head = NULL ;
276+ p_data -> p_tail = NULL ;
277+ p_data -> num_threads = 0 ;
278+ ABTD_atomic_release_store_int (& p_data -> is_empty , 1 );
279+ } else {
280+ p_thread -> p_prev -> p_next = p_thread -> p_next ;
281+ p_thread -> p_next -> p_prev = p_thread -> p_prev ;
282+ p_data -> p_head = p_thread -> p_next ;
283+ p_data -> num_threads -- ;
284+ }
285+
286+ p_thread -> p_prev = NULL ;
287+ p_thread -> p_next = NULL ;
288+ ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
289+
290+ h_unit = (ABT_unit )p_thread ;
221291 }
222- /* Sleep. */
223- const int sleep_nsecs = 100 ;
224- struct timespec ts = { 0 , sleep_nsecs };
225- nanosleep (& ts , NULL );
292+ ABTD_spinlock_release (& p_data -> mutex );
293+ if (h_unit != ABT_UNIT_NULL )
294+ return h_unit ;
226295 }
227- } while (h_unit == ABT_UNIT_NULL );
296+ const int sleep_nsecs = 100 ;
297+ struct timespec ts = { 0 , sleep_nsecs };
298+ nanosleep (& ts , NULL );
228299
229- return h_unit ;
300+ if (ABTI_get_wtime () > abstime_secs )
301+ return ABT_UNIT_NULL ;
302+ }
230303}
231304
232- static ABT_unit pool_pop_timedwait (ABT_pool pool , double abstime_secs )
305+ static ABT_unit pool_pop_shared (ABT_pool pool )
233306{
234307 ABTI_pool * p_pool = ABTI_pool_get_ptr (pool );
235308 data_t * p_data = pool_get_data_ptr (p_pool -> data );
236309 ABTI_thread * p_thread = NULL ;
237- ABT_unit h_unit = ABT_UNIT_NULL ;
238310
239- do {
240- ABTD_spinlock_acquire ( & p_data -> mutex ) ;
311+ if ( spinlock_acquire_if_not_empty ( p_data ) == 0 ) {
312+ ABT_unit h_unit = ABT_UNIT_NULL ;
241313 if (p_data -> num_threads > 0 ) {
242314 p_thread = p_data -> p_head ;
243315 if (p_data -> num_threads == 1 ) {
244316 p_data -> p_head = NULL ;
245317 p_data -> p_tail = NULL ;
318+ p_data -> num_threads = 0 ;
319+ ABTD_atomic_release_store_int (& p_data -> is_empty , 1 );
246320 } else {
247321 p_thread -> p_prev -> p_next = p_thread -> p_next ;
248322 p_thread -> p_next -> p_prev = p_thread -> p_prev ;
249323 p_data -> p_head = p_thread -> p_next ;
324+ p_data -> num_threads -- ;
250325 }
251- p_data -> num_threads -- ;
252326
253327 p_thread -> p_prev = NULL ;
254328 p_thread -> p_next = NULL ;
255329 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
256330
257331 h_unit = (ABT_unit )p_thread ;
258- ABTD_spinlock_release (& p_data -> mutex );
259- } else {
260- ABTD_spinlock_release (& p_data -> mutex );
261- /* Sleep. */
262- const int sleep_nsecs = 100 ;
263- struct timespec ts = { 0 , sleep_nsecs };
264- nanosleep (& ts , NULL );
265-
266- if (ABTI_get_wtime () > abstime_secs )
267- break ;
268- }
269- } while (h_unit == ABT_UNIT_NULL );
270-
271- return h_unit ;
272- }
273-
274- static ABT_unit pool_pop_shared (ABT_pool pool )
275- {
276- ABTI_pool * p_pool = ABTI_pool_get_ptr (pool );
277- data_t * p_data = pool_get_data_ptr (p_pool -> data );
278- ABTI_thread * p_thread = NULL ;
279- ABT_unit h_unit = ABT_UNIT_NULL ;
280-
281- ABTD_spinlock_acquire (& p_data -> mutex );
282- if (p_data -> num_threads > 0 ) {
283- p_thread = p_data -> p_head ;
284- if (p_data -> num_threads == 1 ) {
285- p_data -> p_head = NULL ;
286- p_data -> p_tail = NULL ;
287- } else {
288- p_thread -> p_prev -> p_next = p_thread -> p_next ;
289- p_thread -> p_next -> p_prev = p_thread -> p_prev ;
290- p_data -> p_head = p_thread -> p_next ;
291332 }
292- p_data -> num_threads -- ;
293-
294- p_thread -> p_prev = NULL ;
295- p_thread -> p_next = NULL ;
296- ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
297-
298- h_unit = (ABT_unit )p_thread ;
333+ ABTD_spinlock_release (& p_data -> mutex );
334+ return h_unit ;
335+ } else {
336+ return ABT_UNIT_NULL ;
299337 }
300- ABTD_spinlock_release (& p_data -> mutex );
301-
302- return h_unit ;
303338}
304339
305340static ABT_unit pool_pop_private (ABT_pool pool )
306341{
307342 ABTI_pool * p_pool = ABTI_pool_get_ptr (pool );
308343 data_t * p_data = pool_get_data_ptr (p_pool -> data );
309344 ABTI_thread * p_thread = NULL ;
310- ABT_unit h_unit = ABT_UNIT_NULL ;
311345
346+ ABT_unit h_unit = ABT_UNIT_NULL ;
312347 if (p_data -> num_threads > 0 ) {
313348 p_thread = p_data -> p_head ;
314349 if (p_data -> num_threads == 1 ) {
315350 p_data -> p_head = NULL ;
316351 p_data -> p_tail = NULL ;
352+ p_data -> num_threads = 0 ;
353+ ABTD_atomic_relaxed_store_int (& p_data -> is_empty , 1 );
317354 } else {
318355 p_thread -> p_prev -> p_next = p_thread -> p_next ;
319356 p_thread -> p_next -> p_prev = p_thread -> p_prev ;
320357 p_data -> p_head = p_thread -> p_next ;
358+ p_data -> num_threads -- ;
321359 }
322- p_data -> num_threads -- ;
323360
324361 p_thread -> p_prev = NULL ;
325362 p_thread -> p_next = NULL ;
326363 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
327364
328365 h_unit = (ABT_unit )p_thread ;
329366 }
330-
331367 return h_unit ;
332368}
333369
@@ -345,6 +381,8 @@ static int pool_remove_shared(ABT_pool pool, ABT_unit unit)
345381 if (p_data -> num_threads == 1 ) {
346382 p_data -> p_head = NULL ;
347383 p_data -> p_tail = NULL ;
384+ p_data -> num_threads = 0 ;
385+ ABTD_atomic_release_store_int (& p_data -> is_empty , 1 );
348386 } else {
349387 p_thread -> p_prev -> p_next = p_thread -> p_next ;
350388 p_thread -> p_next -> p_prev = p_thread -> p_prev ;
@@ -353,8 +391,8 @@ static int pool_remove_shared(ABT_pool pool, ABT_unit unit)
353391 } else if (p_thread == p_data -> p_tail ) {
354392 p_data -> p_tail = p_thread -> p_prev ;
355393 }
394+ p_data -> num_threads -- ;
356395 }
357- p_data -> num_threads -- ;
358396
359397 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
360398 ABTD_spinlock_release (& p_data -> mutex );
@@ -378,6 +416,8 @@ static int pool_remove_private(ABT_pool pool, ABT_unit unit)
378416 if (p_data -> num_threads == 1 ) {
379417 p_data -> p_head = NULL ;
380418 p_data -> p_tail = NULL ;
419+ p_data -> num_threads = 0 ;
420+ ABTD_atomic_relaxed_store_int (& p_data -> is_empty , 1 );
381421 } else {
382422 p_thread -> p_prev -> p_next = p_thread -> p_next ;
383423 p_thread -> p_next -> p_prev = p_thread -> p_prev ;
@@ -386,8 +426,8 @@ static int pool_remove_private(ABT_pool pool, ABT_unit unit)
386426 } else if (p_thread == p_data -> p_tail ) {
387427 p_data -> p_tail = p_thread -> p_prev ;
388428 }
429+ p_data -> num_threads -- ;
389430 }
390- p_data -> num_threads -- ;
391431
392432 ABTD_atomic_release_store_int (& p_thread -> is_in_pool , 0 );
393433 p_thread -> p_prev = NULL ;
0 commit comments