1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25
26 #include <ndb_global.h>
27
28 #include <NdbCondition.h>
29 #include <NdbMutex.h>
30 #include <NdbMem.h>
31
32 static int init = 0;
33 #ifdef HAVE_CLOCK_GETTIME
34 static int clock_id = CLOCK_REALTIME;
35 #endif
36
37 void
NdbCondition_initialize(int need_monotonic)38 NdbCondition_initialize(int need_monotonic)
39 {
40 #if defined HAVE_CLOCK_GETTIME && defined HAVE_PTHREAD_CONDATTR_SETCLOCK && \
41 defined CLOCK_MONOTONIC
42
43 int res, condattr_init = 0;
44 pthread_cond_t tmp;
45 pthread_condattr_t attr;
46
47 init = 1;
48
49 if (!need_monotonic)
50 return;
51
52 if ((res = pthread_condattr_init(&attr)) != 0)
53 goto nogo;
54
55 condattr_init = 1;
56
57 if ((res = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) != 0)
58 goto nogo;
59
60 if ((res = pthread_cond_init(&tmp, &attr)) != 0)
61 goto nogo;
62
63 pthread_condattr_destroy(&attr);
64 pthread_cond_destroy(&tmp);
65
66 clock_id = CLOCK_MONOTONIC;
67
68 return;
69
70 nogo:
71 if (condattr_init)
72 {
73 pthread_condattr_destroy(&attr);
74 }
75
76 clock_id = CLOCK_REALTIME;
77 fprintf(stderr,
78 "Failed to use CLOCK_MONOTONIC for pthread_condition res: %u\n",
79 res);
80 fflush(stderr);
81 return;
82 #else
83 init = 1;
84 #endif
85 }
86
87 int
NdbCondition_Init(struct NdbCondition * ndb_cond)88 NdbCondition_Init(struct NdbCondition* ndb_cond)
89 {
90 int result;
91
92 assert(init); /* Make sure library has been initialized */
93
94 #if defined HAVE_CLOCK_GETTIME && defined HAVE_PTHREAD_CONDATTR_SETCLOCK && \
95 defined CLOCK_MONOTONIC
96 if (clock_id == CLOCK_MONOTONIC)
97 {
98 pthread_condattr_t attr;
99 pthread_condattr_init(&attr);
100 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
101 result = pthread_cond_init(&ndb_cond->cond, &attr);
102 pthread_condattr_destroy(&attr);
103 }
104 else
105 {
106 result = pthread_cond_init(&ndb_cond->cond, NULL);
107 }
108 #else
109 result = pthread_cond_init(&ndb_cond->cond, NULL);
110 #endif
111 assert(result==0);
112 return result;
113 }
114
115
116 struct NdbCondition*
NdbCondition_Create(void)117 NdbCondition_Create(void)
118 {
119 struct NdbCondition* tmpCond;
120
121 tmpCond = (struct NdbCondition*)NdbMem_Allocate(sizeof(struct NdbCondition));
122
123 if (tmpCond == NULL)
124 return NULL;
125
126 (void)NdbCondition_Init(tmpCond);
127 return tmpCond;
128 }
129
130 int
NdbCondition_Wait(struct NdbCondition * p_cond,NdbMutex * p_mutex)131 NdbCondition_Wait(struct NdbCondition* p_cond,
132 NdbMutex* p_mutex)
133 {
134 int result;
135
136 if (p_cond == NULL || p_mutex == NULL)
137 return 1;
138
139 #ifdef NDB_MUTEX_STAT
140 result = pthread_cond_wait(&p_cond->cond, &p_mutex->mutex);
141 #else
142 result = pthread_cond_wait(&p_cond->cond, p_mutex);
143 #endif
144
145 return result;
146 }
147
148 int
NdbCondition_WaitTimeout(struct NdbCondition * p_cond,NdbMutex * p_mutex,int msecs)149 NdbCondition_WaitTimeout(struct NdbCondition* p_cond,
150 NdbMutex* p_mutex,
151 int msecs)
152 {
153 struct timespec abstime;
154
155 NdbCondition_ComputeAbsTime(&abstime, msecs);
156 return NdbCondition_WaitTimeoutAbs(p_cond, p_mutex, &abstime);
157 }
158
159 void
NdbCondition_ComputeAbsTime(struct timespec * abstime,unsigned msecs)160 NdbCondition_ComputeAbsTime(struct timespec * abstime, unsigned msecs)
161 {
162 int secs = 0;
163 #ifndef NDB_WIN
164 #ifdef HAVE_CLOCK_GETTIME
165 clock_gettime(clock_id, abstime);
166 #else
167 {
168 struct timeval tick_time;
169 gettimeofday(&tick_time, 0);
170 abstime->tv_sec = tick_time.tv_sec;
171 abstime->tv_nsec = tick_time.tv_usec * 1000;
172 }
173 #endif
174
175 if(msecs >= 1000){
176 secs = msecs / 1000;
177 msecs = msecs % 1000;
178 }
179
180 abstime->tv_sec += secs;
181 abstime->tv_nsec += msecs * 1000000;
182 if (abstime->tv_nsec >= 1000000000) {
183 abstime->tv_sec += 1;
184 abstime->tv_nsec -= 1000000000;
185 }
186 #else
187 set_timespec_nsec(*abstime,msecs*1000000ULL);
188 #endif
189 }
190
191 int
NdbCondition_WaitTimeoutAbs(struct NdbCondition * p_cond,NdbMutex * p_mutex,const struct timespec * abstime)192 NdbCondition_WaitTimeoutAbs(struct NdbCondition* p_cond,
193 NdbMutex* p_mutex,
194 const struct timespec * abstime)
195 {
196 #ifdef NDB_WIN
197 struct timespec tmp = *abstime;
198 abstime = &tmp;
199 #endif
200
201 if (p_cond == NULL || p_mutex == NULL)
202 return 1;
203
204 #ifdef NDB_MUTEX_STAT
205 return pthread_cond_timedwait(&p_cond->cond, &p_mutex->mutex, abstime);
206 #else
207 return pthread_cond_timedwait(&p_cond->cond, p_mutex, abstime);
208 #endif
209 }
210
211 int
NdbCondition_Signal(struct NdbCondition * p_cond)212 NdbCondition_Signal(struct NdbCondition* p_cond){
213 int result;
214
215 if (p_cond == NULL)
216 return 1;
217
218 result = pthread_cond_signal(&p_cond->cond);
219
220 return result;
221 }
222
223
NdbCondition_Broadcast(struct NdbCondition * p_cond)224 int NdbCondition_Broadcast(struct NdbCondition* p_cond)
225 {
226 int result;
227
228 if (p_cond == NULL)
229 return 1;
230
231 result = pthread_cond_broadcast(&p_cond->cond);
232
233 return result;
234 }
235
236
NdbCondition_Destroy(struct NdbCondition * p_cond)237 int NdbCondition_Destroy(struct NdbCondition* p_cond)
238 {
239 int result;
240
241 if (p_cond == NULL)
242 return 1;
243
244 result = pthread_cond_destroy(&p_cond->cond);
245 free(p_cond);
246
247 return 0;
248 }
249
250