Fixed a couple of race conditions in the wine_pthread routines at
thread startup and exit.
diff --git a/loader/kthread.c b/loader/kthread.c
index 7255f6b..436f059 100644
--- a/loader/kthread.c
+++ b/loader/kthread.c
@@ -189,6 +189,7 @@
{
/* copy the info structure since it is on the stack we will free */
struct wine_pthread_thread_info info = *(struct wine_pthread_thread_info *)ptr;
+ if (info.cleanup) info.cleanup( &info );
wine_ldt_free_fs( info.teb_sel );
munmap( info.stack_base, info.stack_size );
munmap( info.teb_base, info.teb_size );
@@ -220,34 +221,6 @@
{
struct pthread_descr_struct *descr;
-#ifdef __i386__
- /* On the i386, the current thread is in the %fs register */
- LDT_ENTRY fs_entry;
-
- wine_ldt_set_base( &fs_entry, info->teb_base );
- wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
- wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
- wine_ldt_init_fs( info->teb_sel, &fs_entry );
-#elif defined(__powerpc__)
- /* On PowerPC, the current TEB is in the gpr13 register */
-# ifdef __APPLE__
- __asm__ __volatile__("mr r13, %0" : : "r" (info->teb_base));
-# else
- __asm__ __volatile__("mr 2, %0" : : "r" (info->teb_base));
-# endif
-#elif defined(HAVE__LWP_CREATE)
- /* On non-i386 Solaris, we use the LWP private pointer */
- _lwp_setprivate( info->teb_base );
-#endif
-
- /* set pid and tid */
- info->pid = getpid();
-#ifdef HAVE__LWP_SELF
- info->tid = _lwp_self();
-#else
- info->tid = -1;
-#endif
-
if (funcs.ptr_set_thread_data)
{
descr = calloc( 1, sizeof(*descr) );
@@ -319,6 +292,43 @@
/***********************************************************************
+ * wine_pthread_init_current_teb
+ *
+ * Set the current TEB for a new thread.
+ */
+void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info )
+{
+#ifdef __i386__
+ /* On the i386, the current thread is in the %fs register */
+ LDT_ENTRY fs_entry;
+
+ wine_ldt_set_base( &fs_entry, info->teb_base );
+ wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
+ wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
+ wine_ldt_init_fs( info->teb_sel, &fs_entry );
+#elif defined(__powerpc__)
+ /* On PowerPC, the current TEB is in the gpr13 register */
+# ifdef __APPLE__
+ __asm__ __volatile__("mr r13, %0" : : "r" (info->teb_base));
+# else
+ __asm__ __volatile__("mr 2, %0" : : "r" (info->teb_base));
+# endif
+#elif defined(HAVE__LWP_CREATE)
+ /* On non-i386 Solaris, we use the LWP private pointer */
+ _lwp_setprivate( info->teb_base );
+#endif
+
+ /* set pid and tid */
+ info->pid = getpid();
+#ifdef HAVE__LWP_SELF
+ info->tid = _lwp_self();
+#else
+ info->tid = -1;
+#endif
+}
+
+
+/***********************************************************************
* wine_pthread_get_current_teb
*/
void *wine_pthread_get_current_teb(void)
diff --git a/loader/pthread.c b/loader/pthread.c
index 835786d..e8469c2 100644
--- a/loader/pthread.c
+++ b/loader/pthread.c
@@ -62,20 +62,6 @@
*/
void wine_pthread_init_thread( struct wine_pthread_thread_info *info )
{
-#ifdef __i386__
- /* On the i386, the current thread is in the %fs register */
- LDT_ENTRY fs_entry;
-
- wine_ldt_set_base( &fs_entry, info->teb_base );
- wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
- wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
- wine_ldt_init_fs( info->teb_sel, &fs_entry );
-#else
- if (!funcs.ptr_set_thread_data) /* first thread */
- pthread_key_create( &teb_key, NULL );
- pthread_setspecific( teb_key, info->teb_base );
-#endif
-
/* retrieve the stack info (except for main thread) */
if (funcs.ptr_set_thread_data)
{
@@ -91,10 +77,6 @@
info->stack_base = stack_top - info->stack_size;
#endif
}
-
- /* set pid and tid */
- info->pid = getpid();
- info->tid = gettid();
}
@@ -116,6 +98,33 @@
/***********************************************************************
+ * wine_pthread_init_current_teb
+ *
+ * Set the current TEB for a new thread.
+ */
+void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info )
+{
+#ifdef __i386__
+ /* On the i386, the current thread is in the %fs register */
+ LDT_ENTRY fs_entry;
+
+ wine_ldt_set_base( &fs_entry, info->teb_base );
+ wine_ldt_set_limit( &fs_entry, info->teb_size - 1 );
+ wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
+ wine_ldt_init_fs( info->teb_sel, &fs_entry );
+#else
+ if (!funcs.ptr_set_thread_data) /* first thread */
+ pthread_key_create( &teb_key, NULL );
+ pthread_setspecific( teb_key, info->teb_base );
+#endif
+
+ /* set pid and tid */
+ info->pid = getpid();
+ info->tid = gettid();
+}
+
+
+/***********************************************************************
* wine_pthread_get_current_teb
*/
void *wine_pthread_get_current_teb(void)
@@ -153,6 +162,7 @@
if ((free_info = interlocked_xchg_ptr( (void **)&previous_info, cleanup_info )) != NULL)
{
pthread_join( free_info->self, &ptr );
+ if (free_info->thread_info.cleanup) free_info->thread_info.cleanup( &free_info->thread_info );
wine_ldt_free_fs( free_info->thread_info.teb_sel );
munmap( free_info->thread_info.teb_base, free_info->thread_info.teb_size );
}