mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / mysys / my_winthread.c
blob0afbd6558ea42ec1885c86ffa17f210399971f0a
1 /*
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 */
24 #undef SAFE_MUTEX
26 #include "mysys_priv.h"
27 #if defined(THREAD) && defined(__WIN__)
28 #include <m_string.h>
29 #undef getpid
30 #include <process.h>
32 static pthread_mutex_t THR_LOCK_thread;
34 struct pthread_map
36 HANDLE pthreadself;
37 pthread_handler func;
38 void *param;
41 void win_pthread_init(void)
43 pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
47 /**
48 Adapter to @c pthread_mutex_trylock()
50 @retval 0 Mutex was acquired
51 @retval EBUSY Mutex was already locked by a thread
53 int
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);
61 return EBUSY;
63 return 0;
65 return EBUSY;
70 ** We have tried to use '_beginthreadex' instead of '_beginthread' here
71 ** but in this case the program leaks about 512 characters for each
72 ** created thread !
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
76 ** in the new thread.
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)
96 HANDLE hThread;
97 struct pthread_map *map;
98 DBUG_ENTER("pthread_create");
100 if (!(map=malloc(sizeof(*map))))
101 DBUG_RETURN(-1);
102 map->func=func;
103 map->param=param;
104 pthread_mutex_lock(&THR_LOCK_thread);
105 #ifdef __BORLANDC__
106 hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
107 attr->dwStackSize ? attr->dwStackSize :
108 65535, (void*) map);
109 #else
110 hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
111 attr->dwStackSize ? attr->dwStackSize :
112 65535, (void*) map);
113 #endif
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)
120 int error=errno;
121 DBUG_PRINT("error",
122 ("Can't create thread to handle request (error %d)",error));
123 DBUG_RETURN(error ? error : -1);
125 VOID(SetThreadPriority(hThread, attr->priority)) ;
126 DBUG_RETURN(0);
130 void pthread_exit(void *a)
132 _endthread();
135 /* This is neaded to get the macro pthread_setspecific to work */
137 int win_pthread_setspecific(void *a,void *b,uint length)
139 memcpy(a,b,length);
140 return 0;
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);
153 switch(state)
155 case MY_PTHREAD_ONCE_INIT:
156 /* This is initializer thread */
157 (*init_routine)();
158 *once_control= MY_PTHREAD_ONCE_DONE;
159 break;
161 case MY_PTHREAD_ONCE_INPROGRESS:
162 /* init_routine in progress. Wait for its completion */
163 while(*once_control == MY_PTHREAD_ONCE_INPROGRESS)
165 Sleep(1);
167 break;
168 case MY_PTHREAD_ONCE_DONE:
169 /* Nothing to do */
170 break;
172 return 0;
175 #endif