From 2065f19101bdfd8d83ec0335edf9b04a2b4c7d1f Mon Sep 17 00:00:00 2001 From: "Costa Tsaousis (ktsaou)" Date: Sun, 12 Mar 2017 05:29:58 +0200 Subject: [PATCH] locks error handling --- src/avl.c | 18 +++++++++++------ src/rrd.h | 55 ++++++++++++++++++++++++++++++++++++++++++---------- src/rrdset.c | 26 +++++++++++++++++++------ 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/avl.c b/src/avl.c index 1ec1b8ad..f6a99788 100644 --- a/src/avl.c +++ b/src/avl.c @@ -315,9 +315,11 @@ int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *da void avl_read_lock(avl_tree_lock *t) { #ifndef AVL_WITHOUT_PTHREADS #ifdef AVL_LOCK_WITH_MUTEX - pthread_mutex_lock(&t->mutex); + if(unlikely(pthread_mutex_lock(&t->mutex) != 0)) + error("Cannot get mutex of an AVL"); #else - pthread_rwlock_rdlock(&t->rwlock); + if(unlikely(pthread_rwlock_rdlock(&t->rwlock) != 0)) + error("Cannot get read lock of an AVL"); #endif #endif /* AVL_WITHOUT_PTHREADS */ } @@ -325,9 +327,11 @@ void avl_read_lock(avl_tree_lock *t) { void avl_write_lock(avl_tree_lock *t) { #ifndef AVL_WITHOUT_PTHREADS #ifdef AVL_LOCK_WITH_MUTEX - pthread_mutex_lock(&t->mutex); + if(unlikely(pthread_mutex_lock(&t->mutex) != 0) + error("Cannot get mutex of an AVL"); #else - pthread_rwlock_wrlock(&t->rwlock); + if(unlikely(pthread_rwlock_wrlock(&t->rwlock) != 0)) + error("Cannot write lock an AVL."); #endif #endif /* AVL_WITHOUT_PTHREADS */ } @@ -335,9 +339,11 @@ void avl_write_lock(avl_tree_lock *t) { void avl_unlock(avl_tree_lock *t) { #ifndef AVL_WITHOUT_PTHREADS #ifdef AVL_LOCK_WITH_MUTEX - pthread_mutex_unlock(&t->mutex); + if(unlikely(pthread_mutex_unlock(&t->mutex) != 0)) + error("Cannot unlock mutex of an AVL"); #else - pthread_rwlock_unlock(&t->rwlock); + if(unlikely(pthread_rwlock_unlock(&t->rwlock) != 0)) + error("Cannot unlock an AVL"); #endif #endif /* AVL_WITHOUT_PTHREADS */ } diff --git a/src/rrd.h b/src/rrd.h index 2b872ed7..bc642d80 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -325,10 +325,6 @@ struct rrdset { }; typedef struct rrdset RRDSET; -#define rrdset_rdlock(st) pthread_rwlock_rdlock(&((st)->rrdset_rwlock)) -#define rrdset_wrlock(st) pthread_rwlock_wrlock(&((st)->rrdset_rwlock)) -#define rrdset_unlock(st) pthread_rwlock_unlock(&((st)->rrdset_rwlock)) - // ---------------------------------------------------------------------------- // these loop macros make sure the linked list is accessed with the right lock @@ -452,9 +448,21 @@ struct rrdhost { typedef struct rrdhost RRDHOST; extern RRDHOST *localhost; -#define rrdhost_rdlock(h) pthread_rwlock_rdlock(&((h)->rrdhost_rwlock)) -#define rrdhost_wrlock(h) pthread_rwlock_wrlock(&((h)->rrdhost_rwlock)) -#define rrdhost_unlock(h) pthread_rwlock_unlock(&((h)->rrdhost_rwlock)) +static inline void rrdhost_rdlock(RRDHOST *host) { + if(unlikely(pthread_rwlock_rdlock(&host->rrdhost_rwlock) != 0)) + error("Cannot obtain read lock on host '%s'", host->hostname); +} + +static inline void rrdhost_wrlock(RRDHOST *host) { + if(unlikely(pthread_rwlock_wrlock(&host->rrdhost_rwlock) != 0)) + error("Cannot obtain write lock on host '%s'", host->hostname); +} + +static inline void rrdhost_unlock(RRDHOST *host) { + if(unlikely(pthread_rwlock_unlock(&host->rrdhost_rwlock) != 0)) + error("Cannot unlock host '%s'", host->hostname); +} + // ---------------------------------------------------------------------------- // these loop macros make sure the linked list is accessed with the right lock @@ -470,9 +478,36 @@ extern RRDHOST *localhost; // global lock for all RRDHOSTs extern pthread_rwlock_t rrd_rwlock; -#define rrd_rdlock() pthread_rwlock_rdlock(&rrd_rwlock) -#define rrd_wrlock() pthread_rwlock_wrlock(&rrd_rwlock) -#define rrd_unlock() pthread_rwlock_unlock(&rrd_rwlock) + +static inline void rrd_rdlock() { + if(unlikely(pthread_rwlock_rdlock(&rrd_rwlock) != 0)) + error("Cannot read lock the RRD database."); +} + +static inline void rrd_wrlock() { + if(unlikely(pthread_rwlock_wrlock(&rrd_rwlock) != 0)) + error("Cannot write lock the RRD database."); +} + +static inline void rrd_unlock() { + if(unlikely(pthread_rwlock_unlock(&rrd_rwlock) != 0)) + error("Cannot unlock the RRD database."); +} + +static inline void rrdset_rdlock(RRDSET *st) { + if(unlikely(pthread_rwlock_rdlock(&st->rrdset_rwlock) != 0)) + error("Cannot read lock RRDSET '%s' of host '%s'", st->id, st->rrdhost->hostname); +} + +static inline void rrdset_wrlock(RRDSET *st) { + if(unlikely(pthread_rwlock_wrlock(&st->rrdset_rwlock) != 0)) + error("Cannot write lock RRDSET '%s' of host '%s'", st->id, st->rrdhost->hostname); +} + +static inline void rrdset_unlock(RRDSET *st) { + if(unlikely(pthread_rwlock_unlock(&st->rrdset_rwlock) != 0)) + error("Cannot unlock RRDSET '%s' of host '%s'", st->id, st->rrdhost->hostname); +} // ---------------------------------------------------------------------------- diff --git a/src/rrdset.c b/src/rrdset.c index 1918b5cb..30fd561a 100644 --- a/src/rrdset.c +++ b/src/rrdset.c @@ -328,6 +328,17 @@ void rrdset_delete(RRDSET *st) { // ---------------------------------------------------------------------------- // RRDSET - create a chart +static inline RRDSET *rrdset_find_on_create(RRDHOST *host, const char *fullid) { + RRDSET *st = rrdset_find(host, fullid); + if(unlikely(st)) { + rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); + debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid); + return st; + } + + return NULL; +} + RRDSET *rrdset_create( RRDHOST *host , const char *type @@ -357,10 +368,14 @@ RRDSET *rrdset_create( char fullid[RRD_ID_LENGTH_MAX + 1]; snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); - RRDSET *st = rrdset_find(host, fullid); + RRDSET *st = rrdset_find_on_create(host, fullid); + if(st) return st; + + rrdhost_wrlock(host); + + st = rrdset_find_on_create(host, fullid); if(st) { - rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); - debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid); + rrdhost_unlock(host); return st; } @@ -523,7 +538,6 @@ RRDSET *rrdset_create( avl_init_lock(&st->variables_root_index, rrdvar_compare); pthread_rwlock_init(&st->rrdset_rwlock, NULL); - rrdhost_wrlock(host); if(name && *name) rrdset_set_name(st, name); else rrdset_set_name(st, id); @@ -1250,8 +1264,8 @@ void rrdset_done(RRDSET *st) { RRDDIM *last; // there is dimension to free // upgrade our read lock to a write lock - pthread_rwlock_unlock(&st->rrdset_rwlock); - pthread_rwlock_wrlock(&st->rrdset_rwlock); + rrdset_unlock(st); + rrdset_wrlock(st); for( rd = st->dimensions, last = NULL ; likely(rd) ; ) { // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds -- 2.39.2