2 Copyright (c) 2000, 2001, 2005, 2007 MySQL AB, 2009 Sun Microsystems, Inc.
3 Use is subject to license terms.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 /*****************************************************************************
20 ** Simulation of posix threads calls for WIN95 and NT
21 *****************************************************************************/
23 /* SAFE_MUTEX will not work until the thread structure is up to date */
26 #include "mysys_priv.h"
27 #if defined(THREAD) && defined(__WIN__)
32 static pthread_mutex_t THR_LOCK_thread
;
41 void win_pthread_init(void)
43 pthread_mutex_init(&THR_LOCK_thread
,MY_MUTEX_INIT_FAST
);
48 Adapter to @c pthread_mutex_trylock()
50 @retval 0 Mutex was acquired
51 @retval EBUSY Mutex was already locked by a thread
54 win_pthread_mutex_trylock(pthread_mutex_t
*mutex
)
56 if (TryEnterCriticalSection(mutex
))
58 /* Don't allow recursive lock */
59 if (mutex
->RecursionCount
> 1){
60 LeaveCriticalSection(mutex
);
70 ** We have tried to use '_beginthreadex' instead of '_beginthread' here
71 ** but in this case the program leaks about 512 characters for each
73 ** As we want to save the created thread handler for other threads to
74 ** use and to be returned by pthread_self() (instead of the Win32 pseudo
75 ** handler), we have to go trough pthread_start() to catch the returned handler
79 pthread_handler_t
pthread_start(void *param
)
81 pthread_handler func
=((struct pthread_map
*) param
)->func
;
82 void *func_param
=((struct pthread_map
*) param
)->param
;
83 my_thread_init(); /* Will always succeed in windows */
84 pthread_mutex_lock(&THR_LOCK_thread
); /* Wait for beginthread to return */
85 win_pthread_self
=((struct pthread_map
*) param
)->pthreadself
;
86 pthread_mutex_unlock(&THR_LOCK_thread
);
87 free((char*) param
); /* Free param from create */
88 pthread_exit((void*) (*func
)(func_param
));
89 return 0; /* Safety */
93 int pthread_create(pthread_t
*thread_id
, pthread_attr_t
*attr
,
94 pthread_handler func
, void *param
)
97 struct pthread_map
*map
;
98 DBUG_ENTER("pthread_create");
100 if (!(map
=malloc(sizeof(*map
))))
104 pthread_mutex_lock(&THR_LOCK_thread
);
106 hThread
=(HANDLE
)_beginthread((void(_USERENTRY
*)(void *)) pthread_start
,
107 attr
->dwStackSize
? attr
->dwStackSize
:
110 hThread
=(HANDLE
)_beginthread((void( __cdecl
*)(void *)) pthread_start
,
111 attr
->dwStackSize
? attr
->dwStackSize
:
114 DBUG_PRINT("info", ("hThread=%lu",(long) hThread
));
115 *thread_id
=map
->pthreadself
=hThread
;
116 pthread_mutex_unlock(&THR_LOCK_thread
);
118 if (hThread
== (HANDLE
) -1)
122 ("Can't create thread to handle request (error %d)",error
));
123 DBUG_RETURN(error
? error
: -1);
125 VOID(SetThreadPriority(hThread
, attr
->priority
)) ;
130 void pthread_exit(void *a
)
135 /* This is neaded to get the macro pthread_setspecific to work */
137 int win_pthread_setspecific(void *a
,void *b
,uint length
)
145 One time initialization. For simplicity, we assume initializer thread
146 does not exit within init_routine().
148 int my_pthread_once(my_pthread_once_t
*once_control
,
149 void (*init_routine
)(void))
151 LONG state
= InterlockedCompareExchange(once_control
, MY_PTHREAD_ONCE_INPROGRESS
,
152 MY_PTHREAD_ONCE_INIT
);
155 case MY_PTHREAD_ONCE_INIT
:
156 /* This is initializer thread */
158 *once_control
= MY_PTHREAD_ONCE_DONE
;
161 case MY_PTHREAD_ONCE_INPROGRESS
:
162 /* init_routine in progress. Wait for its completion */
163 while(*once_control
== MY_PTHREAD_ONCE_INPROGRESS
)
168 case MY_PTHREAD_ONCE_DONE
: