Threading on Solaris
Gregg Mattinson
gm138242 at scot.canada.sun.com
Tue Aug 13 06:52:40 CDT 2002
This is a patch against wine-20020710 to fix threading in Solaris. I submitted
it over two weeks ago, and I was wondering what's happened to it. Unfortunatly,
Sun has moved it's focus away from Wine, so I no longer have time to submit
patches. I just wanted to make sure this patch gets in because it will
*hopefully* fix many issues for OSs which use LWPs.
Thanks,
Gregg Mattinson
Co-op Developer
Sun Microsystems of Canada
------------- Begin Forwarded Message -------------
From: Gregg Mattinson <gm138242 at opcom-mail.canada.sun.com>
Subject: Threading on Solaris
To: wine-patches at winehq.com
Date: Fri, 26 Jul 2002 13:48:42 -0400 (EDT)
Here is my first attempt at fixing threads for Solaris. This patch is based on
the comments from and bug entered by Francois Gouget.
I compiled the wineserver under i386-solaris, and it runs. I do not have the
resources to compile ALL of wine under i386, or on any OS other than Solaris so
the linux and BSD portions of this code are completly un-tested.
ChangeLog:
include/wine/server_protocol.h
scheduler/client.c
scheduler/process.c
server/console.c
server/context_i386.c
server/context_sparc.c
server/debugger.c
server/process.c
server/process.h
server/ptrace.c
server/thread.c
server/thread.h
server/trace.c
- Improved wineserver's handling of LWPs by following recommendations from
http://bugs.winehq.com/show_bug.cgi?id=904 With LWPs (Solaris), each wine
process contains the unix_pid, and each thread contains the LWP id. Without
LWPs (Linux, BSD, ...) each process contains the unix_pid 0, and each thread
contains the actual unix pid in it's tid member.
------------- End Forwarded Message -------------
-------------- next part --------------
Index: include/wine/server_protocol.h
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/include/wine/server_protocol.h,v
retrieving revision 1.1
diff -u -r1.1 server_protocol.h
--- /tmp/T0usaaXl Fri Jul 26 09:17:16 2002
+++ server_protocol.h Wed Jul 24 10:28:34 2002
@@ -248,7 +248,9 @@
{
struct request_header __header;
void* ldt_copy;
- int ppid;
+ int unix_pid;
+ int unix_ppid;
+ int unix_ptid;
};
struct init_process_reply
{
@@ -298,7 +300,7 @@
struct init_thread_request
{
struct request_header __header;
- int unix_pid;
+ int unix_tid;
void* teb;
void* entry;
int reply_fd;
Index: scheduler/client.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/client.c,v
retrieving revision 1.2
diff -u -r1.2 client.c
--- /tmp/T07na42l Fri Jul 26 09:17:40 2002
+++ client.c Tue Jul 23 15:51:27 2002
@@ -686,7 +686,11 @@
SERVER_START_REQ( init_thread )
{
- req->unix_pid = getpid();
+#ifdef HAVE__LWP_CREATE
+ req->unix_tid = _lwp_self();
+#else
+ req->unix_tid = getpid();
+#endif
req->teb = teb;
req->entry = teb->entry_point;
req->reply_fd = reply_pipe[1];
Index: scheduler/process.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/process.c,v
retrieving revision 1.2
diff -u -r1.2 process.c
--- /tmp/T0Dwaq3l Fri Jul 26 09:17:41 2002
+++ process.c Wed Jul 24 10:29:04 2002
@@ -241,6 +241,25 @@
}
+static void wine_get_parent_id( int *ppid, int *ptid )
+{
+#ifdef HAVE__LWP_CREATE
+ char *env_ppid;
+
+ env_ppid = getenv( "WINE_PARENT_LWPID" );
+ if ((env_ppid == NULL) || (sscanf( env_ppid, "%d:%d", ppid, ptid ) != 2) ||
+ (*ppid != getppid())) {
+ /* Maybe the parent is not a Wine process */
+ *ppid = getppid();
+ *ptid = 0;
+ }
+#else
+ *ppid = 0;
+ *ptid = getppid();
+#endif
+}
+
+
/***********************************************************************
* get_basename
*/
@@ -380,7 +399,8 @@
SERVER_START_REQ( init_process )
{
req->ldt_copy = &wine_ldt_copy;
- req->ppid = getppid();
+ req->unix_pid = getpid();
+ wine_get_parent_id( &req->unix_ppid, &req->unix_ptid );
if ((ret = !wine_server_call_err( req )))
{
main_exe_file = reply->exe_file;
@@ -541,7 +561,7 @@
*/
void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file )
{
- char error[100];
+ char error[1024];
DWORD stack_size = 0;
/* Initialize everything */
@@ -844,6 +864,10 @@
int pid, err;
char *extra_env = NULL;
+#ifdef HAVE__LWP_CREATE
+ int ptid = _lwp_self();
+#endif
+
if (!env)
{
env = GetEnvironmentStringsA();
@@ -862,6 +886,13 @@
char **envp = build_envp( env, extra_env );
close( fd[0] );
+#ifdef HAVE__LWP_CREATE
+ {
+ char *env_ppid = malloc( 40 );
+ sprintf( env_ppid, "WINE_PARENT_LWPID=%d:%d", getppid(), ptid );
+ putenv( env_ppid );
+ }
+#endif
/* Reset signals that we previously set to SIG_IGN */
signal( SIGPIPE, SIG_DFL );
signal( SIGCHLD, SIG_DFL );
Index: server/console.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/console.c,v
retrieving revision 1.2
diff -u -r1.2 console.c
--- /tmp/T0pNaa4l Fri Jul 26 09:17:42 2002
+++ console.c Tue Jul 23 07:47:51 2002
@@ -404,7 +404,7 @@
while (thread)
{
struct thread *next = thread->proc_next;
- kill( thread->unix_pid, csi->signal );
+ signal_thread( thread, csi->signal );
thread = next;
}
}
Index: server/context_i386.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/context_i386.c,v
retrieving revision 1.1
diff -u -r1.1 context_i386.c
--- /tmp/T0qSay4l Fri Jul 26 09:17:42 2002
+++ context_i386.c Fri Jul 26 09:13:25 2002
@@ -24,6 +24,7 @@
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
@@ -37,6 +38,7 @@
#include "winbase.h"
#include "thread.h"
+#include "process.h"
#include "request.h"
#ifndef PTRACE_PEEKUSER
@@ -68,6 +70,8 @@
#define PTRACE_SETFPREGS PT_SETFPREGS
#endif
+#ifndef HAVE__LWP_CREATE
+
#ifdef linux
#ifdef HAVE_SYS_USER_H
# include <sys/user.h>
@@ -104,7 +108,7 @@
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int pid = thread->unix_pid;
+ int pid = thread->unix_tid;
if (flags & CONTEXT_FULL)
{
struct kernel_user_regs_struct regs;
@@ -160,7 +164,7 @@
/* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int pid = thread->unix_pid;
+ int pid = thread->unix_tid;
if (flags & CONTEXT_FULL)
{
struct kernel_user_regs_struct regs;
@@ -215,15 +219,16 @@
file_set_error();
}
-#elif defined(__sun) || defined(__sun__)
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+#include <machine/reg.h>
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int pid = thread->unix_pid;
+ int pid = thread->unix_tid;
if (flags & CONTEXT_FULL)
{
- struct regs regs;
+ struct reg regs;
if (ptrace( PTRACE_GETREGS, pid, 0, (int) ®s ) == -1) goto error;
if (flags & CONTEXT_INTEGER)
{
@@ -241,7 +246,7 @@
context->Eip = regs.r_eip;
context->SegCs = regs.r_cs & 0xffff;
context->SegSs = regs.r_ss & 0xffff;
- context->EFlags = regs.r_efl;
+ context->EFlags = regs.r_eflags;
}
if (flags & CONTEXT_SEGMENTS)
{
@@ -253,7 +258,7 @@
}
if (flags & CONTEXT_DEBUG_REGISTERS)
{
- /* FIXME: How is this done on Solaris? */
+ /* FIXME: How is this done on FreeBSD? */
}
if (flags & CONTEXT_FLOATING_POINT)
{
@@ -271,10 +276,10 @@
/* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int pid = thread->unix_pid;
+ int pid = thread->unix_tid;
if (flags & CONTEXT_FULL)
{
- struct regs regs;
+ struct reg regs;
if (((flags | CONTEXT_i386) & CONTEXT_FULL) != CONTEXT_FULL)
{
/* need to preserve some registers */
@@ -296,7 +301,7 @@
regs.r_eip = context->Eip;
regs.r_cs = context->SegCs;
regs.r_ss = context->SegSs;
- regs.r_efl = context->EFlags;
+ regs.r_eflags = context->EFlags;
}
if (flags & CONTEXT_SEGMENTS)
{
@@ -309,7 +314,7 @@
}
if (flags & CONTEXT_DEBUG_REGISTERS)
{
- /* FIXME: How is this done on Solaris? */
+ /* FIXME: How is this done on FreeBSD? */
}
if (flags & CONTEXT_FLOATING_POINT)
{
@@ -322,53 +327,70 @@
file_set_error();
}
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-#include <machine/reg.h>
+#else /* linux || __FreeBSD__ */
+#error You must implement get/set_thread_context for your platform
+#endif /* linux || __FreeBSD__ */
+
+#else /* HAVE__LWP_CREATE */
+
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
+
+static BOOL get_thread_status( struct thread *thread, struct lwpstatus *status)
+{
+ char sStatusFile[30];
+ int fd;
+
+ sprintf( sStatusFile, "/proc/%d/lwp/%d/lwpstatus",
+ thread->process->unix_pid, thread->unix_tid );
+ if (-1 == (fd = open( sStatusFile, O_RDONLY ))) return FALSE;
+ if (sizeof(status) != read(fd, &status, sizeof(status))) return FALSE;
+ close(fd);
+
+ return TRUE;
+}
+
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int pid = thread->unix_pid;
- if (flags & CONTEXT_FULL)
+ struct lwpstatus status;
+
+ if (!get_thread_status(thread, &status)) goto error;
+
+ if (flags & CONTEXT_INTEGER)
{
- struct reg regs;
- if (ptrace( PTRACE_GETREGS, pid, 0, (int) ®s ) == -1) goto error;
- if (flags & CONTEXT_INTEGER)
- {
- context->Eax = regs.r_eax;
- context->Ebx = regs.r_ebx;
- context->Ecx = regs.r_ecx;
- context->Edx = regs.r_edx;
- context->Esi = regs.r_esi;
- context->Edi = regs.r_edi;
- }
- if (flags & CONTEXT_CONTROL)
- {
- context->Ebp = regs.r_ebp;
- context->Esp = regs.r_esp;
- context->Eip = regs.r_eip;
- context->SegCs = regs.r_cs & 0xffff;
- context->SegSs = regs.r_ss & 0xffff;
- context->EFlags = regs.r_eflags;
- }
- if (flags & CONTEXT_SEGMENTS)
- {
- context->SegDs = regs.r_ds & 0xffff;
- context->SegEs = regs.r_es & 0xffff;
- context->SegFs = regs.r_fs & 0xffff;
- context->SegGs = regs.r_gs & 0xffff;
- }
+ context->Eax = status.pr_reg[EAX];
+ context->Ebx = status.pr_reg[EBX];
+ context->Ecx = status.pr_reg[ECX];
+ context->Edx = status.pr_reg[EDX];
+ context->Esi = status.pr_reg[ESI];
+ context->Edi = status.pr_reg[EDI];
+ }
+ if (flags & CONTEXT_CONTROL)
+ {
+ context->Ebp = status.pr_reg[EBP];
+ context->Esp = status.pr_reg[ESP];
+ context->Eip = status.pr_reg[EIP];
+ context->SegCs = status.pr_reg[CS] & 0xffff;
+ context->SegSs = status.pr_reg[SS] & 0xffff;
+ context->EFlags = status.pr_reg[EFL];
+ }
+ if (flags & CONTEXT_SEGMENTS)
+ {
+ context->SegDs = status.pr_reg[DS] & 0xffff;
+ context->SegEs = status.pr_reg[ES] & 0xffff;
+ context->SegFs = status.pr_reg[FS] & 0xffff;
+ context->SegGs = status.pr_reg[GS] & 0xffff;
}
if (flags & CONTEXT_DEBUG_REGISTERS)
{
- /* FIXME: How is this done on FreeBSD? */
+ /* FIXME: How is this done with procfs? */
}
if (flags & CONTEXT_FLOATING_POINT)
{
- /* we can use context->FloatSave directly as it is using the */
- /* correct structure (the same as fsave/frstor) */
- if (ptrace( PTRACE_GETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
- context->FloatSave.Cr0NpxState = 0; /* FIXME */
+ /* FIXME status.pr_fpreg should be used here,
+ * but it's format is different from context->FloatSave */
}
return;
error:
@@ -379,60 +401,55 @@
/* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int pid = thread->unix_pid;
+ struct lwpstatus status;
+
+ if (!get_thread_status(thread, &status)) goto error;
+
if (flags & CONTEXT_FULL)
{
- struct reg regs;
- if (((flags | CONTEXT_i386) & CONTEXT_FULL) != CONTEXT_FULL)
- {
- /* need to preserve some registers */
- if (ptrace( PTRACE_GETREGS, pid, 0, (int) ®s ) == -1) goto error;
- }
- if (flags & CONTEXT_INTEGER)
- {
- regs.r_eax = context->Eax;
- regs.r_ebx = context->Ebx;
- regs.r_ecx = context->Ecx;
- regs.r_edx = context->Edx;
- regs.r_esi = context->Esi;
- regs.r_edi = context->Edi;
- }
- if (flags & CONTEXT_CONTROL)
- {
- regs.r_ebp = context->Ebp;
- regs.r_esp = context->Esp;
- regs.r_eip = context->Eip;
- regs.r_cs = context->SegCs;
- regs.r_ss = context->SegSs;
- regs.r_eflags = context->EFlags;
- }
- if (flags & CONTEXT_SEGMENTS)
- {
- regs.r_ds = context->SegDs;
- regs.r_es = context->SegEs;
- regs.r_fs = context->SegFs;
- regs.r_gs = context->SegGs;
- }
- if (ptrace( PTRACE_SETREGS, pid, 0, (int) ®s ) == -1) goto error;
+ if (flags & CONTEXT_INTEGER)
+ {
+ status.pr_reg[EAX] = context->Eax;
+ status.pr_reg[EBX] = context->Ebx;
+ status.pr_reg[ECX] = context->Ecx;
+ status.pr_reg[EDX] = context->Edx;
+ status.pr_reg[ESI] = context->Esi;
+ status.pr_reg[EDI] = context->Edi;
+ }
+ if (flags & CONTEXT_CONTROL)
+ {
+ status.pr_reg[EBP] = context->Ebp;
+ status.pr_reg[ESP] = context->Esp;
+ status.pr_reg[EIP] = context->Eip;
+ status.pr_reg[CS] = context->SegCs;
+ status.pr_reg[SS] = context->SegSs;
+ status.pr_reg[EFL] = context->EFlags;
+ }
+ if (flags & CONTEXT_SEGMENTS)
+ {
+ status.pr_reg[DS] = context->SegDs;
+ status.pr_reg[ES] = context->SegEs;
+ status.pr_reg[FS] = context->SegFs;
+ status.pr_reg[GS] = context->SegGs;
+ }
+ lwpctl( thread, PCSREG, &status.pr_reg, sizeof(status.pr_reg) );
}
if (flags & CONTEXT_DEBUG_REGISTERS)
{
- /* FIXME: How is this done on FreeBSD? */
+ /* FIXME: How is this done with procfs? */
}
if (flags & CONTEXT_FLOATING_POINT)
{
- /* we can use context->FloatSave directly as it is using the */
- /* correct structure (the same as fsave/frstor) */
- if (ptrace( PTRACE_SETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
+ /* FIXME status.pr_fpreg should be used here,
+ * but it's format is different from context->FloatSave */
+ lwpctl( thread, PCSFPREG, &status.pr_fpreg, sizeof(status.pr_reg) );
}
return;
error:
file_set_error();
}
-#else /* linux || __sun__ || __FreeBSD__ */
-#error You must implement get/set_thread_context for your platform
-#endif /* linux || __sun__ || __FreeBSD__ */
+#endif /* HAVE__LWP_CREATE */
/* copy a context structure according to the flags */
Index: server/context_sparc.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/context_sparc.c,v
retrieving revision 1.1
diff -u -r1.1 context_sparc.c
--- /tmp/T0mWaW4l Fri Jul 26 09:17:42 2002
+++ context_sparc.c Wed Jul 24 09:45:08 2002
@@ -24,6 +24,7 @@
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <sys/types.h>
#ifdef HAVE_SYS_REG_H
# include <sys/reg.h>
@@ -36,15 +37,164 @@
#include "winbase.h"
#include "thread.h"
+#include "process.h"
#include "request.h"
-#if defined(__sun) || defined(__sun__)
+#ifdef HAVE__LWP_CREATE
+
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
+
+static BOOL get_thread_status( struct thread *thread, struct lwpstatus *status)
+{
+ char sStatusFile[30];
+ int fd;
+
+ sprintf( sStatusFile, "/proc/%d/lwp/%d/lwpstatus",
+ thread->process->unix_pid, thread->unix_tid );
+ if (-1 == (fd = open( sStatusFile, O_RDONLY ))) return FALSE;
+ if (sizeof(status) != read(fd, &status, sizeof(status))) return FALSE;
+ close(fd);
+
+ return TRUE;
+}
+
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int pid = thread->unix_pid;
+ struct lwpstatus status;
+
+ if (!get_thread_status( thread, &status )) goto error;
+ if (flags & CONTEXT_INTEGER)
+ {
+ context->g0 = status.pr_reg[R_G0];
+ context->g1 = status.pr_reg[R_G1];
+ context->g2 = status.pr_reg[R_G2];
+ context->g3 = status.pr_reg[R_G3];
+ context->g4 = status.pr_reg[R_G4];
+ context->g5 = status.pr_reg[R_G5];
+ context->g6 = status.pr_reg[R_G6];
+ context->g7 = status.pr_reg[R_G7];
+
+ context->o0 = status.pr_reg[R_O0];
+ context->o1 = status.pr_reg[R_O1];
+ context->o2 = status.pr_reg[R_O2];
+ context->o3 = status.pr_reg[R_O3];
+ context->o4 = status.pr_reg[R_O4];
+ context->o5 = status.pr_reg[R_O5];
+ context->o6 = status.pr_reg[R_O6];
+ context->o7 = status.pr_reg[R_O7];
+
+ context->l0 = status.pr_reg[R_L0];
+ context->l1 = status.pr_reg[R_L1];
+ context->l2 = status.pr_reg[R_L2];
+ context->l3 = status.pr_reg[R_L3];
+ context->l4 = status.pr_reg[R_L4];
+ context->l5 = status.pr_reg[R_L5];
+ context->l6 = status.pr_reg[R_L6];
+ context->l7 = status.pr_reg[R_L7];
+
+ context->i0 = status.pr_reg[R_I0];
+ context->i1 = status.pr_reg[R_I1];
+ context->i2 = status.pr_reg[R_I2];
+ context->i3 = status.pr_reg[R_I3];
+ context->i4 = status.pr_reg[R_I4];
+ context->i5 = status.pr_reg[R_I5];
+ context->i6 = status.pr_reg[R_I6];
+ context->i7 = status.pr_reg[R_I7];
+ }
+ if (flags & CONTEXT_CONTROL)
+ {
+ context->psr = status.pr_reg[R_PSR];
+ context->pc = status.pr_reg[R_PC];
+ context->npc = status.pr_reg[R_nPC];
+ context->y = status.pr_reg[R_Y];
+ context->wim = status.pr_reg[R_WIM];
+ context->tbr = status.pr_reg[R_TBR];
+ }
+ if (flags & CONTEXT_FLOATING_POINT)
+ {
+ /* FIXME, contained in status.pr_fpreg, but not defined in context */
+ }
+ return;
+ error:
+ file_set_error();
+}
+
+
+/* set a thread context */
+static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
+{
+ struct lwpstatus status;
+
+ if (!get_thread_status(thread, &status)) goto error;
+ if (flags & CONTEXT_INTEGER)
+ {
+ status.pr_reg[R_G0] = context->g0;
+ status.pr_reg[R_G1] = context->g1;
+ status.pr_reg[R_G2] = context->g2;
+ status.pr_reg[R_G3] = context->g3;
+ status.pr_reg[R_G4] = context->g4;
+ status.pr_reg[R_G5] = context->g5;
+ status.pr_reg[R_G6] = context->g6;
+ status.pr_reg[R_G7] = context->g7;
+
+ status.pr_reg[R_O0] = context->o0;
+ status.pr_reg[R_O1] = context->o1;
+ status.pr_reg[R_O2] = context->o2;
+ status.pr_reg[R_O3] = context->o3;
+ status.pr_reg[R_O4] = context->o4;
+ status.pr_reg[R_O5] = context->o5;
+ status.pr_reg[R_O6] = context->o6;
+ status.pr_reg[R_O7] = context->o7;
+
+ status.pr_reg[R_L0] = context->l0;
+ status.pr_reg[R_L1] = context->l1;
+ status.pr_reg[R_L2] = context->l2;
+ status.pr_reg[R_L3] = context->l3;
+ status.pr_reg[R_L4] = context->l4;
+ status.pr_reg[R_L5] = context->l5;
+ status.pr_reg[R_L6] = context->l6;
+ status.pr_reg[R_L7] = context->l7;
+
+ status.pr_reg[R_I0] = context->i0;
+ status.pr_reg[R_I1] = context->i1;
+ status.pr_reg[R_I2] = context->i2;
+ status.pr_reg[R_I3] = context->i3;
+ status.pr_reg[R_I4] = context->i4;
+ status.pr_reg[R_I5] = context->i5;
+ status.pr_reg[R_I6] = context->i6;
+ status.pr_reg[R_I7] = context->i7;
+ }
+ if (flags & CONTEXT_CONTROL)
+ {
+ status.pr_reg[R_PSR] = context->psr;
+ status.pr_reg[R_PC] = context->pc;
+ status.pr_reg[R_nPC] = context->npc;
+ status.pr_reg[R_Y] = context->y;
+ status.pr_reg[R_WIM] = context->wim;
+ status.pr_reg[R_TBR] = context->tbr;
+ }
+ lwpctl( thread, PCSREG, &status.pr_reg, sizeof(status.pr_reg) );
+ if (flags & CONTEXT_FLOATING_POINT)
+ {
+ /* FIXME, contained in status.pr_fpreg, but not defined in context */
+ lwpctl( thread, PCSFPREG, &status.pr_fpreg, sizeof(status.pr_reg) );
+ }
+ return;
+ error:
+ file_set_error();
+}
+
+
+#else /* !HAVE__LWP_CREATE */
+
+
+static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+{
+ int pid = thread->unix_tid;
if (flags & CONTEXT_FULL)
{
struct regs regs;
@@ -97,9 +247,7 @@
/* FIXME */
}
-#else /* __sun__ */
-#error You must implement get/set_thread_context for your platform
-#endif /* __sun__ */
+#endif
/* copy a context structure according to the flags */
Index: server/debugger.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/debugger.c,v
retrieving revision 1.1
diff -u -r1.1 debugger.c
--- /tmp/T0F2ai5l Fri Jul 26 09:17:43 2002
+++ debugger.c Wed Jul 24 09:39:25 2002
@@ -730,9 +730,9 @@
struct thread *thread;
for (thread = process->thread_list; thread; thread = thread->proc_next)
{
- if (thread->unix_pid)
+ if (thread->unix_tid)
{
- kill( thread->unix_pid, SIGTRAP );
+ signal_thread( thread, SIGTRAP );
break;
}
}
Index: server/process.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/process.c,v
retrieving revision 1.2
diff -u -r1.2 process.c
--- /tmp/T01.aG5l Fri Jul 26 09:17:43 2002
+++ process.c Wed Jul 24 10:28:11 2002
@@ -251,10 +251,10 @@
}
/* initialize the current process and fill in the request */
-static struct startup_info *init_process( int ppid, struct init_process_reply *reply )
+static struct startup_info *init_process( int unix_pid, int unix_ppid, int unix_ptid, struct init_process_reply *reply )
{
struct process *process = current->process;
- struct thread *parent_thread = get_thread_from_pid( ppid );
+ struct thread *parent_thread = get_thread_from_pid( unix_ppid, unix_ptid );
struct process *parent = NULL;
struct startup_info *info = NULL;
@@ -269,6 +269,7 @@
}
process->parent = (struct process *)grab_object( parent );
}
+ process->unix_pid = unix_pid;
/* set the process flags */
process->create_flags = info ? info->create_flags : 0;
@@ -568,7 +569,7 @@
while (thread)
{
struct thread *next = thread->proc_next;
- if (!thread->suspend) continue_thread( thread );
+ if (!thread->suspend) continue_thread( thread, SIGSTOP );
thread = next;
}
}
@@ -869,7 +870,7 @@
/* initialize a new process */
DECL_HANDLER(init_process)
{
- if (!current->unix_pid)
+ if (!current->unix_tid)
{
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
return;
@@ -881,7 +882,7 @@
}
reply->info_size = 0;
current->process->ldt_copy = req->ldt_copy;
- current->process->startup_info = init_process( req->ppid, reply );
+ current->process->startup_info = init_process( req->unix_pid, req->unix_ppid, req->unix_ptid, reply );
}
/* signal the end of the process initialization */
Index: server/process.h
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/process.h,v
retrieving revision 1.1
diff -u -r1.1 process.h
--- /tmp/T06ca45l Fri Jul 26 09:17:44 2002
+++ process.h Tue Jul 23 07:45:18 2002
@@ -73,6 +73,7 @@
void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags in client addr space */
void *group_id; /* group ID of the process */
+ int unix_pid; /* Unix PID of entire process (Solaris) */
};
struct process_snapshot
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/T0aiaq6l Fri Jul 26 09:17:44 2002
+++ ptrace.c Wed Jul 24 15:53:10 2002
@@ -66,6 +66,17 @@
inline static int ptrace(int req, ...) { errno = EPERM; return -1; /*FAIL*/ }
#endif /* HAVE_SYS_PTRACE_H */
+#ifdef HAVE__LWP_CREATE
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
+
+#define PID(thread) thread->process->unix_pid
+#define PIDTID(pid) pid, 1
+#else
+#define PID(thread) thread->unix_tid
+#define PIDTID(pid) 0, pid
+#endif
+
static const int use_ptrace = 1; /* set to 0 to disable ptrace */
/* handle a status returned by wait4 */
@@ -82,10 +93,7 @@
if (thread && (thread->process->suspend + thread->suspend)) break;
/* fall through */
default: /* ignore other signals for now */
- if (thread && get_thread_single_step( thread ))
- ptrace( PTRACE_SINGLESTEP, pid, (caddr_t)1, sig );
- else
- ptrace( PTRACE_CONT, pid, (caddr_t)1, sig );
+ continue_thread(thread, sig);
break;
}
return sig;
@@ -93,7 +101,7 @@
if (thread && (WIFSIGNALED(status) || WIFEXITED(status)))
{
thread->attached = 0;
- thread->unix_pid = 0;
+ thread->unix_tid = 0;
if (debug_level)
{
if (WIFSIGNALED(status))
@@ -115,7 +123,8 @@
for (;;)
{
if (!(pid = wait4( -1, &status, WUNTRACED | WNOHANG, NULL ))) break;
- if (pid != -1) handle_child_status( get_thread_from_pid(pid), pid, status );
+ if (pid != -1) handle_child_status( get_thread_from_pid( PIDTID(pid) ),
+ pid, status );
else break;
}
}
@@ -127,7 +136,7 @@
do
{
- if ((res = wait4( thread->unix_pid, &status, WUNTRACED, NULL )) == -1)
+ if ((res = wait4( PID(thread), &status, WUNTRACED, NULL )) == -1)
{
perror( "wait4" );
return;
@@ -141,9 +150,9 @@
{
/* this may fail if the client is already being debugged */
if (!use_ptrace) return 0;
- if (ptrace( PTRACE_ATTACH, thread->unix_pid, 0, 0 ) == -1)
+ if (ptrace( PTRACE_ATTACH, PID(thread), 0, 0 ) == -1)
{
- if (errno == ESRCH) thread->unix_pid = 0; /* process got killed */
+ if (errno == ESRCH) thread->unix_tid = 0; /* process got killed */
return 0;
}
if (debug_level) fprintf( stderr, "%08x: *attached*\n", (unsigned int)thread );
@@ -155,21 +164,24 @@
/* detach from a Unix thread and kill it */
void detach_thread( struct thread *thread, int sig )
{
- if (!thread->unix_pid) return;
+ if (!thread->unix_tid) return;
if (thread->attached)
{
/* make sure it is stopped */
suspend_thread( thread, 0 );
- if (sig) kill( thread->unix_pid, sig );
+ if (sig) signal_thread( thread, sig );
if (debug_level) fprintf( stderr, "%08x: *detached*\n", (unsigned int)thread );
- ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig );
+ ptrace( PTRACE_DETACH, PID(thread), (caddr_t)1, sig );
thread->suspend = 0; /* detach makes it continue */
thread->attached = 0;
}
else
{
- if (sig) kill( thread->unix_pid, sig );
- if (thread->suspend + thread->process->suspend) continue_thread( thread );
+#ifndef HAVE__LWP_CREATE
+ if (sig) signal_thread( thread, sig );
+#endif
+ if (thread->suspend + thread->process->suspend)
+ continue_thread( thread, SIGSTOP );
}
}
@@ -177,23 +189,43 @@
void stop_thread( struct thread *thread )
{
/* can't stop a thread while initialisation is in progress */
- if (!thread->unix_pid || !is_process_init_done(thread->process)) return;
+ if (!thread->unix_tid || !is_process_init_done(thread->process)) return;
+#ifdef HAVE__LWP_CREATE
+ lwpctl( thread, PCSTOP, 0, 0 );
+#else
/* first try to attach to it */
if (!thread->attached)
if (attach_thread( thread )) return; /* this will have stopped it */
/* attached already, or attach failed -> send a signal */
- if (!thread->unix_pid) return;
- kill( thread->unix_pid, SIGSTOP );
+ if (!thread->unix_tid) return;
+ signal_thread( thread, SIGSTOP );
if (thread->attached) wait4_thread( thread, SIGSTOP );
+#endif
}
/* make a thread continue (at the Unix level) */
-void continue_thread( struct thread *thread )
+void continue_thread( struct thread *thread, int sig )
{
- if (!thread->unix_pid) return;
- 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 );
+ if (!thread || !thread->unix_tid) return;
+#ifdef HAVE__LWP_CREATE
+ {
+ int temp;
+ if (get_thread_single_step( thread ))
+ temp = PRSTEP;
+ else
+ temp = 0;
+ lwpctl( thread, PCRUN, &temp, sizeof(int) );
+ }
+#else
+ if (!thread->attached) signal_thread( thread, SIGCONT );
+ else
+ {
+ if (get_thread_single_step( thread ))
+ ptrace( PTRACE_SINGLESTEP, pid, (caddr_t)1, sig );
+ else
+ ptrace( PTRACE_CONT, pid, (caddr_t)1, sig );
+ }
+#endif
}
/* suspend a thread to allow using ptrace on it */
@@ -206,7 +238,7 @@
return 1;
}
/* can't stop a thread while initialisation is in progress */
- if (!thread->unix_pid || !is_process_init_done(thread->process)) goto error;
+ if (!thread->unix_tid || !is_process_init_done(thread->process)) goto error;
thread->suspend++;
if (attach_thread( thread )) return 1;
thread->suspend--;
@@ -218,7 +250,7 @@
/* read an int from a thread address space */
int read_thread_int( struct thread *thread, const int *addr, int *data )
{
- *data = ptrace( PTRACE_PEEKDATA, thread->unix_pid, (caddr_t)addr, 0 );
+ *data = ptrace( PTRACE_PEEKDATA, PID(thread), (caddr_t)addr, 0 );
if ( *data == -1 && errno)
{
file_set_error();
@@ -236,7 +268,7 @@
if (read_thread_int( thread, addr, &res ) == -1) return -1;
data = (data & mask) | (res & ~mask);
}
- if ((res = ptrace( PTRACE_POKEDATA, thread->unix_pid, (caddr_t)addr, data )) == -1)
+ if ((res = ptrace( PTRACE_POKEDATA, PID(thread), (caddr_t)addr, data )) == -1)
file_set_error();
return res;
}
Index: server/thread.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/thread.c,v
retrieving revision 1.2
diff -u -r1.2 thread.c
--- /tmp/T0_paO6l Fri Jul 26 09:17:44 2002
+++ thread.c Wed Jul 24 09:34:11 2002
@@ -41,6 +41,8 @@
#include "request.h"
#include "user.h"
+#undef _FILE_OFFSET_BITS
+#include <procfs.h>
/* thread queues */
@@ -103,7 +105,7 @@
{
int i;
- thread->unix_pid = 0; /* not known yet */
+ thread->unix_tid = 0; /* not known yet */
thread->context = NULL;
thread->teb = NULL;
thread->mutex = NULL;
@@ -242,8 +244,9 @@
struct thread *thread = (struct thread *)obj;
assert( obj->ops == &thread_ops );
- fprintf( stderr, "Thread pid=%d teb=%p state=%d\n",
- thread->unix_pid, thread->teb, thread->state );
+ fprintf( stderr, "Thread tid=%d.%d teb=%p state=%d\n",
+ thread->process->unix_pid, thread->unix_tid,
+ thread->teb, thread->state );
}
static int thread_signaled( struct object *obj, struct thread *thread )
@@ -270,10 +273,13 @@
}
/* find a thread from a Unix pid */
-struct thread *get_thread_from_pid( int pid )
+struct thread *get_thread_from_pid( int unix_pid, int unix_tid )
{
struct thread *t = first_thread;
- while (t && (t->unix_pid != pid)) t = t->next;
+ while (t &&
+ (t->unix_tid != unix_tid) &&
+ (t->process->unix_pid != unix_pid))
+ t = t->next;
return t;
}
@@ -308,7 +314,8 @@
int old_count = thread->suspend;
if (thread->suspend > 0)
{
- if (!(--thread->suspend + thread->process->suspend)) continue_thread( thread );
+ if (!(--thread->suspend + thread->process->suspend))
+ continue_thread( thread, SIGSTOP );
}
return old_count;
}
@@ -736,6 +743,42 @@
release_object( thread );
}
+
+#ifdef HAVE__LWP_CREATE
+void lwpctl( struct thread *thread, int cmd, void *arg, int size )
+{
+ char sCtlFile[30];
+ int fd;
+ int *msg;
+
+ sprintf( sCtlFile, "/proc/%d/lwp/%d/lwpctl",
+ thread->process->unix_pid, thread->unix_tid );
+ fd = open( sCtlFile, O_WRONLY );
+ if( fd >= 0 )
+ {
+ msg = (int*)malloc(size + sizeof(int));
+ msg[0] = cmd;
+ memcpy(msg + 1, arg, size);
+ write( fd, msg, size + sizeof(int) );
+ close( fd );
+ }
+}
+#endif
+
+
+/* Send signal to thread.
+ * On linux, this is equivilant to kill(thread->unix_tid, signal).
+ * On Solaris, the above can't be done, so this function is needed. */
+void signal_thread( struct thread *thread, int signal)
+{
+#ifdef HAVE__LWP_CREATE
+ lwpctl( thread, PCKILL, &signal, sizeof(int) );
+#else
+ kill( thread->unix_tid, signal );
+#endif
+}
+
+
/* take a snapshot of currently running threads */
struct thread_snapshot *thread_snap( int *count )
{
@@ -805,7 +848,7 @@
int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
int wait_fd = thread_get_inflight_fd( current, req->wait_fd );
- if (current->unix_pid)
+ if (current->unix_tid)
{
fatal_protocol_error( current, "init_thread: already running\n" );
goto error;
@@ -821,7 +864,7 @@
goto error;
}
- current->unix_pid = req->unix_pid;
+ current->unix_tid = req->unix_tid;
current->teb = req->teb;
current->reply_fd = reply_fd;
current->wait_fd = wait_fd;
Index: server/thread.h
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/thread.h,v
retrieving revision 1.1
diff -u -r1.1 thread.h
--- /tmp/T0puaa7l Fri Jul 26 09:17:45 2002
+++ thread.h Wed Jul 24 09:32:51 2002
@@ -84,7 +84,7 @@
enum run_state state; /* running state */
int attached; /* is thread attached with ptrace? */
int exit_code; /* thread exit code */
- int unix_pid; /* Unix pid of client */
+ int unix_tid; /* Unix tid of client */
CONTEXT *context; /* current context if in an exception handler */
void *teb; /* TEB address (in client address space) */
int priority; /* priority level */
@@ -106,12 +106,16 @@
extern struct thread *create_thread( int fd, struct process *process );
extern struct thread *get_thread_from_id( void *id );
extern struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access );
-extern struct thread *get_thread_from_pid( int pid );
+extern struct thread *get_thread_from_pid( int unix_pid, int unix_tid );
extern int suspend_thread( struct thread *thread, int check_limit );
extern int resume_thread( struct thread *thread );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern void kill_thread( struct thread *thread, int violent_death );
+#ifdef HAVE__LWP_CREATE
+extern void lwpctl( struct thread *thread, int cmd, void *arg, int size );
+#endif
+extern void signal_thread( struct thread *thread, int signal);
extern void wake_up( struct object *obj, int max );
extern int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
enum apc_type type, int system, int nb_args, ... );
@@ -125,7 +129,7 @@
extern void sigchld_handler();
extern void wait4_thread( struct thread *thread, int signal );
extern void stop_thread( struct thread *thread );
-extern void continue_thread( struct thread *thread );
+extern void continue_thread( struct thread *thread, int sig );
extern void detach_thread( struct thread *thread, int sig );
extern int suspend_for_ptrace( struct thread *thread );
extern int read_thread_int( struct thread *thread, const int *addr, int *data );
Index: server/trace.c
===================================================================
RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/trace.c,v
retrieving revision 1.1
diff -u -r1.1 trace.c
--- /tmp/T0wAay7l Fri Jul 26 09:17:45 2002
+++ trace.c Wed Jul 24 09:38:08 2002
@@ -400,7 +400,8 @@
static void dump_init_process_request( const struct init_process_request *req )
{
fprintf( stderr, " ldt_copy=%p,", req->ldt_copy );
- fprintf( stderr, " ppid=%d", req->ppid );
+ fprintf( stderr, " unix_ppid=%d", req->unix_ppid );
+ fprintf( stderr, " unix_ptid=%d", req->unix_ptid );
}
static void dump_init_process_reply( const struct init_process_reply *req )
@@ -443,7 +444,7 @@
static void dump_init_thread_request( const struct init_thread_request *req )
{
- fprintf( stderr, " unix_pid=%d,", req->unix_pid );
+ fprintf( stderr, " unix_tid=%d,", req->unix_tid );
fprintf( stderr, " teb=%p,", req->teb );
fprintf( stderr, " entry=%p,", req->entry );
fprintf( stderr, " reply_fd=%d,", req->reply_fd );
More information about the wine-patches
mailing list