From 396e211e5cfd195b7135947d425b089a0447fa88 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 5 Mar 2010 08:27:26 +0100 Subject: enabled compilation by using "racy" replacements for atomic instructions ... but this is not considered a real solution. For some of the uses, it may acutally be sufficient, but the implications need to be analyzed in detail. --- runtime/atomic.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'runtime/atomic.h') diff --git a/runtime/atomic.h b/runtime/atomic.h index d5aaf56b..62ceb8b3 100644 --- a/runtime/atomic.h +++ b/runtime/atomic.h @@ -66,6 +66,9 @@ # define ATOMIC_DEC_AND_FETCH(data) (--(data)) # define ATOMIC_FETCH_32BIT(data) (data) # define ATOMIC_STORE_1_TO_32BIT(data) (data) = 1 +# define ATOMIC_STORE_1_TO_INT(data) (data) = 1 +# define ATOMIC_STORE_0_TO_INT(data) (data) = 0 +# define ATOMIC_CAS_VAL(data, oldVal, newVal) (data) = (newVal) #endif #endif /* #ifndef INCLUDED_ATOMIC_H */ -- cgit From 072fc663a83b2050d961d1c7ec7aa16f12842c9a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 23 Mar 2010 15:04:24 +0100 Subject: added replacements for atomic instructions on systems that do not support them. [backport of Stefen Sledz' patch for v5] --- runtime/atomic.h | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'runtime/atomic.h') diff --git a/runtime/atomic.h b/runtime/atomic.h index 62ceb8b3..ea3be37a 100644 --- a/runtime/atomic.h +++ b/runtime/atomic.h @@ -53,6 +53,122 @@ # define ATOMIC_CAS(data, oldVal, newVal) __sync_bool_compare_and_swap(&(data), (oldVal), (newVal)); # define ATOMIC_CAS_VAL(data, oldVal, newVal) __sync_val_compare_and_swap(&(data), (oldVal), (newVal)); #else +#ifdef HAVE_SEMAPHORE_H + /* we use POSIX semaphores instead */ + +#include "rsyslog.h" +#include + +extern sem_t atomicSem; +rsRetVal atomicSemInit(void); +void atomicSemExit(void); + +#if HAVE_TYPEOF +#define my_typeof(x) typeof(x) +#else /* sorry, can't determine types, using 'int' */ +#define my_typeof(x) int +#endif + +# define ATOMIC_SUB(data, val) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data -= val; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_ADD(data, val) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data += val; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_INC_AND_FETCH(data) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data += 1; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_INC(data) ((void) ATOMIC_INC_AND_FETCH(data)) + +# define ATOMIC_DEC_AND_FETCH(data) \ +({ \ + sem_wait(&atomicSem); \ + data -= 1; \ + sem_post(&atomicSem); \ + data; \ +}) + +# define ATOMIC_DEC(data) ((void) ATOMIC_DEC_AND_FETCH(data)) + +# define ATOMIC_FETCH_32BIT(data) ((unsigned) ATOMIC_ADD((data), 0xffffffff)) + +# define ATOMIC_STORE_1_TO_32BIT(data) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data = 1; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_STORE_0_TO_INT(data) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data = 0; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_STORE_1_TO_INT(data) \ +({ \ + my_typeof(data) tmp; \ + sem_wait(&atomicSem); \ + tmp = data; \ + data = 1; \ + sem_post(&atomicSem); \ + tmp; \ +}) + +# define ATOMIC_CAS(data, oldVal, newVal) \ +({ \ + int ret; \ + sem_wait(&atomicSem); \ + if(data != oldVal) ret = 0; \ + else \ + { \ + data = newVal; \ + ret = 1; \ + } \ + sem_post(&atomicSem); \ + ret; \ +}) + +# define ATOMIC_CAS_VAL(data, oldVal, newVal) \ +({ \ + sem_wait(&atomicSem); \ + if(data == oldVal) \ + { \ + data = newVal; \ + } \ + sem_post(&atomicSem); \ + data; \ +}) + +#else /* not HAVE_SEMAPHORE_H */ /* note that we gained parctical proof that theoretical problems DO occur * if we do not properly address them. See this blog post for details: * http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html @@ -70,5 +186,6 @@ # define ATOMIC_STORE_0_TO_INT(data) (data) = 0 # define ATOMIC_CAS_VAL(data, oldVal, newVal) (data) = (newVal) #endif +#endif #endif /* #ifndef INCLUDED_ATOMIC_H */ -- cgit From 57eb123abe8aa4c169a5a155247f036b703cd8cf Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 23 Apr 2010 12:59:11 +0100 Subject: minor fix: invalid duplicated include of config.h --- runtime/atomic.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'runtime/atomic.h') diff --git a/runtime/atomic.h b/runtime/atomic.h index ea3be37a..271e825e 100644 --- a/runtime/atomic.h +++ b/runtime/atomic.h @@ -31,8 +31,6 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ -#include "config.h" /* autotools! */ - #ifndef INCLUDED_ATOMIC_H #define INCLUDED_ATOMIC_H -- cgit From cbe2e3d44496ec7c6418e7e74ce917f2086a2947 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 27 Apr 2010 17:31:28 +0200 Subject: bugfix: problems with atomic operations emulation replaced atomic operation emulation with new code. The previous code seemed to have some issue and also limited concurrency severely. The whole atomic operation emulation has been rewritten. --- runtime/atomic.h | 200 ++++++++++++++++++++----------------------------------- 1 file changed, 71 insertions(+), 129 deletions(-) (limited to 'runtime/atomic.h') diff --git a/runtime/atomic.h b/runtime/atomic.h index 271e825e..fc3e0b2d 100644 --- a/runtime/atomic.h +++ b/runtime/atomic.h @@ -39,134 +39,29 @@ * They simply came in too late. -- rgerhards, 2008-04-02 */ #ifdef HAVE_ATOMIC_BUILTINS -# define ATOMIC_INC(data) ((void) __sync_fetch_and_add(&(data), 1)) +# define ATOMIC_INC(data, phlpmut) ((void) __sync_fetch_and_add(data, 1)) # define ATOMIC_INC_AND_FETCH(data) __sync_fetch_and_add(&(data), 1) -# define ATOMIC_DEC(data) ((void) __sync_sub_and_fetch(&(data), 1)) -# define ATOMIC_DEC_AND_FETCH(data) __sync_sub_and_fetch(&(data), 1) +# define ATOMIC_DEC(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1)) +# define ATOMIC_DEC_AND_FETCH(data, phlpmut) __sync_sub_and_fetch(data, 1) # define ATOMIC_FETCH_32BIT(data) ((unsigned) __sync_fetch_and_and(&(data), 0xffffffff)) # define ATOMIC_STORE_1_TO_32BIT(data) __sync_lock_test_and_set(&(data), 1) -# define ATOMIC_STORE_0_TO_INT(data) __sync_fetch_and_and(&(data), 0) -# define ATOMIC_STORE_1_TO_INT(data) __sync_fetch_and_or(&(data), 1) +# define ATOMIC_STORE_0_TO_INT(data, phlpmut) __sync_fetch_and_and(data, 0) +# define ATOMIC_STORE_1_TO_INT(data, phlpmut) __sync_fetch_and_or(data, 1) # define ATOMIC_STORE_INT_TO_INT(data, val) __sync_fetch_and_or(&(data), (val)) # define ATOMIC_CAS(data, oldVal, newVal) __sync_bool_compare_and_swap(&(data), (oldVal), (newVal)); -# define ATOMIC_CAS_VAL(data, oldVal, newVal) __sync_val_compare_and_swap(&(data), (oldVal), (newVal)); -#else -#ifdef HAVE_SEMAPHORE_H - /* we use POSIX semaphores instead */ - -#include "rsyslog.h" -#include - -extern sem_t atomicSem; -rsRetVal atomicSemInit(void); -void atomicSemExit(void); - -#if HAVE_TYPEOF -#define my_typeof(x) typeof(x) -#else /* sorry, can't determine types, using 'int' */ -#define my_typeof(x) int -#endif - -# define ATOMIC_SUB(data, val) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data -= val; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_ADD(data, val) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data += val; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_INC_AND_FETCH(data) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data += 1; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_INC(data) ((void) ATOMIC_INC_AND_FETCH(data)) - -# define ATOMIC_DEC_AND_FETCH(data) \ -({ \ - sem_wait(&atomicSem); \ - data -= 1; \ - sem_post(&atomicSem); \ - data; \ -}) +# define ATOMIC_CAS_VAL(data, oldVal, newVal, phlpmut) __sync_val_compare_and_swap(data, (oldVal), (newVal)); -# define ATOMIC_DEC(data) ((void) ATOMIC_DEC_AND_FETCH(data)) + /* functions below are not needed if we have atomics */ +# define DEF_ATOMIC_HELPER_MUT(x) +# define INIT_ATOMIC_HELPER_MUT(x) +# define DESTROY_ATOMIC_HELPER_MUT(x) -# define ATOMIC_FETCH_32BIT(data) ((unsigned) ATOMIC_ADD((data), 0xffffffff)) - -# define ATOMIC_STORE_1_TO_32BIT(data) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data = 1; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_STORE_0_TO_INT(data) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data = 0; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_STORE_1_TO_INT(data) \ -({ \ - my_typeof(data) tmp; \ - sem_wait(&atomicSem); \ - tmp = data; \ - data = 1; \ - sem_post(&atomicSem); \ - tmp; \ -}) - -# define ATOMIC_CAS(data, oldVal, newVal) \ -({ \ - int ret; \ - sem_wait(&atomicSem); \ - if(data != oldVal) ret = 0; \ - else \ - { \ - data = newVal; \ - ret = 1; \ - } \ - sem_post(&atomicSem); \ - ret; \ -}) - -# define ATOMIC_CAS_VAL(data, oldVal, newVal) \ -({ \ - sem_wait(&atomicSem); \ - if(data == oldVal) \ - { \ - data = newVal; \ - } \ - sem_post(&atomicSem); \ - data; \ -}) - -#else /* not HAVE_SEMAPHORE_H */ + /* the following operations should preferrably be done atomic, but it is + * not fatal if not -- that means we can live with some missed updates. So be + * sure to use these macros only if that really does not matter! + */ +# define PREFER_ATOMIC_INC(data) ((void) __sync_fetch_and_add(&(data), 1)) +#else /* note that we gained parctical proof that theoretical problems DO occur * if we do not properly address them. See this blog post for details: * http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html @@ -174,16 +69,63 @@ void atomicSemExit(void); * simply go ahead and do without them - use mutexes or other things. The * code needs to be checked against all those cases. -- rgerhards, 2009-01-30 */ + #include +# define ATOMIC_INC(data, phlpmut) { \ + pthread_mutex_lock(phlpmut); \ + ++(*(data)); \ + pthread_mutex_unlock(phlpmut); \ + } + +# define ATOMIC_STORE_0_TO_INT(data, hlpmut) { \ + pthread_mutex_lock(&hlpmut); \ + *(data) = 0; \ + pthread_mutex_unlock(&hlpmut); \ + } + +# define ATOMIC_STORE_1_TO_INT(data, hlpmut) { \ + pthread_mutex_lock(&hlpmut); \ + *(data) = 1; \ + pthread_mutex_unlock(&hlpmut); \ + } + + static inline int + ATOMIC_CAS_VAL(int *data, int oldVal, int newVal, pthread_mutex_t *phlpmut) { + int val; + pthread_mutex_lock(phlpmut); + if(*data == oldVal) { + *data = newVal; + } + val = *data; + pthread_mutex_unlock(phlpmut); + return(val); + } + +# define ATOMIC_DEC(data, phlpmut) { \ + pthread_mutex_lock(phlpmut); \ + --(*(data)); \ + pthread_mutex_unlock(phlpmut); \ + } + + static inline int + ATOMIC_DEC_AND_FETCH(int *data, pthread_mutex_t *phlpmut) { + int val; + pthread_mutex_lock(phlpmut); + val = --(*data); + pthread_mutex_unlock(phlpmut); + return(val); + } +#if 0 # warning "atomic builtins not available, using nul operations - rsyslogd will probably be racy!" -# define ATOMIC_INC(data) (++(data)) -# define ATOMIC_DEC(data) (--(data)) -# define ATOMIC_DEC_AND_FETCH(data) (--(data)) -# define ATOMIC_FETCH_32BIT(data) (data) -# define ATOMIC_STORE_1_TO_32BIT(data) (data) = 1 -# define ATOMIC_STORE_1_TO_INT(data) (data) = 1 -# define ATOMIC_STORE_0_TO_INT(data) (data) = 0 -# define ATOMIC_CAS_VAL(data, oldVal, newVal) (data) = (newVal) +# define ATOMIC_INC_AND_FETCH(data) (++(data)) +# define ATOMIC_FETCH_32BIT(data) (data) // TODO: del +# define ATOMIC_STORE_1_TO_32BIT(data) (data) = 1 // TODO: del #endif +# define DEF_ATOMIC_HELPER_MUT(x) pthread_mutex_t x +# define INIT_ATOMIC_HELPER_MUT(x) pthread_mutex_init(&(x), NULL) +# define DESTROY_ATOMIC_HELPER_MUT(x) pthread_mutex_init(&(x), NULL) + +# define PREFER_ATOMIC_INC(data) ((void) ++data) + #endif #endif /* #ifndef INCLUDED_ATOMIC_H */ -- cgit