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