MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_winthread.c
1 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*****************************************************************************
17 ** Simulation of posix threads calls for Windows
18 *****************************************************************************/
19 #if defined (_WIN32)
20 /* SAFE_MUTEX will not work until the thread structure is up to date */
21 #undef SAFE_MUTEX
22 #include "mysys_priv.h"
23 #include <process.h>
24 #include <signal.h>
25 
26 static void install_sigabrt_handler(void);
27 
28 struct thread_start_parameter
29 {
30  pthread_handler func;
31  void *arg;
32 };
33 
40 int
41 win_pthread_mutex_trylock(pthread_mutex_t *mutex)
42 {
43  if (TryEnterCriticalSection(mutex))
44  {
45  /* Don't allow recursive lock */
46  if (mutex->RecursionCount > 1){
47  LeaveCriticalSection(mutex);
48  return EBUSY;
49  }
50  return 0;
51  }
52  return EBUSY;
53 }
54 
55 static unsigned int __stdcall pthread_start(void *p)
56 {
57  struct thread_start_parameter *par= (struct thread_start_parameter *)p;
58  pthread_handler func= par->func;
59  void *arg= par->arg;
60  free(p);
61  (*func)(arg);
62  return 0;
63 }
64 
65 
66 int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr,
67  pthread_handler func, void *param)
68 {
69  uintptr_t handle;
70  struct thread_start_parameter *par;
71  unsigned int stack_size;
72  int error_no;
73  DBUG_ENTER("pthread_create");
74 
75  par= (struct thread_start_parameter *)malloc(sizeof(*par));
76  if (!par)
77  goto error_return;
78 
79  par->func= func;
80  par->arg= param;
81  stack_size= attr?attr->dwStackSize:0;
82 
83  handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
84  if (!handle)
85  goto error_return;
86  DBUG_PRINT("info", ("thread id=%u",*thread_id));
87 
88  /* Do not need thread handle, close it */
89  CloseHandle((HANDLE)handle);
90  DBUG_RETURN(0);
91 
92 error_return:
93  error_no= errno;
94  DBUG_PRINT("error",
95  ("Can't create thread to handle request (error %d)",error_no));
96  DBUG_RETURN(error_no);
97 }
98 
99 
100 void pthread_exit(void *a)
101 {
102  _endthreadex(0);
103 }
104 
105 int pthread_join(pthread_t thread, void **value_ptr)
106 {
107  DWORD ret;
108  HANDLE handle;
109 
110  handle= OpenThread(SYNCHRONIZE, FALSE, thread);
111  if (!handle)
112  {
113  errno= EINVAL;
114  goto error_return;
115  }
116 
117  ret= WaitForSingleObject(handle, INFINITE);
118 
119  if(ret != WAIT_OBJECT_0)
120  {
121  errno= EINVAL;
122  goto error_return;
123  }
124 
125  CloseHandle(handle);
126  return 0;
127 
128 error_return:
129  if(handle)
130  CloseHandle(handle);
131  return -1;
132 }
133 
134 int pthread_cancel(pthread_t thread)
135 {
136 
137  HANDLE handle= 0;
138  BOOL ok= FALSE;
139 
140  handle= OpenThread(THREAD_TERMINATE, FALSE, thread);
141  if (handle)
142  {
143  ok= TerminateThread(handle,0);
144  CloseHandle(handle);
145  }
146  if (ok)
147  return 0;
148 
149  errno= EINVAL;
150  return -1;
151 }
152 
153 /*
154  One time initialization. For simplicity, we assume initializer thread
155  does not exit within init_routine().
156 */
157 int my_pthread_once(my_pthread_once_t *once_control,
158  void (*init_routine)(void))
159 {
160  LONG state;
161 
162  /*
163  Do "dirty" read to find out if initialization is already done, to
164  save an interlocked operation in common case. Memory barriers are ensured by
165  Visual C++ volatile implementation.
166  */
167  if (*once_control == MY_PTHREAD_ONCE_DONE)
168  return 0;
169 
170  state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
171  MY_PTHREAD_ONCE_INIT);
172 
173  switch(state)
174  {
175  case MY_PTHREAD_ONCE_INIT:
176  /* This is initializer thread */
177  (*init_routine)();
178  *once_control= MY_PTHREAD_ONCE_DONE;
179  break;
180 
181  case MY_PTHREAD_ONCE_INPROGRESS:
182  /* init_routine in progress. Wait for its completion */
183  while(*once_control == MY_PTHREAD_ONCE_INPROGRESS)
184  {
185  Sleep(1);
186  }
187  break;
188  case MY_PTHREAD_ONCE_DONE:
189  /* Nothing to do */
190  break;
191  }
192  return 0;
193 }
194 #endif