From: Ondřej Kuzník Date: Fri, 8 Jan 2021 11:32:04 +0000 (-0600) Subject: ITS#8747 Do not observe an epoch while calling dispose_cb X-Git-Tag: OPENLDAP_REL_ENG_2_6_0~231 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c1bb42f018ddaf236474b8765a0c54c5aa989d8;p=thirdparty%2Fopenldap.git ITS#8747 Do not observe an epoch while calling dispose_cb --- diff --git a/servers/lloadd/epoch.c b/servers/lloadd/epoch.c index dce030ce96..b46928369e 100644 --- a/servers/lloadd/epoch.c +++ b/servers/lloadd/epoch.c @@ -112,6 +112,7 @@ epoch_join( void ) epoch_t epoch; struct pending_ref *old, *ref = NULL; +retry: /* TODO: make this completely lock-free */ ldap_pvt_thread_rdwr_rlock( &epoch_mutex ); epoch = current_epoch; @@ -134,6 +135,19 @@ epoch_join( void ) current_epoch = EPOCH_NEXT(epoch); ldap_pvt_thread_rdwr_wunlock( &epoch_mutex ); + if ( !ref ) { + return epoch; + } + + /* + * The below is now safe to free outside epochs and we don't want to make + * the current epoch last any longer than necessary. + * + * Looks like there might be fairness issues in massively parallel + * environments but they haven't been observed on 32-core machines. + */ + epoch_leave( epoch ); + for ( old = ref; old; old = ref ) { ref = old->next; @@ -141,7 +155,7 @@ epoch_join( void ) ch_free( old ); } - return epoch; + goto retry; } void