@@ -55,11 +55,11 @@ int opal_progress_spin_count = 10000;
5555static opal_atomic_lock_t progress_lock ;
5656
5757/* callbacks to progress */
58- static opal_progress_callback_t * callbacks = NULL ;
58+ static volatile opal_progress_callback_t * callbacks = NULL ;
5959static size_t callbacks_len = 0 ;
6060static size_t callbacks_size = 0 ;
6161
62- static opal_progress_callback_t * callbacks_lp = NULL ;
62+ static volatile opal_progress_callback_t * callbacks_lp = NULL ;
6363static size_t callbacks_lp_len = 0 ;
6464static size_t callbacks_lp_size = 0 ;
6565
@@ -93,6 +93,9 @@ static int debug_output = -1;
9393 */
9494static int fake_cb (void ) { return 0 ; }
9595
96+ static int _opal_progress_unregister (opal_progress_callback_t cb , opal_progress_callback_t * callback_array ,
97+ size_t * callback_array_len );
98+
9699/* init the progress engine - called from orte_init */
97100int
98101opal_progress_init (void )
@@ -109,6 +112,27 @@ opal_progress_init(void)
109112 }
110113#endif
111114
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+
112136 OPAL_OUTPUT ((debug_output , "progress: initialized event flag to: %x" ,
113137 opal_progress_event_flag ));
114138 OPAL_OUTPUT ((debug_output , "progress: initialized yield_when_idle to: %s" ,
@@ -130,10 +154,13 @@ opal_progress_finalize(void)
130154
131155 callbacks_len = 0 ;
132156 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 ;
137164
138165 opal_atomic_unlock (& progress_lock );
139166
@@ -322,38 +349,73 @@ opal_progress_set_event_poll_rate(int polltime)
322349#endif
323350}
324351
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+ }
325360
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 )
328366{
329367 int ret = OPAL_SUCCESS ;
330- size_t index ;
331368
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+ }
336372
337373 /* 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 );
341378 if (tmp == NULL ) {
342- ret = OPAL_ERR_TEMP_OUT_OF_RESOURCE ;
343- goto cleanup ;
379+ return OPAL_ERR_TEMP_OUT_OF_RESOURCE ;
344380 }
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 );
348385 }
349386
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 ;
352400 }
353401
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 );
355417
356- cleanup :
418+ ret = _opal_progress_register ( cb , & callbacks , & callbacks_size , & callbacks_len );
357419
358420 opal_atomic_unlock (& progress_lock );
359421
@@ -362,84 +424,58 @@ opal_progress_register(opal_progress_callback_t cb)
362424
363425int opal_progress_register_lp (opal_progress_callback_t cb )
364426{
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 ;
370428
371429 opal_atomic_lock (& progress_lock );
372430
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 );
385432
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 );
393434
394435 opal_atomic_unlock (& progress_lock );
395436
396437 return ret ;
397438}
398439
399440static 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 )
401442{
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 ;
413446 }
414447
415448 /* If we found the function we're unregistering: If callbacks_len
416449 is 0, we're not goig to do anything interesting anyway, so
417450 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 ]);
428456 }
429457
430- opal_atomic_unlock (& progress_lock );
458+ callback_array [* callback_array_len ] = fake_cb ;
459+ -- * callback_array_len ;
431460
432- return ret ;
461+ return OPAL_SUCCESS ;
433462}
434463
435464int opal_progress_unregister (opal_progress_callback_t cb )
436465{
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+
438472 if (OPAL_SUCCESS != ret ) {
439473 /* if not in the high-priority array try to remove from the lp array.
440474 * 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 );
442476 }
443477
478+ opal_atomic_unlock (& progress_lock );
479+
444480 return ret ;
445481}
0 commit comments