1 /***************************************************************************** 2 * RRDtool 1.2.30 Copyright by Tobi Oetiker, 1997-2009 3 * This file: Copyright 2003 Peter Stamfest <peter@stamfest.at> 4 * & Tobias Oetiker 5 * Distributed under the GPL 6 ***************************************************************************** 7 * rrd_thread_safe.c Contains routines used when thread safety is required 8 ***************************************************************************** 9 * $Id: rrd_thread_safe.c 1735 2009-01-19 14:29:11Z oetiker $ 10 *************************************************************************** */ 11 12 #include <pthread.h> 13 #include <string.h> 14 /* #include <error.h> */ 15 #include "rrd.h" 16 #include "rrd_tool.h" 17 18 /* Key for the thread-specific rrd_context */ 19 static pthread_key_t context_key; 20 21 /* Once-only initialisation of the key */ 22 static pthread_once_t context_key_once = PTHREAD_ONCE_INIT; 23 24 /* Free the thread-specific rrd_context - we might actually use 25 rrd_free_context instead... 26 */ context_destroy_context(void * ctx_)27static void context_destroy_context(void *ctx_) 28 { 29 struct rrd_context *ctx = ctx_; 30 if (ctx) rrd_free_context(ctx); 31 } 32 33 /* Allocate the key */ context_get_key()34static void context_get_key() 35 { 36 pthread_key_create(&context_key, context_destroy_context); 37 } 38 rrd_get_context(void)39struct rrd_context *rrd_get_context(void) { 40 struct rrd_context *ctx; 41 42 pthread_once(&context_key_once, context_get_key); 43 ctx = pthread_getspecific(context_key); 44 if (!ctx) { 45 ctx = rrd_new_context(); 46 pthread_setspecific(context_key, ctx); 47 } 48 return ctx; 49 } 50 51 #ifdef HAVE_STRERROR_R rrd_strerror(int err)52const char *rrd_strerror(int err) { 53 struct rrd_context *ctx = rrd_get_context(); 54 if (strerror_r(err, ctx->lib_errstr, ctx->errlen)) 55 return "strerror_r failed. sorry!"; 56 else 57 return ctx->lib_errstr; 58 } 59 #else 60 #undef strerror rrd_strerror(int err)61const char *rrd_strerror(int err) { 62 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 63 struct rrd_context *ctx; 64 ctx = rrd_get_context(); 65 pthread_mutex_lock(&mtx); 66 strncpy(ctx->lib_errstr, strerror(err), ctx->errlen); 67 ctx->lib_errstr[ctx->errlen]='\0'; 68 pthread_mutex_unlock(&mtx); 69 return ctx->lib_errstr; 70 } 71 #endif 72 73