OSDN Git Service

First version
[st-ro/stro.git] / 3rdparty / mysql / include / thr_cond.h
1 #ifndef THR_COND_INCLUDED
2 #define THR_COND_INCLUDED
3
4 /* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; version 2 of the License.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
18
19 /**
20   MySQL condition variable implementation.
21
22   There are three "layers":
23   1) native_cond_*()
24        Functions that map directly down to OS primitives.
25        Windows    - ConditionVariable
26        Other OSes - pthread
27   2) my_cond_*()
28        Functions that use SAFE_MUTEX (default for debug).
29        Otherwise native_cond_*() is used.
30   3) mysql_cond*()
31        Functions that include Performance Schema instrumentation.
32        See include/mysql/psi/mysql_thread.h
33 */
34
35 #include "my_thread.h"
36 #include "thr_mutex.h"
37
38 C_MODE_START
39
40 #ifdef _WIN32
41 typedef CONDITION_VARIABLE native_cond_t;
42 #else
43 typedef pthread_cond_t native_cond_t;
44 #endif
45
46 #ifdef _WIN32
47 /**
48   Convert abstime to milliseconds
49 */
50
51 static DWORD get_milliseconds(const struct timespec *abstime)
52 {
53 #ifndef HAVE_STRUCT_TIMESPEC
54   long long millis;
55   union ft64 now;
56
57   if (abstime == NULL)
58    return INFINITE;
59
60   GetSystemTimeAsFileTime(&now.ft);
61
62   /*
63     Calculate time left to abstime
64     - subtract start time from current time(values are in 100ns units)
65     - convert to millisec by dividing with 10000
66   */
67   millis= (abstime->tv.i64 - now.i64) / 10000;
68
69   /* Don't allow the timeout to be negative */
70   if (millis < 0)
71     return 0;
72
73   /*
74     Make sure the calculated timeout does not exceed original timeout
75     value which could cause "wait for ever" if system time changes
76   */
77   if (millis > abstime->max_timeout_msec)
78     millis= abstime->max_timeout_msec;
79
80   if (millis > UINT_MAX)
81     millis= UINT_MAX;
82
83   return (DWORD)millis;
84 #else
85   /*
86     Convert timespec to millis and subtract current time.
87     my_getsystime() returns time in 100 ns units.
88   */
89   ulonglong future= abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000;
90   ulonglong now= my_getsystime() / 10000;
91   /* Don't allow the timeout to be negative. */
92   if (future < now)
93     return 0;
94   return (DWORD)(future - now);
95 #endif
96 }
97 #endif /* _WIN32 */
98
99 static inline int native_cond_init(native_cond_t *cond)
100 {
101 #ifdef _WIN32
102   InitializeConditionVariable(cond);
103   return 0;
104 #else
105   /* pthread_condattr_t is not used in MySQL */
106   return pthread_cond_init(cond, NULL);
107 #endif
108 }
109
110 static inline int native_cond_destroy(native_cond_t *cond)
111 {
112 #ifdef _WIN32
113   return 0; /* no destroy function */
114 #else
115   return pthread_cond_destroy(cond);
116 #endif
117 }
118
119 static inline int native_cond_timedwait(native_cond_t *cond,
120                                         native_mutex_t *mutex,
121                                         const struct timespec *abstime)
122 {
123 #ifdef _WIN32
124   DWORD timeout= get_milliseconds(abstime);
125   if (!SleepConditionVariableCS(cond, mutex, timeout))
126     return ETIMEDOUT;
127   return 0;
128 #else
129   return pthread_cond_timedwait(cond, mutex, abstime);
130 #endif
131 }
132
133 static inline int native_cond_wait(native_cond_t *cond, native_mutex_t *mutex)
134 {
135 #ifdef _WIN32
136   if (!SleepConditionVariableCS(cond, mutex, INFINITE))
137     return ETIMEDOUT;
138   return 0;
139 #else
140   return pthread_cond_wait(cond, mutex);
141 #endif
142 }
143
144 static inline int native_cond_signal(native_cond_t *cond)
145 {
146 #ifdef _WIN32
147   WakeConditionVariable(cond);
148   return 0;
149 #else
150   return pthread_cond_signal(cond);
151 #endif
152 }
153
154 static inline int native_cond_broadcast(native_cond_t *cond)
155 {
156 #ifdef _WIN32
157   WakeAllConditionVariable(cond);
158   return 0;
159 #else
160   return pthread_cond_broadcast(cond);
161 #endif
162 }
163
164 #ifdef SAFE_MUTEX
165 int safe_cond_wait(native_cond_t *cond, my_mutex_t *mp,
166                    const char *file, uint line);
167 int safe_cond_timedwait(native_cond_t *cond, my_mutex_t *mp,
168                         const struct timespec *abstime,
169                         const char *file, uint line);
170 #endif
171
172 static inline int my_cond_timedwait(native_cond_t *cond, my_mutex_t *mp,
173                                     const struct timespec *abstime
174 #ifdef SAFE_MUTEX
175                                     , const char *file, uint line
176 #endif
177                                     )
178 {
179 #ifdef SAFE_MUTEX
180   return safe_cond_timedwait(cond, mp, abstime, file, line);
181 #else
182   return native_cond_timedwait(cond, mp, abstime);
183 #endif
184 }
185
186 static inline int my_cond_wait(native_cond_t *cond, my_mutex_t *mp
187 #ifdef SAFE_MUTEX
188                                , const char *file, uint line
189 #endif
190                                )
191 {
192 #ifdef SAFE_MUTEX
193   return safe_cond_wait(cond, mp, file, line);
194 #else
195   return native_cond_wait(cond, mp);
196 #endif
197 }
198
199 C_MODE_END
200
201 #endif /* THR_COND_INCLUDED */