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 * for win32
9 *****************************************************************************
10 * $Id: rrd_thread_safe_nt.c 1735 2009-01-19 14:29:11Z oetiker $
11 *************************************************************************** */
12
13 #include <windows.h>
14 #include <string.h>
15 /* #include <error.h> */
16 #include "rrd.h"
17 #include "rrd_tool.h"
18
19 /* Key for the thread-specific rrd_context */
20 static DWORD context_key;
21 static CRITICAL_SECTION CriticalSection;
22
23
24 /* Once-only initialisation of the key */
25 static DWORD context_key_once = 0;
26
27
28 /* Free the thread-specific rrd_context - we might actually use
29 rrd_free_context instead...
30 */
context_destroy_context(void)31 static void context_destroy_context(void)
32 {
33 DeleteCriticalSection(&CriticalSection);
34 TlsFree(context_key);
35 context_key_once=0;
36 }
context_init_context(void)37 static void context_init_context(void)
38 {
39 if (!InterlockedExchange(&context_key_once, 1)) {
40 context_key = TlsAlloc();
41 InitializeCriticalSection(&CriticalSection);
42 atexit(context_destroy_context);
43 }
44 }
rrd_get_context(void)45 struct rrd_context *rrd_get_context(void) {
46 struct rrd_context *ctx;
47
48 context_init_context();
49
50 ctx = TlsGetValue(context_key);
51 if (!ctx) {
52 ctx = rrd_new_context();
53 TlsSetValue(context_key, ctx);
54 }
55 return ctx;
56 }
57 #undef strerror
rrd_strerror(int err)58 const char *rrd_strerror(int err) {
59 struct rrd_context *ctx;
60 context_init_context();
61
62 ctx = rrd_get_context();
63
64 EnterCriticalSection(&CriticalSection);
65 strncpy(ctx->lib_errstr, strerror(err), ctx->errlen);
66 ctx->lib_errstr[ctx->errlen] = '\0';
67 LeaveCriticalSection(&CriticalSection);
68
69 return ctx->lib_errstr;
70 }
71 /*
72 * there much be a re-entrant version of these somewhere in win32 land
73 */
localtime_r(const time_t * timep,struct tm * result)74 struct tm* localtime_r(const time_t *timep, struct tm* result)
75 {
76 struct tm *local;
77 context_init_context();
78
79 EnterCriticalSection(&CriticalSection);
80 local = localtime(timep);
81 memcpy(result,local,sizeof(struct tm));
82 LeaveCriticalSection(&CriticalSection);
83 return result;
84 }
ctime_r(const time_t * timep,char * result)85 char* ctime_r(const time_t *timep, char* result)
86 {
87 char *local;
88 context_init_context();
89
90 EnterCriticalSection(&CriticalSection);
91 local = ctime(timep);
92 strcpy(result,local);
93 LeaveCriticalSection(&CriticalSection);
94 return result;
95 }
96
gmtime_r(const time_t * timep,struct tm * result)97 struct tm* gmtime_r(const time_t *timep, struct tm* result)
98 {
99 struct tm *local;
100 context_init_context();
101
102 EnterCriticalSection(&CriticalSection);
103 local = gmtime(timep);
104 memcpy(result,local,sizeof(struct tm));
105 LeaveCriticalSection(&CriticalSection);
106 return result;
107 }
108
109 /* implementation from Apache's APR library */
strtok_r(char * str,const char * sep,char ** last)110 char *strtok_r(char *str, const char *sep, char **last)
111 {
112 char *token;
113 context_init_context();
114
115
116 if (!str) /* subsequent call */
117 str = *last; /* start where we left off */
118
119 /* skip characters in sep (will terminate at '\0') */
120 while (*str && strchr(sep, *str))
121 ++str;
122
123 if (!*str) /* no more tokens */
124 return NULL;
125
126 token = str;
127
128 /* skip valid token characters to terminate token and
129 * prepare for the next call (will terminate at '\0)
130 */
131 *last = token + 1;
132 while (**last && !strchr(sep, **last))
133 ++*last;
134
135 if (**last) {
136 **last = '\0';
137 ++*last;
138 }
139
140 return token;
141 }
142
143