@@ -55,11 +55,11 @@ int opal_progress_spin_count = 10000;
55
55
static opal_atomic_lock_t progress_lock ;
56
56
57
57
/* callbacks to progress */
58
- static opal_progress_callback_t * callbacks = NULL ;
58
+ static volatile opal_progress_callback_t * callbacks = NULL ;
59
59
static size_t callbacks_len = 0 ;
60
60
static size_t callbacks_size = 0 ;
61
61
62
- static opal_progress_callback_t * callbacks_lp = NULL ;
62
+ static volatile opal_progress_callback_t * callbacks_lp = NULL ;
63
63
static size_t callbacks_lp_len = 0 ;
64
64
static size_t callbacks_lp_size = 0 ;
65
65
@@ -93,6 +93,9 @@ static int debug_output = -1;
93
93
*/
94
94
static int fake_cb (void ) { return 0 ; }
95
95
96
+ static int _opal_progress_unregister (opal_progress_callback_t cb , opal_progress_callback_t * callback_array ,
97
+ size_t * callback_array_len );
98
+
96
99
/* init the progress engine - called from orte_init */
97
100
int
98
101
opal_progress_init (void )
@@ -109,6 +112,27 @@ opal_progress_init(void)
109
112
}
110
113
#endif
111
114
115
+ callbacks_size = callbacks_lp_size = 8 ;
116
+
117
+ callbacks = malloc (callbacks_size * sizeof (callbacks [0 ]));
118
+ callbacks_lp = malloc (callbacks_lp_size * sizeof (callbacks_lp [0 ]));
119
+
120
+ if (NULL == callbacks || NULL == callbacks_lp ) {
121
+ free (callbacks );
122
+ free (callbacks_lp );
123
+ callbacks_size = callbacks_lp_size = 0 ;
124
+ callbacks = callbacks_lp = NULL ;
125
+ return OPAL_ERR_OUT_OF_RESOURCE ;
126
+ }
127
+
128
+ for (size_t i = 0 ; i < callbacks_size ; ++ i ) {
129
+ callbacks [i ] = fake_cb ;
130
+ }
131
+
132
+ for (size_t i = 0 ; i < callbacks_lp_size ; ++ i ) {
133
+ callbacks_lp [i ] = fake_cb ;
134
+ }
135
+
112
136
OPAL_OUTPUT ((debug_output , "progress: initialized event flag to: %x" ,
113
137
opal_progress_event_flag ));
114
138
OPAL_OUTPUT ((debug_output , "progress: initialized yield_when_idle to: %s" ,
@@ -130,10 +154,13 @@ opal_progress_finalize(void)
130
154
131
155
callbacks_len = 0 ;
132
156
callbacks_size = 0 ;
133
- if (NULL != callbacks ) {
134
- free (callbacks );
135
- callbacks = NULL ;
136
- }
157
+ free (callbacks );
158
+ callbacks = NULL ;
159
+
160
+ callbacks_lp_len = 0 ;
161
+ callbacks_lp_size = 0 ;
162
+ free (callbacks_lp );
163
+ callbacks_lp = NULL ;
137
164
138
165
opal_atomic_unlock (& progress_lock );
139
166
@@ -322,38 +349,73 @@ opal_progress_set_event_poll_rate(int polltime)
322
349
#endif
323
350
}
324
351
352
+ static int opal_progress_find_cb (opal_progress_callback_t cb , opal_progress_callback_t * cbs ,
353
+ size_t cbs_len )
354
+ {
355
+ for (size_t i = 0 ; i < cbs_len ; ++ i ) {
356
+ if (cbs [i ] == cb ) {
357
+ return (int ) i ;
358
+ }
359
+ }
325
360
326
- int
327
- opal_progress_register (opal_progress_callback_t cb )
361
+ return OPAL_ERR_NOT_FOUND ;
362
+ }
363
+
364
+ static int _opal_progress_register (opal_progress_callback_t cb , opal_progress_callback_t * * cbs ,
365
+ size_t * cbs_size , size_t * cbs_len )
328
366
{
329
367
int ret = OPAL_SUCCESS ;
330
- size_t index ;
331
368
332
- /* just in case there is a low-priority callback remove it */
333
- (void ) opal_progress_unregister (cb );
334
-
335
- opal_atomic_lock (& progress_lock );
369
+ if (OPAL_ERR_NOT_FOUND != opal_progress_find_cb (cb , * cbs , * cbs_len )) {
370
+ return OPAL_SUCCESS ;
371
+ }
336
372
337
373
/* see if we need to allocate more space */
338
- if (callbacks_len + 1 > callbacks_size ) {
339
- opal_progress_callback_t * tmp ;
340
- tmp = (opal_progress_callback_t * )realloc (callbacks , sizeof (opal_progress_callback_t ) * (callbacks_size + 4 ));
374
+ if (* cbs_len + 1 > * cbs_size ) {
375
+ opal_progress_callback_t * tmp , * old ;
376
+
377
+ tmp = (opal_progress_callback_t * ) malloc (sizeof (tmp [0 ]) * 2 * * cbs_size );
341
378
if (tmp == NULL ) {
342
- ret = OPAL_ERR_TEMP_OUT_OF_RESOURCE ;
343
- goto cleanup ;
379
+ return OPAL_ERR_TEMP_OUT_OF_RESOURCE ;
344
380
}
345
- /* registering fake callbacks to fill callbacks[] */
346
- for ( index = callbacks_len + 1 ; index < callbacks_size + 4 ; index ++ ) {
347
- tmp [index ] = & fake_cb ;
381
+
382
+ if (* cbs ) {
383
+ /* copy old callbacks */
384
+ memcpy (tmp , * cbs , sizeof (tmp [0 ]) * * cbs_size );
348
385
}
349
386
350
- callbacks = tmp ;
351
- callbacks_size += 4 ;
387
+ for (size_t i = * cbs_len ; i < 2 * * cbs_size ; ++ i ) {
388
+ tmp [i ] = fake_cb ;
389
+ }
390
+
391
+ opal_atomic_wmb ();
392
+
393
+ /* swap out callback array */
394
+ old = opal_atomic_swap_ptr (cbs , tmp );
395
+
396
+ opal_atomic_wmb ();
397
+
398
+ free (old );
399
+ * cbs_size *= 2 ;
352
400
}
353
401
354
- callbacks [callbacks_len ++ ] = cb ;
402
+ cbs [0 ][* cbs_len ] = cb ;
403
+ ++ * cbs_len ;
404
+
405
+ opal_atomic_wmb ();
406
+
407
+ return ret ;
408
+ }
409
+
410
+ int opal_progress_register (opal_progress_callback_t cb )
411
+ {
412
+ int ret ;
413
+
414
+ opal_atomic_lock (& progress_lock );
415
+
416
+ (void ) _opal_progress_unregister (cb , callbacks_lp , & callbacks_lp_len );
355
417
356
- cleanup :
418
+ ret = _opal_progress_register ( cb , & callbacks , & callbacks_size , & callbacks_len );
357
419
358
420
opal_atomic_unlock (& progress_lock );
359
421
@@ -362,84 +424,58 @@ opal_progress_register(opal_progress_callback_t cb)
362
424
363
425
int opal_progress_register_lp (opal_progress_callback_t cb )
364
426
{
365
- int ret = OPAL_SUCCESS ;
366
- size_t index ;
367
-
368
- /* just in case there is a high-priority callback remove it */
369
- (void ) opal_progress_unregister (cb );
427
+ int ret ;
370
428
371
429
opal_atomic_lock (& progress_lock );
372
430
373
- /* see if we need to allocate more space */
374
- if (callbacks_lp_len + 1 > callbacks_lp_size ) {
375
- opal_progress_callback_t * tmp ;
376
- tmp = (opal_progress_callback_t * )realloc (callbacks_lp , sizeof (opal_progress_callback_t ) * (callbacks_lp_size + 4 ));
377
- if (tmp == NULL ) {
378
- ret = OPAL_ERR_TEMP_OUT_OF_RESOURCE ;
379
- goto cleanup ;
380
- }
381
- /* registering fake callbacks_lp to fill callbacks_lp[] */
382
- for ( index = callbacks_lp_len + 1 ; index < callbacks_lp_size + 4 ; index ++ ) {
383
- tmp [index ] = & fake_cb ;
384
- }
431
+ (void ) _opal_progress_unregister (cb , callbacks , & callbacks_len );
385
432
386
- callbacks_lp = tmp ;
387
- callbacks_lp_size += 4 ;
388
- }
389
-
390
- callbacks_lp [callbacks_lp_len ++ ] = cb ;
391
-
392
- cleanup :
433
+ ret = _opal_progress_register (cb , & callbacks_lp , & callbacks_lp_size , & callbacks_lp_len );
393
434
394
435
opal_atomic_unlock (& progress_lock );
395
436
396
437
return ret ;
397
438
}
398
439
399
440
static int _opal_progress_unregister (opal_progress_callback_t cb , opal_progress_callback_t * callback_array ,
400
- size_t callback_array_len )
441
+ size_t * callback_array_len )
401
442
{
402
- size_t i ;
403
- int ret = OPAL_ERR_NOT_FOUND ;
404
-
405
- opal_atomic_lock (& progress_lock );
406
-
407
- for (i = 0 ; i < callback_array_len ; ++ i ) {
408
- if (cb == callback_array [i ]) {
409
- callback_array [i ] = & fake_cb ;
410
- ret = OPAL_SUCCESS ;
411
- break ;
412
- }
443
+ int ret = opal_progress_find_cb (cb , callback_array , * callback_array_len );
444
+ if (OPAL_ERR_NOT_FOUND == ret ) {
445
+ return ret ;
413
446
}
414
447
415
448
/* If we found the function we're unregistering: If callbacks_len
416
449
is 0, we're not goig to do anything interesting anyway, so
417
450
skip. If callbacks_len is 1, it will soon be 0, so no need to
418
- do any repacking. size_t can be unsigned, so 0 - 1 is bad for
419
- a loop condition :). */
420
- if (OPAL_SUCCESS == ret ) {
421
- if (i < callback_array_len - 1 ) {
422
- memmove (callback_array + i , callback_array + i + 1 ,
423
- (callback_array_len - i - 1 ) * sizeof (callback_array [0 ]));
424
- }
425
-
426
- callback_array [callback_array_len - 1 ] = & fake_cb ;
427
- callback_array_len -- ;
451
+ do any repacking. */
452
+ for (size_t i = (size_t ) ret ; i < * callback_array_len - 1 ; ++ i ) {
453
+ /* copy callbacks atomically since another thread may be in
454
+ * opal_progress(). */
455
+ (void ) opal_atomic_swap_ptr (callback_array + i , callback_array [i + 1 ]);
428
456
}
429
457
430
- opal_atomic_unlock (& progress_lock );
458
+ callback_array [* callback_array_len ] = fake_cb ;
459
+ -- * callback_array_len ;
431
460
432
- return ret ;
461
+ return OPAL_SUCCESS ;
433
462
}
434
463
435
464
int opal_progress_unregister (opal_progress_callback_t cb )
436
465
{
437
- int ret = _opal_progress_unregister (cb , callbacks , callbacks_len );
466
+ int ret ;
467
+
468
+ opal_atomic_lock (& progress_lock );
469
+
470
+ ret = _opal_progress_unregister (cb , callbacks , & callbacks_len );
471
+
438
472
if (OPAL_SUCCESS != ret ) {
439
473
/* if not in the high-priority array try to remove from the lp array.
440
474
* a callback will never be in both. */
441
- return _opal_progress_unregister (cb , callbacks_lp , callbacks_lp_len );
475
+ ret = _opal_progress_unregister (cb , callbacks_lp , & callbacks_lp_len );
442
476
}
443
477
478
+ opal_atomic_unlock (& progress_lock );
479
+
444
480
return ret ;
445
481
}
0 commit comments