X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fcommon%2Fsrc%2Fring_static.c;h=7170a9d0795caadaa191673891f8f67a699f5ffa;hb=ce1c741c01e8387cb095dac5e36a4d8ad91d006d;hp=37bb4dbcf3600a9fa864e151130c92bc654297ad;hpb=c1f84f8a4a4e2b90ad9ec18aba2b5365d3e51386;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/common/src/ring_static.c b/src/rmr/common/src/ring_static.c index 37bb4db..7170a9d 100644 --- a/src/rmr/common/src/ring_static.c +++ b/src/rmr/common/src/ring_static.c @@ -75,6 +75,7 @@ static void* uta_mk_ring( int size ) { return NULL; } + r->flags = 0; r->rgate = NULL; r->wgate = NULL; r->head = r->tail = 0; @@ -85,12 +86,12 @@ static void* uta_mk_ring( int size ) { } r->nelements = size; // because we always have an empty element when full - if( (r->data = (void **) malloc( sizeof( void** ) * (r->nelements + 1) )) == NULL ) { + if( (r->data = (void **) malloc( sizeof( void* ) * (r->nelements + 1) )) == NULL ) { free( r ); return NULL; } - memset( r->data, 0, sizeof( void** ) * r->nelements ); + memset( r->data, 0, sizeof( void* ) * r->nelements ); r->pfd = eventfd( 0, EFD_SEMAPHORE | EFD_NONBLOCK ); // in semaphore mode counter is maintained with each insert/extract return (void *) r; } @@ -124,7 +125,7 @@ static int uta_ring_config( void* vr, int options ) { } } - if( options & RING_RLOCK ) { + if( options & (RING_RLOCK | RING_FRLOCK) ) { // read locking if( r->rgate == NULL ) { // don't realloc r->rgate = (pthread_mutex_t *) malloc( sizeof( *r->rgate ) ); if( r->rgate == NULL ) { @@ -133,6 +134,9 @@ static int uta_ring_config( void* vr, int options ) { pthread_mutex_init( r->rgate, NULL ); } + if( options & RING_FRLOCK ) { + r->flags |= RING_FL_FLOCK; + } } return 1; @@ -148,7 +152,15 @@ static void uta_ring_free( void* vr ) { if( (r = (ring_t*) vr) == NULL ) { return; } - + if( r->data ){ + free( r->data ); + } + if( r->rgate ){ + free( r->rgate ); + } + if( r->wgate ){ + free( r->wgate ); + } free( r ); } @@ -166,6 +178,7 @@ static inline void* uta_ring_extract( void* vr ) { ring_t* r; uint16_t ti; // real index in data int64_t ctr; // pfd counter + void* data; if( !RING_FAST ) { // compiler should drop the conditional when always false if( (r = (ring_t*) vr) == NULL ) { @@ -179,9 +192,18 @@ static inline void* uta_ring_extract( void* vr ) { return NULL; } - if( r->rgate != NULL ) { // if lock exists we must honour it - pthread_mutex_lock( r->rgate ); + if( r->rgate != NULL ) { // if lock exists we must honour it + if( r->flags & RING_FL_FLOCK ) { // fast read locking try once and return nil if we cant lock + if( pthread_mutex_trylock( r->rgate ) != 0 ) { // quick fail if not able to get a lock + return NULL; + } + } else { + if( pthread_mutex_lock( r->rgate ) != 0 ) { + return NULL; + } + } if( r->tail == r->head ) { // ensure ring didn't go empty while waiting + pthread_mutex_unlock( r->rgate ); return NULL; } } @@ -199,15 +221,23 @@ future -- investigate if it's possible only to set/clear when empty or going to } */ + data = r->data[ti]; // secure data and clear before letting go of the lock + r->data[ti] = NULL; + if( r->rgate != NULL ) { // if locked above... pthread_mutex_unlock( r->rgate ); } - return r->data[ti]; + + return data; } + /* Insert the pointer at the next open space in the ring. - Returns 1 if the inert was ok, and 0 if the ring is full. + Returns 1 if the inert was ok, and 0 if there is an error; + errno will be set to EXFULL if the ring is full, if the attempt + fails with anyt other error that indicates the inability to obtain + a lock on the ring. */ static inline int uta_ring_insert( void* vr, void* new_data ) { ring_t* r; @@ -222,16 +252,25 @@ static inline int uta_ring_insert( void* vr, void* new_data ) { } if( r->wgate != NULL ) { // if lock exists we must honour it - pthread_mutex_lock( r->wgate ); + if( pthread_mutex_lock( r->wgate ) != 0 ) { + return 0; // leave mutex reason in place + } } if( r->head+1 == r->tail || (r->head+1 >= r->nelements && !r->tail) ) { // ring is full - if( r->wgate != NULL ) { // ensure released if needed + if( r->wgate != NULL ) { // ensure released if needed pthread_mutex_unlock( r->wgate ); } + errno = EXFULL; return 0; } + r->data[r->head] = new_data; + r->head++; + if( r->head >= r->nelements ) { + r->head = 0; + } + write( r->pfd, &inc, sizeof( inc ) ); /* future -- investigate if it's possible only to set/clear when empty or going to empty @@ -239,12 +278,6 @@ future -- investigate if it's possible only to set/clear when empty or going to } */ - r->data[r->head] = new_data; - r->head++; - if( r->head >= r->nelements ) { - r->head = 0; - } - if( r->wgate != NULL ) { // if lock exists we must unlock before going pthread_mutex_unlock( r->wgate ); }