@@ -104,63 +104,58 @@ 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 a __cdecl function instead of a __stdcall */
110+ static unsigned __stdcall
112111bootstrap (void * call )
113112{
114113 callobj * obj = (callobj * )call ;
115- /* copy callobj since other thread might free it before we're done */
116114 void (* func )(void * ) = obj -> func ;
117115 void * arg = obj -> arg ;
118-
119- obj -> id = PyThread_get_thread_ident ();
120- ReleaseSemaphore (obj -> done , 1 , NULL );
116+ HeapFree (GetProcessHeap (), 0 , obj );
121117 func (arg );
122118 return 0 ;
123119}
124120
125121long
126122PyThread_start_new_thread (void (* func )(void * ), void * arg )
127123{
128- Py_uintptr_t rv ;
129- callobj obj ;
130-
124+ HANDLE hThread ;
125+ unsigned threadID ;
126+ callobj * obj ;
127+
131128 dprintf (("%ld: PyThread_start_new_thread called\n" ,
132129 PyThread_get_thread_ident ()));
133130 if (!initialized )
134131 PyThread_init_thread ();
135132
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 )
133+ obj = (callobj * )HeapAlloc (GetProcessHeap (), 0 , sizeof (* obj ));
134+ if (!obj )
141135 return -1 ;
142-
143- rv = _beginthread (bootstrap ,
136+ obj -> func = func ;
137+ obj -> arg = arg ;
138+ hThread = (HANDLE )_beginthreadex (0 ,
144139 Py_SAFE_DOWNCAST (_pythread_stacksize ,
145- Py_ssize_t , int ),
146- & obj );
147- if (rv == (Py_uintptr_t )- 1 ) {
140+ Py_ssize_t , unsigned int ),
141+ bootstrap , obj ,
142+ 0 , & threadID );
143+ if (hThread == 0 ) {
148144 /* I've seen errno == EAGAIN here, which means "there are
149145 * too many threads".
150146 */
151- dprintf (("%ld: PyThread_start_new_thread failed: %p errno %d\n" ,
152- PyThread_get_thread_ident (), (void * )rv , errno ));
153- obj .id = -1 ;
147+ dprintf (("%ld: PyThread_start_new_thread failed, errno %d\n" ,
148+ PyThread_get_thread_ident (), errno ));
149+ threadID = (unsigned )-1 ;
150+ HeapFree (GetProcessHeap (), 0 , obj );
154151 }
155152 else {
156153 dprintf (("%ld: PyThread_start_new_thread succeeded: %p\n" ,
157- PyThread_get_thread_ident (), (void * )rv ));
154+ PyThread_get_thread_ident (), (void * )hThread ));
158155 /* wait for thread to initialize, so we can get its id */
159- WaitForSingleObject (obj .done , INFINITE );
160- assert (obj .id != -1 );
156+ CloseHandle (hThread );
161157 }
162- CloseHandle ((HANDLE )obj .done );
163- return obj .id ;
158+ return (long ) threadID ;
164159}
165160
166161/*
@@ -176,52 +171,22 @@ PyThread_get_thread_ident(void)
176171 return GetCurrentThreadId ();
177172}
178173
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-
191174void
192175PyThread_exit_thread (void )
193176{
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 ));
177+ dprintf (("%ld: PyThread_exit_thread called\n" , PyThread_get_thread_ident ()));
208178 if (!initialized )
209- if (no_cleanup )
210- _exit (status );
211- else
212- exit (status );
179+ exit (0 );
180+ _endthreadex (0 );
213181}
214182
183+ #ifndef NO_EXIT_PROG
215184void
216185PyThread_exit_prog (int status )
217186{
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 );
187+ dprintf (("PyThread_exit_prog(%d) called\n" , status ));
188+ if (!initialized )
189+ exit (status );
225190}
226191#endif /* NO_EXIT_PROG */
227192
@@ -309,3 +274,64 @@ _pythread_nt_set_stacksize(size_t size)
309274}
310275
311276#define THREAD_SET_STACKSIZE (x ) _pythread_nt_set_stacksize(x)
277+
278+
279+ /* use native Windows TLS functions */
280+ #define Py_HAVE_NATIVE_TLS
281+
282+ #ifdef Py_HAVE_NATIVE_TLS
283+ int
284+ PyThread_create_key (void )
285+ {
286+ return (int ) TlsAlloc ();
287+ }
288+
289+ void
290+ PyThread_delete_key (int key )
291+ {
292+ TlsFree (key );
293+ }
294+
295+ /* We must be careful to emulate the strange semantics implemented in thread.c,
296+ * where the value is only set if it hasn't been set before.
297+ */
298+ int
299+ PyThread_set_key_value (int key , void * value )
300+ {
301+ BOOL ok ;
302+ void * oldvalue ;
303+
304+ assert (value != NULL );
305+ oldvalue = TlsGetValue (key );
306+ if (oldvalue != NULL )
307+ /* ignore value if already set */
308+ return 0 ;
309+ ok = TlsSetValue (key , value );
310+ if (!ok )
311+ return -1 ;
312+ return 0 ;
313+ }
314+
315+ void *
316+ PyThread_get_key_value (int key )
317+ {
318+ return TlsGetValue (key );
319+ }
320+
321+ void
322+ PyThread_delete_key_value (int key )
323+ {
324+ /* NULL is used as "key missing", and it is also the default
325+ * given by TlsGetValue() if nothing has been set yet.
326+ */
327+ TlsSetValue (key , NULL );
328+ }
329+
330+ /* reinitialization of TLS is not necessary after fork when using
331+ * the native TLS functions. And forking isn't supported on Windows either.
332+ */
333+ void
334+ PyThread_ReInitTLS (void )
335+ {}
336+
337+ #endif
0 commit comments