@@ -104,63 +104,77 @@ PyThread__init_thread(void)
104104typedef struct {
105105 void (* func )(void * );
106106 void * arg ;
107- long id ;
108- HANDLE done ;
109107} callobj ;
110108
111- static int
109+ /* thunker to call adapt between the function type used by the system's
110+ thread start function and the internally used one. */
111+ #if defined(MS_WINCE )
112+ static DWORD WINAPI
113+ #else
114+ static unsigned __stdcall
115+ #endif
112116bootstrap (void * call )
113117{
114118 callobj * obj = (callobj * )call ;
115- /* copy callobj since other thread might free it before we're done */
116119 void (* func )(void * ) = obj -> func ;
117120 void * arg = obj -> arg ;
118-
119- obj -> id = PyThread_get_thread_ident ();
120- ReleaseSemaphore (obj -> done , 1 , NULL );
121+ HeapFree (GetProcessHeap (), 0 , obj );
121122 func (arg );
122123 return 0 ;
123124}
124125
125126long
126127PyThread_start_new_thread (void (* func )(void * ), void * arg )
127128{
128- Py_uintptr_t rv ;
129- callobj obj ;
130-
129+ HANDLE hThread ;
130+ unsigned threadID ;
131+ callobj * obj ;
132+
131133 dprintf (("%ld: PyThread_start_new_thread called\n" ,
132134 PyThread_get_thread_ident ()));
133135 if (!initialized )
134136 PyThread_init_thread ();
135137
136- obj .id = -1 ; /* guilty until proved innocent */
137- obj .func = func ;
138- obj .arg = arg ;
139- obj .done = CreateSemaphore (NULL , 0 , 1 , NULL );
140- if (obj .done == NULL )
138+ obj = (callobj * )HeapAlloc (GetProcessHeap (), 0 , sizeof (* obj ));
139+ if (!obj )
141140 return -1 ;
142-
143- rv = _beginthread (bootstrap ,
141+ obj -> func = func ;
142+ obj -> arg = arg ;
143+ #if defined(MS_WINCE )
144+ hThread = CreateThread (NULL ,
145+ Py_SAFE_DOWNCAST (_pythread_stacksize , Py_ssize_t , SIZE_T ),
146+ bootstrap , obj , 0 , & threadID );
147+ #else
148+ hThread = (HANDLE )_beginthreadex (0 ,
144149 Py_SAFE_DOWNCAST (_pythread_stacksize ,
145- Py_ssize_t , int ),
146- & obj );
147- if (rv == (Py_uintptr_t )- 1 ) {
150+ Py_ssize_t , unsigned int ),
151+ bootstrap , obj ,
152+ 0 , & threadID );
153+ #endif
154+ if (hThread == 0 ) {
155+ #if defined(MS_WINCE )
156+ /* Save error in variable, to prevent PyThread_get_thread_ident
157+ from clobbering it. */
158+ unsigned e = GetLastError ();
159+ dprintf (("%ld: PyThread_start_new_thread failed, win32 error code %u\n" ,
160+ PyThread_get_thread_ident (), e ));
161+ #else
148162 /* I've seen errno == EAGAIN here, which means "there are
149163 * too many threads".
150164 */
151- dprintf (("%ld: PyThread_start_new_thread failed: %p errno %d\n" ,
152- PyThread_get_thread_ident (), (void * )rv , errno ));
153- obj .id = -1 ;
165+ int e = errno ;
166+ dprintf (("%ld: PyThread_start_new_thread failed, errno %d\n" ,
167+ PyThread_get_thread_ident (), e ));
168+ #endif
169+ threadID = (unsigned )-1 ;
170+ HeapFree (GetProcessHeap (), 0 , obj );
154171 }
155172 else {
156173 dprintf (("%ld: PyThread_start_new_thread succeeded: %p\n" ,
157- PyThread_get_thread_ident (), (void * )rv ));
158- /* wait for thread to initialize, so we can get its id */
159- WaitForSingleObject (obj .done , INFINITE );
160- assert (obj .id != -1 );
174+ PyThread_get_thread_ident (), (void * )hThread ));
175+ CloseHandle (hThread );
161176 }
162- CloseHandle ((HANDLE )obj .done );
163- return obj .id ;
177+ return (long ) threadID ;
164178}
165179
166180/*
@@ -176,52 +190,26 @@ PyThread_get_thread_ident(void)
176190 return GetCurrentThreadId ();
177191}
178192
179- static void
180- do_PyThread_exit_thread (int no_cleanup )
181- {
182- dprintf (("%ld: PyThread_exit_thread called\n" , PyThread_get_thread_ident ()));
183- if (!initialized )
184- if (no_cleanup )
185- _exit (0 );
186- else
187- exit (0 );
188- _endthread ();
189- }
190-
191193void
192194PyThread_exit_thread (void )
193195{
194- do_PyThread_exit_thread (0 );
195- }
196-
197- void
198- PyThread__exit_thread (void )
199- {
200- do_PyThread_exit_thread (1 );
201- }
202-
203- #ifndef NO_EXIT_PROG
204- static void
205- do_PyThread_exit_prog (int status , int no_cleanup )
206- {
207- dprintf (("PyThread_exit_prog(%d) called\n" , status ));
196+ dprintf (("%ld: PyThread_exit_thread called\n" , PyThread_get_thread_ident ()));
208197 if (!initialized )
209- if (no_cleanup )
210- _exit (status );
211- else
212- exit (status );
198+ exit (0 );
199+ #if defined(MS_WINCE )
200+ ExitThread (0 );
201+ #else
202+ _endthreadex (0 );
203+ #endif
213204}
214205
206+ #ifndef NO_EXIT_PROG
215207void
216208PyThread_exit_prog (int status )
217209{
218- do_PyThread_exit_prog (status , 0 );
219- }
220-
221- void
222- PyThread__exit_prog (int status )
223- {
224- do_PyThread_exit_prog (status , 1 );
210+ dprintf (("PyThread_exit_prog(%d) called\n" , status ));
211+ if (!initialized )
212+ exit (status );
225213}
226214#endif /* NO_EXIT_PROG */
227215
@@ -309,3 +297,73 @@ _pythread_nt_set_stacksize(size_t size)
309297}
310298
311299#define THREAD_SET_STACKSIZE (x ) _pythread_nt_set_stacksize(x)
300+
301+
302+ /* use native Windows TLS functions */
303+ #define Py_HAVE_NATIVE_TLS
304+
305+ #ifdef Py_HAVE_NATIVE_TLS
306+ int
307+ PyThread_create_key (void )
308+ {
309+ return (int ) TlsAlloc ();
310+ }
311+
312+ void
313+ PyThread_delete_key (int key )
314+ {
315+ TlsFree (key );
316+ }
317+
318+ /* We must be careful to emulate the strange semantics implemented in thread.c,
319+ * where the value is only set if it hasn't been set before.
320+ */
321+ int
322+ PyThread_set_key_value (int key , void * value )
323+ {
324+ BOOL ok ;
325+ void * oldvalue ;
326+
327+ assert (value != NULL );
328+ oldvalue = TlsGetValue (key );
329+ if (oldvalue != NULL )
330+ /* ignore value if already set */
331+ return 0 ;
332+ ok = TlsSetValue (key , value );
333+ if (!ok )
334+ return -1 ;
335+ return 0 ;
336+ }
337+
338+ void *
339+ PyThread_get_key_value (int key )
340+ {
341+ /* because TLS is used in the Py_END_ALLOW_THREAD macro,
342+ * it is necessary to preserve the windows error state, because
343+ * it is assumed to be preserved across the call to the macro.
344+ * Ideally, the macro should be fixed, but it is simpler to
345+ * do it here.
346+ */
347+ DWORD error = GetLastError ();
348+ void * result = TlsGetValue (key );
349+ SetLastError (error );
350+ return result ;
351+ }
352+
353+ void
354+ PyThread_delete_key_value (int key )
355+ {
356+ /* NULL is used as "key missing", and it is also the default
357+ * given by TlsGetValue() if nothing has been set yet.
358+ */
359+ TlsSetValue (key , NULL );
360+ }
361+
362+ /* reinitialization of TLS is not necessary after fork when using
363+ * the native TLS functions. And forking isn't supported on Windows either.
364+ */
365+ void
366+ PyThread_ReInitTLS (void )
367+ {}
368+
369+ #endif
0 commit comments