LWP Threads (again)

Gregg Mattinson gm138242 at scot.canada.sun.com
Fri Jul 12 13:56:07 CDT 2002


I submitted this patch on June 5th, but it appears that it didn't get put in.

ChangeLog: include/thread.h scheduler/sysdeps.c
           scheduler/thread.c server/ptrace.c
 - Fixed SuspendThread / ResumeThread for LWP threads
 - Fixed crash in ExitThread


SYSDEPS_ExitThread wasn't checking the return code of VirtualQuery.  Since the 
stack is in high memory on Sparc (kernel memory, according to a comment in 
VirtualQuery) this caused any program which calls ExitThread to crash.  That is 
fixed now.

Also, SuspendThread and ResumeThread were using signals.  This DOES NOT work 
with LWP threads.  LWP threads are actually in the same process, so sending 
SIGSTOP to the PID of one thread stops the ENTIRE process.  This patch fixes 
this bug too.

Gregg Mattinson
Co-op Developer
Sun Microsystems of Canada

-------------- next part --------------
Index: include/thread.h
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/include/thread.h,v
retrieving revision 1.1
diff -u -r1.1 thread.h
--- /tmp/T01RayjX	Fri Jul 12 10:00:20 2002
+++ thread.h	Mon Jun 10 14:59:07 2002
@@ -147,6 +147,8 @@
 extern void SYSDEPS_ExitThread( int status ) WINE_NORETURN;
 extern void SYSDEPS_AbortThread( int status ) WINE_NORETURN;
 extern void SYSDEPS_SwitchToThreadStack( void (*func)(void) ) WINE_NORETURN;
+extern void SYSDEPS_SuspendThread( TEB *teb );
+extern void SYSDEPS_ResumeThread( TEB *teb );
 
 /* signal handling */
 extern BOOL SIGNAL_Init(void);
Index: scheduler/sysdeps.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/sysdeps.c,v
retrieving revision 1.1
diff -u -r1.1 sysdeps.c
--- /tmp/T04_aWLX       Fri Jul 12 14:43:44 2002
+++ sysdeps.c   Fri Jul 12 14:40:18 2002
@@ -167,6 +167,32 @@
 
 
 /***********************************************************************
+ *           SYSDEPS_SuspendThread
+ *
+ * Suspend a thread.
+ */
+void SYSDEPS_SuspendThread( TEB *teb )
+{
+#ifdef HAVE__LWP_CREATE
+    _lwp_suspend(teb->pthread_data);
+#endif
+}
+
+
+/***********************************************************************
+ *           SYSDEPS_ResumeThread
+ *
+ * Resume a thread.
+ */
+void SYSDEPS_ResumeThread( TEB *teb )
+{
+#ifdef HAVE__LWP_CREATE
+    _lwp_continue(teb->pthread_data);
+#endif
+}
+
+
+/***********************************************************************
  *           SYSDEPS_SpawnThread
  *
  * Start running a new thread.
@@ -211,7 +237,7 @@
     ucontext_t context;
     _lwp_makecontext( &context, (void(*)(void *))SYSDEPS_StartThread, teb,
                       NULL, teb->stack_base, (char *)teb->stack_top - (char *)teb->stack_base );
-    if ( _lwp_create( &context, 0, NULL ) )
+    if ( _lwp_create( &context, 0, &teb->pthread_data ) )
         return -1;
     return 0;
 #endif
@@ -279,9 +305,13 @@
     MEMORY_BASIC_INFORMATION meminfo;
 
     FreeSelector16( teb->stack_sel );
-    VirtualQuery( teb->stack_top, &meminfo, sizeof(meminfo) );
-    info.stack_base = meminfo.AllocationBase;
-    info.stack_size = meminfo.RegionSize + ((char *)teb->stack_top - (char *)meminfo.AllocationBase);
+    if( VirtualQuery( teb->stack_top, &meminfo, sizeof(meminfo) ) ) {
+      info.stack_base = meminfo.AllocationBase;
+      info.stack_size = meminfo.RegionSize + ((char *)teb->stack_top - (char *)meminfo.AllocationBase);
+    } else {
+      info.stack_base = 0;
+      info.stack_size = 0;
+    }
     info.status     = status;
 
     SIGNAL_Reset();
Index: scheduler/thread.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/thread.c,v
retrieving revision 1.1
diff -u -r1.1 thread.c
--- /tmp/T0y3aWrX	Fri Jul 12 10:00:54 2002
+++ thread.c	Mon Jun 10 15:11:20 2002
@@ -82,6 +82,32 @@
 
 
 /***********************************************************************
+ *           THREAD_HandleToTEB
+ *
+ * Convert a thread handle to a TEB, making sure it is valid.
+ */
+static TEB *THREAD_HandleToTEB( HANDLE hthread )
+{
+    TEB *ret = NULL;
+
+    if (!hthread) return NtCurrentTeb();
+
+    SERVER_START_REQ( get_thread_info )
+    {
+        req->handle = hthread;
+        req->tid_in = 0;
+        if (!wine_server_call( req )) ret = reply->teb;
+    }
+    SERVER_END_REQ;
+
+    if (!ret)
+        SetLastError( ERROR_INVALID_PARAMETER );
+
+    return ret;
+}
+
+
+/***********************************************************************
  *           THREAD_InitTEB
  *
  * Initialization of a newly created TEB.
@@ -628,6 +654,10 @@
         if (!wine_server_call_err( req )) ret = reply->count;
     }
     SERVER_END_REQ;
+
+    if (ret == 1)
+        SYSDEPS_ResumeThread( THREAD_HandleToTEB(hthread) );
+
     return ret;
 }
 
@@ -649,6 +679,10 @@
         if (!wine_server_call_err( req )) ret = reply->count;
     }
     SERVER_END_REQ;
+
+    if (ret == 0)
+        SYSDEPS_SuspendThread( THREAD_HandleToTEB(hthread) );
+
     return ret;
 }
 
Index: server/ptrace.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/ptrace.c,v
retrieving revision 1.1
diff -u -r1.1 ptrace.c
--- /tmp/T0YpaGsX	Fri Jul 12 10:00:55 2002
+++ ptrace.c	Mon Jun 10 15:13:20 2002
@@ -168,7 +168,9 @@
     }
     else
     {
+#ifndef HAVE__LWP_CREATE
         if (sig) kill( thread->unix_pid, sig );
+#endif
         if (thread->suspend + thread->process->suspend) continue_thread( thread );
     }
 }
@@ -178,6 +180,7 @@
 {
     /* can't stop a thread while initialisation is in progress */
     if (!thread->unix_pid || !is_process_init_done(thread->process)) return;
+#ifndef HAVE__LWP_CREATE
     /* first try to attach to it */
     if (!thread->attached)
         if (attach_thread( thread )) return;  /* this will have stopped it */
@@ -185,15 +188,18 @@
     if (!thread->unix_pid) return;
     kill( thread->unix_pid, SIGSTOP );
     if (thread->attached) wait4_thread( thread, SIGSTOP );
+#endif
 }
 
 /* make a thread continue (at the Unix level) */
 void continue_thread( struct thread *thread )
 {
     if (!thread->unix_pid) return;
+#ifndef HAVE__LWP_CREATE
     if (!thread->attached) kill( thread->unix_pid, SIGCONT );
     else ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT,
                  thread->unix_pid, (caddr_t)1, SIGSTOP );
+#endif
 }
 
 /* suspend a thread to allow using ptrace on it */


More information about the wine-patches mailing list