Subject: winex/server cdrom_eject.c,1.9,1.10 console.c,1.16,1.17 context_i386.c,1.7,1.8 context_ppc.c,1.1,1.2 context_sparc.c,1.3,1.4 debugger.c,1.13,1.14 fd_server.c,1.15,1.16 macosx.c,NONE,1.1 main.c,1.17,1.18 Makefile.in,1.19,1.20 process.c,1.39,1.40 process.h,1.15,1.16 protocol.def,1.39,1.40 ptrace.c,1.21,1.22 request.c,1.25,1.26 request.h,1.26,1.27 server_memory.h,1.12,1.13 shm.c,1.17,1.18 thread.c,1.53,1.54 thread.h,1.26,1.27 trace.c,1.40,1.41Update of /var/lib/cvsd/cvsroot/winex/server
In directory agravaine:/tmp/cvs-serv31107/server
Modified Files:
cdrom_eject.c console.c context_i386.c context_ppc.c
context_sparc.c debugger.c fd_server.c main.c Makefile.in
process.c process.h protocol.def ptrace.c request.c request.h
server_memory.h shm.c thread.c thread.h trace.c
Added Files:
macosx.c
Log Message:
- disambiguate in-process tids (which all platforms have) with
cross-process tids (which only some platforms have)
- store in-process tid in the TEB, and use that to fix thread cleanup on
MacOS X
- modify shm server to handle platforms which don't have cross-process tids
- rename server unix_tid to unix_tid_or_pid for clarity
- implement MacOSX functionality on top of Mach to replace ptrace functionality on Linux:
- suspend/resume thread
- read/write process memory
- get/set thread context
Index: cdrom_eject.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/cdrom_eject.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cdrom_eject.c 27 Mar 2007 20:25:26 -0000 1.9
+++ cdrom_eject.c 30 Mar 2007 15:55:02 -0000 1.10
@@ -262,8 +262,9 @@
{
struct process_eject_notify *s = (struct process_eject_notify*)data;
/* Signal the processes to call us back to get an fd ejection list */
- set_client_cdrom_eject_drive(s->drive, s->mounting, process->thread_list->unix_tid);
- wine_tkill (process->thread_list->unix_tid, SIGUSR2);
+ set_client_cdrom_eject_drive(s->drive, s->mounting,
+ process->thread_list->unix_tid_or_pid);
+ wine_tkill_or_kill (process->thread_list->unix_tid_or_pid, SIGUSR2);
}
return 0;
@@ -426,9 +427,9 @@
SERVER_STATIC_VARIABLE(cdrom_eject, signal_cdrom_eject_request) = 1;
}
+#ifdef linux
static void open_cdrom_entry(struct cdrom_entry *cdrom)
{
-#ifdef linux
int event;
int fd;
@@ -447,8 +448,8 @@
close(fd);
-#endif /* linux */
}
+#endif /* linux */
static int count_eject_objs (struct object *obj, struct process *process, context_fd *entryfd, void *data)
{
@@ -603,7 +604,9 @@
char *devicepath;
size_t devicepathlen;
struct cdrom_entry *entry = NULL;
+#ifdef linux
struct timeval when;
+#endif
/* If the timeout task is already running, just return */
if (SERVER_STATIC_VARIABLE(cdrom_eject, cdrom_eject_timeout_user))
Index: console.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/console.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- console.c 27 Mar 2007 20:25:26 -0000 1.16
+++ console.c 30 Mar 2007 15:55:02 -0000 1.17
@@ -399,7 +399,7 @@
while (thread)
{
struct thread *next = thread->proc_next;
- wine_tkill( thread->unix_tid, csi->signal );
+ wine_tkill_or_kill( thread->unix_tid_or_pid, csi->signal );
thread = next;
}
}
Index: context_i386.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/context_i386.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- context_i386.c 28 Mar 2007 14:34:22 -0000 1.7
+++ context_i386.c 30 Mar 2007 15:55:03 -0000 1.8
@@ -23,6 +23,7 @@
#include "winbase.h"
#include "thread.h"
+#include "process.h"
#include "request.h"
#ifndef PTRACE_PEEKUSER
@@ -90,7 +91,7 @@
/* retrieve a thread context */
void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct kernel_user_regs_struct regs;
@@ -146,7 +147,7 @@
/* set a thread context */
void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct kernel_user_regs_struct regs;
@@ -206,7 +207,7 @@
/* retrieve a thread context */
void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct regs regs;
@@ -257,7 +258,7 @@
/* set a thread context */
void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct regs regs;
@@ -314,7 +315,7 @@
/* retrieve a thread context */
void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct reg regs;
@@ -365,7 +366,7 @@
/* set a thread context */
void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct reg regs;
@@ -419,37 +420,225 @@
#else /* linux || __sun__ || __FreeBSD__ */
#ifdef __APPLE__
/* retrieve a thread context */
-static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
- {
- int pid = thread->unix_tid;
- if (flags & CONTEXT_FULL)
- {
-/* EZUST - apparently not supported! FIXME - we need to use PTRACE_PEEKUSER...ugh */
-/* if (ptrace( PTRACE_GETREGS, pid, 0, (int) NULL ) == -1) goto error; */
- if (flags & CONTEXT_INTEGER)
- {
- /* FIXME: local and in registers */
- }
- if (flags & CONTEXT_CONTROL)
- {
+static void get_thread_context (struct thread *thread, unsigned int flags,
+ CONTEXT *context)
+{
+ if (flags & CONTEXT_FULL)
+ {
+ x86_thread_state32_t regs;
+ mach_msg_type_number_t sc = x86_THREAD_STATE32_COUNT;
- }
- }
- if (flags & CONTEXT_FLOATING_POINT)
- {
- /* FIXME */
- }
- return;
- error:
- file_set_error();
- }
+ if (thread_get_state (thread->thread_port, x86_THREAD_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ if (flags & CONTEXT_INTEGER)
+ {
+ context->Eax = regs.eax;
+ context->Ebx = regs.ebx;
+ context->Ecx = regs.ecx;
+ context->Edx = regs.edx;
+ context->Esi = regs.esi;
+ context->Edi = regs.edi;
+ }
+
+ if (flags & CONTEXT_CONTROL)
+ {
+ context->Ebp = regs.ebp;
+ context->Esp = regs.esp;
+ context->Eip = regs.eip;
+ context->SegCs = regs.cs;
+ context->SegSs = regs.ss;
+ context->EFlags = regs.eflags;
+ }
+
+ if (flags & CONTEXT_SEGMENTS)
+ {
+ context->SegDs = regs.ds;
+ context->SegEs = regs.es;
+ context->SegFs = regs.fs;
+ context->SegGs = regs.gs;
+ }
+ }
+
+ if (flags & CONTEXT_DEBUG_REGISTERS)
+ {
+ x86_debug_state32_t regs;
+ mach_msg_type_number_t sc = x86_DEBUG_STATE32_COUNT;
+
+ if (thread_get_state (thread->thread_port, x86_DEBUG_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ context->Dr0 = regs.dr0;
+ context->Dr1 = regs.dr1;
+ context->Dr2 = regs.dr2;
+ context->Dr3 = regs.dr3;
+ context->Dr6 = regs.dr6;
+ context->Dr7 = regs.dr7;
+ }
+
+ if (flags & CONTEXT_FLOATING_POINT)
+ {
+ x86_float_state32_t regs;
+ mach_msg_type_number_t sc = x86_FLOAT_STATE32_COUNT;
+ unsigned short sVal;
+
+ if (thread_get_state (thread->thread_port, x86_FLOAT_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ memcpy (&sVal, ®s.fpu_fcw, 2);
+ context->FloatSave.ControlWord = sVal;
+
+ memcpy (&sVal, ®s.fpu_fsw, 2);
+ context->FloatSave.StatusWord = sVal;
+
+ context->FloatSave.TagWord = regs.fpu_ftw;
+ context->FloatSave.ErrorOffset = regs.fpu_ip;
+ context->FloatSave.ErrorSelector = regs.fpu_cs;
+ context->FloatSave.DataOffset = regs.fpu_dp;
+ context->FloatSave.DataSelector = regs.fpu_ds;
+
+ memcpy (context->FloatSave.RegisterArea, regs.fpu_stmm0.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 10,
+ regs.fpu_stmm1.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 20,
+ regs.fpu_stmm2.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 30,
+ regs.fpu_stmm3.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 40,
+ regs.fpu_stmm4.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 50,
+ regs.fpu_stmm5.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 60,
+ regs.fpu_stmm6.mmst_reg, 10);
+ memcpy (context->FloatSave.RegisterArea + 70,
+ regs.fpu_stmm7.mmst_reg, 10);
+
+ context->FloatSave.Cr0NpxState = 0; /* FIXME */
+ }
+
+ return;
+ error:
+ set_error (STATUS_ACCESS_VIOLATION);
+}
/* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
- {
- /* FIXME */
- }
+static void set_thread_context (struct thread *thread, unsigned int flags,
+ const CONTEXT *context)
+{
+ if (flags & CONTEXT_FULL)
+ {
+ x86_thread_state32_t regs;
+ mach_msg_type_number_t sc = x86_THREAD_STATE32_COUNT;
+
+ if (thread_get_state (thread->thread_port, x86_THREAD_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ if (flags & CONTEXT_INTEGER)
+ {
+ regs.eax = context->Eax;
+ regs.ebx = context->Ebx;
+ regs.ecx = context->Ecx;
+ regs.edx = context->Edx;
+ regs.esi = context->Esi;
+ regs.edi = context->Edi;
+ }
+
+ if (flags & CONTEXT_CONTROL)
+ {
+ regs.ebp = context->Ebp;
+ regs.esp = context->Esp;
+ regs.eip = context->Eip;
+ regs.cs = context->SegCs;
+ regs.ss = context->SegSs;
+ regs.eflags = context->EFlags;
+ }
+
+ if (flags & CONTEXT_SEGMENTS)
+ {
+ regs.ds = context->SegDs;
+ regs.es = context->SegEs;
+ regs.fs = context->SegFs;
+ regs.gs = context->SegGs;
+ }
+
+ if (thread_set_state (thread->thread_port, x86_THREAD_STATE32,
+ (thread_state_t)®s, sc))
+ goto error;
+ }
+
+ if (flags & CONTEXT_DEBUG_REGISTERS)
+ {
+ x86_debug_state32_t regs;
+ mach_msg_type_number_t sc = x86_DEBUG_STATE32_COUNT;
+
+ if (thread_get_state (thread->thread_port, x86_DEBUG_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ regs.dr0 = context->Dr0;
+ regs.dr1 = context->Dr1;
+ regs.dr2 = context->Dr2;
+ regs.dr3 = context->Dr3;
+ regs.dr6 = context->Dr6;
+ regs.dr7 = context->Dr7;
+
+ if (thread_set_state (thread->thread_port, x86_DEBUG_STATE32,
+ (thread_state_t)®s, sc))
+ goto error;
+ }
+
+ if (flags & CONTEXT_FLOATING_POINT)
+ {
+ x86_float_state32_t regs;
+ mach_msg_type_number_t sc = x86_FLOAT_STATE32_COUNT;
+ unsigned short sVal;
+
+ if (thread_get_state (thread->thread_port, x86_FLOAT_STATE32,
+ (thread_state_t)®s, &sc))
+ goto error;
+
+ sVal = context->FloatSave.ControlWord;
+ memcpy (®s.fpu_fcw, &sVal, 2);
+
+ sVal = context->FloatSave.StatusWord;
+ memcpy (®s.fpu_fsw, &sVal, 2);
+
+ regs.fpu_ftw = context->FloatSave.TagWord;
+ regs.fpu_ip = context->FloatSave.ErrorOffset;
+ regs.fpu_cs = context->FloatSave.ErrorSelector;
+ regs.fpu_dp = context->FloatSave.DataOffset;
+ regs.fpu_ds = context->FloatSave.DataSelector;
+
+ memcpy (regs.fpu_stmm0.mmst_reg, context->FloatSave.RegisterArea, 10);
+ memcpy (regs.fpu_stmm1.mmst_reg,
+ context->FloatSave.RegisterArea + 10, 10);
+ memcpy (regs.fpu_stmm2.mmst_reg,
+ context->FloatSave.RegisterArea + 20, 10);
+ memcpy (regs.fpu_stmm3.mmst_reg,
+ context->FloatSave.RegisterArea + 30, 10);
+ memcpy (regs.fpu_stmm4.mmst_reg,
+ context->FloatSave.RegisterArea + 40, 10);
+ memcpy (regs.fpu_stmm5.mmst_reg,
+ context->FloatSave.RegisterArea + 50, 10);
+ memcpy (regs.fpu_stmm6.mmst_reg,
+ context->FloatSave.RegisterArea + 60, 10);
+ memcpy (regs.fpu_stmm7.mmst_reg,
+ context->FloatSave.RegisterArea + 70, 10);
+
+ if (thread_set_state (thread->thread_port, x86_FLOAT_STATE32,
+ (thread_state_t)®s, sc))
+ goto error;
+ }
+
+ return;
+ error:
+ set_error (STATUS_ACCESS_VIOLATION);
+}
#else /* __APPLE__ */
#error You must implement get/set_thread_context for your platform
Index: context_ppc.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/context_ppc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- context_ppc.c 28 Mar 2007 14:34:22 -0000 1.1
+++ context_ppc.c 30 Mar 2007 15:55:03 -0000 1.2
@@ -27,7 +27,7 @@
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int pid = thread->unix_tid;
+ int pid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
#ifndef __PPC__ /* EZUST - apparently not supported! FIXME */
Index: context_sparc.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/context_sparc.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- context_sparc.c 21 Jan 2005 20:05:06 -0000 1.3
+++ context_sparc.c 30 Mar 2007 15:55:03 -0000 1.4
@@ -32,7 +32,7 @@
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
- int tid = thread->unix_tid;
+ int tid = thread->unix_tid_or_pid;
if (flags & CONTEXT_FULL)
{
struct regs regs;
Index: debugger.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/debugger.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- debugger.c 29 Mar 2007 14:09:54 -0000 1.13
+++ debugger.c 30 Mar 2007 15:55:03 -0000 1.14
@@ -786,9 +786,9 @@
struct thread *thread;
for (thread = process->thread_list; thread; thread = thread->proc_next)
{
- if (thread->unix_tid)
+ if (thread->unix_tid_or_pid)
{
- wine_tkill( thread->unix_tid, SIGTRAP );
+ wine_tkill_or_kill( thread->unix_tid_or_pid, SIGTRAP );
break;
}
}
Index: fd_server.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/fd_server.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- fd_server.c 28 Mar 2007 14:34:22 -0000 1.15
+++ fd_server.c 30 Mar 2007 15:55:03 -0000 1.16
@@ -468,7 +468,7 @@
{
sigset_t sigset;
- if( debug_level > 1 ) fprintf( stderr, "fd server: thread created as pid %d\n", wine_gettid() );
+ if( debug_level > 1 ) fprintf( stderr, "fd server: thread created as pid %d\n", wine_gettid_or_pid() );
fd_server_signal_init( &sigset );
get_new_fdserver_listener();
--- NEW FILE: macosx.c ---
/*
* Server-side support for MacOS X
*
* Copyright (C) 2006 TransGaming Technologies
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include "process.h"
#include "thread.h"
#include "request.h"
#include "server_memory.h"
/* handle a SIGCHLD signal */
void sigchld_handler( int sig )
{
}
/* detach from a Unix thread and kill it */
void detach_thread( struct thread *thread, int sig )
{
if (!thread->unix_tid_or_pid) return;
if (sig) {
/* FIXME - send signal to thread wine_tkill( thread->unix_tid_or_pid, sig ); */
}
if (thread->suspend + thread->process->suspend > 0) continue_thread( thread );
}
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
mach_msg_return_t Err;
/* can't stop a thread while initialisation is in progress */
if (!thread->unix_tid_or_pid || thread->process->init_event ||
!thread->thread_port)
return;
Err = thread_suspend (thread->thread_port);
if (Err != MACH_MSG_SUCCESS)
fprintf (stderr, "Warn: suspending thread port 0x%x failed: 0x%x\n",
thread->thread_port, Err);
}
/* make a thread continue (at the Unix level) */
void continue_thread( struct thread *thread )
{
mach_msg_return_t Err;
if (!thread->unix_tid_or_pid || !thread->thread_port)
return;
Err = thread_resume (thread->thread_port);
if (Err != MACH_MSG_SUCCESS)
fprintf (stderr, "Warn: resuming thread port 0x%x failed: 0x%x\n",
thread->thread_port, Err);
}
/* suspend thread for interaction */
int suspend_for_ptrace( struct thread *thread )
{
suspend_thread (thread, 0);
return 1;
}
/* read data from specified process */
int read_thread_data (struct thread *thread, uintptr_t addr, size_t len,
void* data, size_t* p_num_read)
{
kern_return_t Err;
vm_size_t bytes_read = len;
Err = vm_read_overwrite (thread->process->task_port, addr, len,
(vm_address_t)data,
&bytes_read);
if (Err != KERN_SUCCESS)
return -1;
if (p_num_read)
*p_num_read = bytes_read;
return 0;
}
/* read data from a process memory space
* addr is the virtual address in that process, len is the number of bytes.
*/
void read_process_memory (struct process *process, uintptr_t addr,
size_t len, void *dest, size_t check_len)
{
struct thread *thread = process->thread_list;
vm_size_t bytes_read = len;
kern_return_t Err;
if (!thread) /* process is dead */
{
set_error (STATUS_ACCESS_DENIED);
return;
}
set_error (STATUS_SUCCESS);
if (!(thread->sched_mode & SCDM_INTERNAL))
suspend_for_ptrace (thread);
Err = vm_read_overwrite (thread->process->task_port, addr, len,
(vm_address_t)dest,
&bytes_read);
if (!(thread->sched_mode & SCDM_INTERNAL))
resume_thread (thread);
if (Err == KERN_PROTECTION_FAILURE)
set_error (STATUS_ACCESS_DENIED);
else if (Err != KERN_SUCCESS)
set_error (STATUS_ACCESS_VIOLATION);
if (Err != KERN_SUCCESS)
fprintf (stderr, "Warn: read_process_memory failed: 0x%x\n", Err);
}
/* write data to a process memory space
* addr is the virtual address in that process, len is the number of bytes.
*/
void write_process_memory (struct process *process, uintptr_t addr,
size_t len, const void *src,
size_t check_len)
{
struct thread *thread = process->thread_list;
kern_return_t Err;
if (!thread) /* process is dead */
{
set_error( STATUS_ACCESS_DENIED );
return;
}
set_error (STATUS_SUCCESS);
if (!(thread->sched_mode & SCDM_INTERNAL))
suspend_for_ptrace (thread);
Err = vm_write (thread->process->task_port, addr, (vm_offset_t)src, len);
if (Err == KERN_PROTECTION_FAILURE)
set_error (STATUS_ACCESS_DENIED);
else if (Err != KERN_SUCCESS)
set_error (STATUS_ACCESS_VIOLATION);
if (Err != KERN_SUCCESS)
fprintf (stderr, "Warn: write_process_memory failed: 0x%x\n", Err);
resume_thread (thread);
}
Index: main.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/main.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- main.c 30 Mar 2007 15:05:51 -0000 1.17
+++ main.c 30 Mar 2007 15:55:03 -0000 1.18
@@ -203,7 +203,7 @@
}
}
#else
-static inline set_wait4__WALL_value(void) {}
+static inline void set_wait4__WALL_value(void) {}
#endif /* defined(linux) */
int main( int argc, char *argv[] )
Index: Makefile.in
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/Makefile.in,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Makefile.in 29 Mar 2007 21:48:34 -0000 1.19
+++ Makefile.in 30 Mar 2007 15:55:03 -0000 1.20
@@ -36,7 +36,6 @@
named_pipe.c \
object.c \
process.c \
- ptrace.c \
queue.c \
registry.c \
request.c \
@@ -56,6 +55,9 @@
window.c \
token.c
+@DARWIN_TRUE@LIB_C_SRCS += macosx.c
+@DARWIN_FALSE@LIB_C_SRCS += ptrace.c
+
PROGRAMS = wineserver
all: $(PROGRAMS)
Index: process.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/process.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- process.c 29 Mar 2007 14:03:56 -0000 1.39
+++ process.c 30 Mar 2007 15:55:03 -0000 1.40
@@ -214,6 +214,9 @@
process->queue = NULL;
process->atom_table = NULL;
process->ldt_copy = NULL;
+#ifdef __APPLE__
+ process->task_port = MACH_PORT_NULL;
+#endif
process->group_id = 0;
process->id = 0;
process->exe.next = NULL;
@@ -269,7 +272,7 @@
struct process *process = current->process;
/* current thread is the boot thread so tid == pid */
- struct thread *parent_thread = get_parent_thread_of_created_pid( current->unix_tid );
+ struct thread *parent_thread = get_parent_thread_of_created_pid( current->unix_tid_or_pid );
struct process *parent = NULL;
struct startup_info *info = NULL;
@@ -378,6 +381,10 @@
if (process->exe.file_name) mem_free( process->exe.file_name );
if (process->context_fd_list) mem_free( process->context_fd_list );
+#ifdef __APPLE__
+ if (process->task_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), process->task_port);
+#endif
}
/* dump a process on stdout for debugging purposes */
@@ -584,9 +591,10 @@
{
if (!thread->suspend || (thread->sched_mode & SCDM_INTERNAL))
{
- if (!thread->wait && thread->unix_tid && !(thread->sched_mode & SCDM_BLOCKED))
+ if (!thread->wait && thread->unix_tid_or_pid &&
+ !(thread->sched_mode & SCDM_BLOCKED))
dequeue_thread(thread);
- if (thread->wait && thread->unix_tid)
+ if (thread->wait && thread->unix_tid_or_pid)
dequeue_thread_wait(thread);
stop_thread( thread );
}
@@ -608,11 +616,12 @@
if (!thread->suspend || (thread->sched_mode & SCDM_INTERNAL))
{
continue_thread( thread );
- if (!thread->wait && thread->unix_tid && !(thread->sched_mode & SCDM_BLOCKED)) {
+ if (!thread->wait && thread->unix_tid_or_pid &&
+ !(thread->sched_mode & SCDM_BLOCKED)) {
thread_not_starved(thread);
queue_thread(thread);
}
- if (thread->wait && thread->unix_tid)
+ if (thread->wait && thread->unix_tid_or_pid)
queue_thread_wait(thread);
wake_thread( thread );
}
@@ -701,110 +710,6 @@
reschedule();
}
-/* Stopping all the threads and reading /proc/pid/maps would be better,
- * but this will do. */
-static int check_process_read_access( struct thread *thread, uintptr_t addr,
- size_t len )
-{
- char buf;
- size_t num_read;
-
- size_t page_size = get_page_size();
-
- /* The range to check is [addr,end). */
- uintptr_t end = addr + len;
-
- /* Make [addr,end) cover all the pages in the range to check. */
- addr -= addr % page_size;
- if (end % page_size != 0) end += page_size - (end % page_size);
-
- for (; addr < end; addr += page_size)
- {
- if (read_thread_data( thread, addr, 1, &buf, &num_read) == -1)
- return 0;
- }
-
- return 1;
-}
-
-/* read data from a process memory space
- * addr is the virtual address in that process, len is the number of bytes.
- *
- * check_len (if nonzero) is the length of the range that needs to be
- * checked for read permissions.
- */
-static void read_process_memory( struct process *process, uintptr_t addr,
- size_t len, void *dest, size_t check_len )
-{
- struct thread *thread = process->thread_list;
-
- if (!thread) /* process is dead */
- {
- set_error( STATUS_ACCESS_DENIED );
- return;
- }
-
- while (thread) {
- set_error( STATUS_SUCCESS );
- if (!(thread->sched_mode & SCDM_INTERNAL) &&
- suspend_for_ptrace( thread ))
- {
- size_t bytes_read;
-
- if (!check_process_read_access( thread, addr, check_len ))
- {
- resume_thread( thread ); /* resume thread even if error */
- set_error( STATUS_ACCESS_DENIED );
- return;
- }
-
- read_thread_data( thread, addr, len, dest, &bytes_read);
- resume_thread( thread );
- return;
- }
- /* if we couldn't attach to this thread,
- * possibly because it was still initializing,
- * try the next thread instead. */
- thread = thread->proc_next;
- }
-}
-
-/* write data to a process memory space
- * addr is the virtual address in that process, len is the number of bytes.
- *
- * check_len (if nonzero) is the size of the range that should be checked
- * for write access. We don't actually do this yet. (We'd have to stop
- * all the threads and look through /proc/pid/maps.)
- */
-static void write_process_memory( struct process *process, uintptr_t addr,
- size_t len, const void *src,
- size_t check_len )
-{
- struct thread *thread = process->thread_list;
-
- if (!thread) /* process is dead */
- {
- set_error( STATUS_ACCESS_DENIED );
- return;
- }
-
- while (thread) {
- set_error( STATUS_SUCCESS );
- if (!(thread->sched_mode & SCDM_INTERNAL) &&
- suspend_for_ptrace( thread ))
- {
- size_t bytes_written;
- write_thread_data( thread, addr, len, src, &bytes_written);
- resume_thread( thread );
- return;
- }
- /* if we couldn't attach to this thread,
- * possibly because it was still initializing,
- * try the next thread instead. */
- thread = thread->proc_next;
- }
-}
-
/* take a snapshot of currently running processes */
struct process_snapshot *process_snap( int *count )
{
@@ -927,13 +832,17 @@
/* initialize a new process */
DECL_HANDLER(init_process)
{
- if (!current->unix_tid)
+ if (!current->unix_tid_or_pid)
{
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
return;
}
current->process->ldt_copy = req->ldt_copy;
+
init_process( reply );
+
+ reply->wineserver_pid = getpid ();
+ reply->unique_msg_id = SERVER_GLOBAL_VARIABLE (unique_msg_id)++;
}
/* signal the end of the process initialization */
Index: process.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/process.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- process.h 27 Mar 2007 20:25:27 -0000 1.15
+++ process.h 30 Mar 2007 15:55:03 -0000 1.16
@@ -7,6 +7,14 @@
#ifndef __WINE_SERVER_PROCESS_H
#define __WINE_SERVER_PROCESS_H
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
+
#include "object.h"
struct msg_queue;
@@ -54,6 +62,9 @@
struct msg_queue *queue; /* main message queue */
struct atom_table *atom_table; /* pointer to local atom table */
struct process_dll exe; /* main exe file */
+#ifdef __APPLE__
+ mach_port_t task_port; /* task port for process */
+#endif
void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags in client addr space */
struct token *token; /* token object */
@@ -110,4 +121,10 @@
extern struct process *get_process_from_id( const process_id_t id );
extern void remove_process_id ( const process_id_t process_id );
+extern void read_process_memory( struct process *process, uintptr_t addr,
+ size_t len, void *dest, size_t check_len );
+extern void write_process_memory( struct process *process, uintptr_t addr,
+ size_t len, const void *src,
+ size_t check_len );
+
#endif /* __WINE_SERVER_PROCESS_H */
Index: protocol.def
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/protocol.def,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- protocol.def 29 Mar 2007 14:03:56 -0000 1.39
+++ protocol.def 30 Mar 2007 15:55:03 -0000 1.40
@@ -229,6 +229,8 @@
handle_t hstdout; /* handle for stdout */
handle_t hstderr; /* handle for stderr */
int cmd_show; /* main window show mode */
+ pid_t wineserver_pid; /* Apple: pid of wineserver to identify port */
+ int unique_msg_id; /* Apple: unique id to send with port */
VARARG(filename,string); /* file name of main exe */
@END
@@ -252,7 +254,8 @@
/* Initialize a thread; called from the child after fork()/clone() */
@REQ(init_thread)
- pid_t unix_tid; /* Unix tid of new thread */
+ pid_t unix_tid_or_pid; /* Unix tid or pid of new thread, depending */
+ /* whether OS supports cross-process tids */
void* teb; /* TEB of new thread (in thread address space) */
void* entry; /* thread entry point (in thread address space) */
int reply_fd; /* fd for reply pipe */
@@ -260,10 +263,20 @@
@REPLY
process_id_t pid; /* process id of the new thread's process */
thread_id_t tid; /* thread id of the new thread */
+ pid_t wineserver_pid; /* Apple: pid of wineserver to identify port */
+ int unique_msg_id; /* Apple: unique id to send with port */
int boot; /* is this the boot thread? */
int version; /* protocol version */
@END
+/* Apple-specific request indicating that a mach port for the thread
+ has been sent to the wineserver */
+@REQ(thread_port_sent)
+ int unique_msg_id; /* unique id to identify the port request */
+ int is_process; /* 1 if sending the task port, 0 otherwise */
+ void* entry; /* thread entry point */
+@END
+
/* Sets thread module load status; called during and after DllThreadAttach */
@REQ(set_thread_moduleload)
int status; /* current thread status */
@@ -1915,6 +1928,9 @@
@REQ(update_thread_tid)
pid_t old_unix_tid; /* Old unix tid */
pid_t new_unix_tid; /* New unix tid */
+@REPLY
+ pid_t wineserver_pid; /* Apple: pid of wineserver to identify port */
+ int unique_msg_id; /* Apple: unique id to send with port */
@END
/* Sending signals */
Index: ptrace.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/ptrace.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- ptrace.c 30 Mar 2007 15:53:39 -0000 1.21
+++ ptrace.c 30 Mar 2007 15:55:03 -0000 1.22
@@ -25,7 +25,11 @@
#include "process.h"
#include "thread.h"
#include "request.h"
+#include "server_memory.h"
+#ifdef __APPLE__
+#error "This file is unsupported on MacOS X"
+#endif
#ifndef PTRACE_CONT
#define PTRACE_CONT PT_CONTINUE
@@ -61,11 +65,7 @@
#define __WALL 0
#endif
-#ifndef __APPLE__
static const int use_ptrace = 1; /* set to 0 to disable ptrace */
-#else
-static const int use_ptrace = 0; /* don't do any ptracing on MacOS X - need alternate mechanisms using mach */
-#endif
extern int alarming;
@@ -74,6 +74,15 @@
#endif /* !defined(linux) */
int wait4__WALL = 0;
+
+/* find a thread from a Unix tid - requires cross-process tids */
+static struct thread *get_thread_from_tid( int tid )
+{
+ struct thread *t = SERVER_GLOBAL_VARIABLE( first_thread );
+ while (t && (t->unix_tid_or_pid != tid)) t = t->next;
+ return t;
+}
+
/* handle a status returned by wait4 */
static int handle_child_status( struct thread *thread, int tid, int status )
{
@@ -93,7 +102,7 @@
else
{
info_msg( WITH_DEBUG, thread, "*detached*\n" );
- ptrace( PTRACE_DETACH, tid, NULL, NULL );
+ ptrace( PTRACE_DETACH, tid, NULL, 0 );
thread->attached = 0;
}
break;
@@ -116,7 +125,7 @@
if (thread && (WIFSIGNALED(status) || WIFEXITED(status)))
{
thread->attached = 0;
- thread->unix_tid = 0;
+ thread->unix_tid_or_pid = 0;
if (WIFSIGNALED(status))
info_msg( WITH_DEBUG, thread, "*exited* signal=%d\n", WTERMSIG(status) );
else
@@ -139,7 +148,7 @@
}
/* wait for a ptraced child to get a certain signal */
-void wait4_thread( struct thread *thread, int signal )
+static void wait4_thread( struct thread *thread, int signal )
{
int res, status;
@@ -147,7 +156,8 @@
{
alarming = 0;
alarm(1); /* make wait4 timeout in 1 second */
- if ((res = wait4( thread->unix_tid, &status, WUNTRACED | wait4__WALL, NULL )) == -1)
+ if ((res = wait4( thread->unix_tid_or_pid, &status,
+ WUNTRACED | wait4__WALL, NULL )) == -1)
{
if (errno == EINTR && alarming) {
fprintf(stderr, "WARNING: wait4 timed out\n");
@@ -166,9 +176,9 @@
{
/* this may fail if the client is already being debugged */
if (!use_ptrace) return 0;
- if (ptrace( PTRACE_ATTACH, thread->unix_tid, 0, 0 ) == -1)
+ if (ptrace( PTRACE_ATTACH, thread->unix_tid_or_pid, 0, 0 ) == -1)
{
- if (errno == ESRCH) thread->unix_tid = 0; /* process got killed */
+ if (errno == ESRCH) thread->unix_tid_or_pid = 0; /* process got killed */
return 0;
}
info_msg( WITH_DEBUG, thread, "*attached*\n" );
@@ -180,20 +190,20 @@
/* detach from a Unix thread and kill it */
void detach_thread( struct thread *thread, int sig )
{
- if (!thread->unix_tid) return;
+ if (!thread->unix_tid_or_pid) return;
if (thread->attached)
{
/* make sure it is stopped */
suspend_thread( thread, 0 );
- if (sig) wine_tkill( thread->unix_tid, sig );
+ if (sig) wine_tkill( thread->unix_tid_or_pid, sig );
info_msg( WITH_DEBUG, thread, "*detached*\n" );
- ptrace( PTRACE_DETACH, thread->unix_tid, (caddr_t)1, sig );
+ ptrace( PTRACE_DETACH, thread->unix_tid_or_pid, (caddr_t)1, sig );
thread->suspend = 0; /* detach makes it continue */
thread->attached = 0;
}
else
{
- if (sig) wine_tkill( thread->unix_tid, sig );
+ if (sig) wine_tkill( thread->unix_tid_or_pid, sig );
if (thread->suspend + thread->process->suspend > 0) continue_thread( thread );
}
}
@@ -202,27 +212,28 @@
void stop_thread( struct thread *thread )
{
/* can't stop a thread while initialisation is in progress */
- if (!thread->unix_tid || thread->process->init_event) return;
+ if (!thread->unix_tid_or_pid || thread->process->init_event) return;
/* 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_tid) return;
- wine_tkill( thread->unix_tid, SIGSTOP );
+ if (!thread->unix_tid_or_pid) return;
+ wine_tkill( thread->unix_tid_or_pid, SIGSTOP );
if (thread->attached) wait4_thread( thread, SIGSTOP );
}
/* make a thread continue (at the Unix level) */
void continue_thread( struct thread *thread )
{
- if (!thread->unix_tid) return;
- if (!thread->attached) wine_tkill( thread->unix_tid, SIGCONT );
+ if (!thread->unix_tid_or_pid) return;
+ if (!thread->attached) wine_tkill( thread->unix_tid_or_pid, SIGCONT );
else if (get_thread_single_step(thread))
- ptrace( PTRACE_SINGLESTEP, thread->unix_tid, (caddr_t)1, SIGSTOP);
+ ptrace( PTRACE_SINGLESTEP, thread->unix_tid_or_pid,
+ (caddr_t)1, SIGSTOP);
else
{
info_msg( WITH_DEBUG, thread, "*detached*\n" );
- ptrace( PTRACE_DETACH, thread->unix_tid, NULL, NULL);
+ ptrace( PTRACE_DETACH, thread->unix_tid_or_pid, NULL, NULL);
thread->attached = 0;
}
}
@@ -237,7 +248,7 @@
return 1;
}
/* can't stop a thread while initialisation is in progress */
- if (!thread->unix_tid || thread->process->init_event) goto error;
+ if (!thread->unix_tid_or_pid || thread->process->init_event) goto error;
thread->suspend++;
if (attach_thread( thread )) return 1;
thread->suspend--;
@@ -251,7 +262,8 @@
uint32_t *data )
{
errno = 0;
- *data = ptrace( PTRACE_PEEKDATA, thread->unix_tid, (caddr_t)addr, 0 );
+ *data = ptrace( PTRACE_PEEKDATA, thread->unix_tid_or_pid,
+ (caddr_t)addr, 0 );
if ( *data == -1 && errno)
{
file_set_error();
@@ -327,18 +339,88 @@
return -1;
}
+/* Stopping all the threads and reading /proc/pid/maps would be better,
+ * but this will do. */
+static int check_process_read_access( struct thread *thread, uintptr_t addr,
+ size_t len )
+{
+ char buf;
+ size_t num_read;
+
+ size_t page_size = get_page_size();
+
+ /* The range to check is [addr,end). */
+ uintptr_t end = addr + len;
+
+ /* Make [addr,end) cover all the pages in the range to check. */
+ addr -= addr % page_size;
+ if (end % page_size != 0) end += page_size - (end % page_size);
+
+ for (; addr < end; addr += page_size)
+ {
+ if (read_thread_data( thread, addr, 1, &buf, &num_read) == -1)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* read data from a process memory space
+ * addr is the virtual address in that process, len is the number of bytes.
+ *
+ * check_len (if nonzero) is the length of the range that needs to be
+ * checked for read permissions.
+ */
+void read_process_memory( struct process *process, uintptr_t addr,
+ size_t len, void *dest, size_t check_len )
+{
+ struct thread *thread = process->thread_list;
+
+ if (!thread) /* process is dead */
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ return;
+ }
+
+ while (thread) {
+ set_error( STATUS_SUCCESS );
+ if (!(thread->sched_mode & SCDM_INTERNAL) &&
+ suspend_for_ptrace( thread ))
+ {
+ size_t bytes_read;
+
+ if (!check_process_read_access( thread, addr, check_len ))
+ {
+ resume_thread( thread ); /* resume thread even if error */
+ set_error( STATUS_ACCESS_DENIED );
+ return;
+ }
+
+ read_thread_data( thread, addr, len, dest, &bytes_read);
+ resume_thread( thread );
+ return;
+ }
+ /* if we couldn't attach to this thread,
+ * possibly because it was still initializing,
+ * try the next thread instead. */
+ thread = thread->proc_next;
+ }
+}
+
+
/* write an int to a thread address space */
static int write_thread_int( struct thread *thread, uintptr_t addr,
uint32_t data )
{
int res;
- if ((res = ptrace( PTRACE_POKEDATA, thread->unix_tid, (caddr_t)addr, data )) == -1)
+ if ((res = ptrace( PTRACE_POKEDATA, thread->unix_tid_or_pid,
+ (caddr_t)addr, data )) == -1)
file_set_error();
return res;
}
int write_thread_data( struct thread *thread, uintptr_t addr, size_t len,
- const void* data, size_t* p_num_written )
+ const void* data)
{
size_t num_written = 0;
const char* p_data = (const char *)data;
@@ -400,10 +482,44 @@
num_written += len;
}
- *p_num_written = num_written;
return 0;
out_err:
- *p_num_written = num_written;
return -1;
}
+
+
+/* write data to a process memory space
+ * addr is the virtual address in that process, len is the number of bytes.
+ *
+ * check_len (if nonzero) is the size of the range that should be checked
+ * for write access. We don't actually do this yet. (We'd have to stop
+ * all the threads and look through /proc/pid/maps.)
+ */
+void write_process_memory( struct process *process, uintptr_t addr,
+ size_t len, const void *src,
+ size_t check_len )
+{
+ struct thread *thread = process->thread_list;
+
+ if (!thread) /* process is dead */
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ return;
+ }
+
+ while (thread) {
+ set_error( STATUS_SUCCESS );
+ if (!(thread->sched_mode & SCDM_INTERNAL) &&
+ suspend_for_ptrace( thread ))
+ {
+ write_thread_data( thread, addr, len, src);
+ resume_thread( thread );
+ return;
+ }
+ /* if we couldn't attach to this thread,
+ * possibly because it was still initializing,
+ * try the next thread instead. */
+ thread = thread->proc_next;
+ }
+}
Index: request.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/request.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- request.c 29 Mar 2007 14:13:44 -0000 1.25
+++ request.c 30 Mar 2007 15:55:03 -0000 1.26
@@ -33,6 +33,10 @@
#include <sys/un.h>
#include <unistd.h>
+#ifdef __APPLE__
+#include <servers/bootstrap.h>
+#endif
+
#include "winnt.h"
#include "winbase.h"
#include "wincon.h"
@@ -578,6 +582,29 @@
SERVER_GLOBAL_VARIABLE( serverdir ) = serverdir;
}
+
+#ifdef __APPLE__
+/* Create bootstrap port on which we receive task & thread ports for
+ wine processes */
+mach_port_t wineserver_bootstrap_port_create ()
+{
+ char PortName[BOOTSTRAP_MAX_NAME_LEN];
+ mach_port_t Port;
+
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &Port);
+ mach_port_insert_right (mach_task_self (), Port, Port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ snprintf (PortName, sizeof (PortName),
+ "com.transgaming.server:%d", getpid ());
+ if (bootstrap_register (bootstrap_port, PortName, Port) == KERN_SUCCESS)
+ return Port;
+
+ mach_port_destroy (mach_task_self (), Port);
+ return MACH_PORT_NULL;
+}
+#endif
+
+
/* open the master server socket and start waiting for new clients */
void open_master_socket(void)
{
@@ -626,7 +653,15 @@
#endif
/* go in the background if requested */
- if( !wineserver_is_daemon ) return;
+ if( !wineserver_is_daemon )
+ {
+#ifdef __APPLE__
+ if ((SERVER_GLOBAL_VARIABLE (bootstrap_port) =
+ wineserver_bootstrap_port_create ()) == MACH_PORT_NULL)
+ fatal_error ("unable to register bootstrap port\n");
+#endif
+ return;
+ }
switch(fork())
{
@@ -638,6 +673,12 @@
default:
_exit(0); /* do not call atexit functions */
}
+
+#ifdef __APPLE__
+ if ((SERVER_GLOBAL_VARIABLE (bootstrap_port) =
+ wineserver_bootstrap_port_create ()) == MACH_PORT_NULL)
+ fatal_error ("unable to register bootstrap port\n");
+#endif
}
/* close the master socket and stop waiting for new clients */
Index: request.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/request.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- request.h 28 Mar 2007 17:49:58 -0000 1.26
+++ request.h 30 Mar 2007 15:55:03 -0000 1.27
@@ -142,6 +142,7 @@
DECL_HANDLER(init_process);
DECL_HANDLER(init_process_done);
DECL_HANDLER(init_thread);
+DECL_HANDLER(thread_port_sent);
DECL_HANDLER(set_thread_moduleload);
DECL_HANDLER(get_thread_moduleload);
DECL_HANDLER(terminate_process);
@@ -316,6 +317,7 @@
(req_handler)req_init_process,
(req_handler)req_init_process_done,
(req_handler)req_init_thread,
+ (req_handler)req_thread_port_sent,
(req_handler)req_set_thread_moduleload,
(req_handler)req_get_thread_moduleload,
(req_handler)req_terminate_process,
Index: server_memory.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/server_memory.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- server_memory.h 29 Mar 2007 14:03:56 -0000 1.12
+++ server_memory.h 30 Mar 2007 15:55:03 -0000 1.13
@@ -3,6 +3,9 @@
#include <object.h> /* For mem_alloc */
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
#define HAVE_STATIC_MEMORY_FOR_FILE(file) void* __server_static_holder_for_##file
@@ -38,6 +41,9 @@
/* server start time */
struct timeval server_start_time;
+ int unique_msg_id; /* Apple: unique id to be passed with port
+ rights msg */
+
/* List of threads in the system. Should figure a way to make it not global. */
struct thread *first_thread;
@@ -69,7 +75,11 @@
/* serverdir */
char* serverdir;
-
+
+#ifdef __APPLE__
+ mach_port_t bootstrap_port;
+#endif
+
HAVE_STATIC_MEMORY_FOR_FILE( atom );
HAVE_STATIC_MEMORY_FOR_FILE( cdrom_eject );
HAVE_STATIC_MEMORY_FOR_FILE( console );
@@ -92,6 +102,7 @@
/* Global memory semaphore information */
LONG sema_lock_count;
+ pid_t sema_owning_pid;
pid_t sema_owning_tid;
unsigned int sema_recursion_count;
Index: shm.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/shm.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- shm.c 29 Mar 2007 14:03:56 -0000 1.17
+++ shm.c 30 Mar 2007 15:55:03 -0000 1.18
@@ -137,13 +137,13 @@
/* Sigaction is unfortunately per process, not per thread so we may have to do a manual
* dispatch to the correct signal handler for the running thread.
*/
- if( signal_tid != wine_gettid() )
+ if( signal_tid != wine_get_inprocess_tid() )
{
shm_orig_sigsegv_action.sa_handler( sig );
return;
}
- info_msg( ALWAYS, current, "Fatal Signal during tid %d shmwineserver execution!\n", wine_gettid() );
+ info_msg( ALWAYS, current, "Fatal Signal during tid %d shmwineserver execution!\n", wine_get_inprocess_tid() );
release_shm_server_semaphore();
@@ -183,7 +183,7 @@
{
if( is_wineserver ) return;
- signal_tid = wine_gettid();
+ signal_tid = wine_get_inprocess_tid();
}
void signal_leave_shm(void)
@@ -306,7 +306,8 @@
#if defined( RECURIVE_CRITSECION_SEMA )
static inline void initialize_recursion(void)
{
- SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = wine_gettid(); /* We start locked for wineserver */
+ SERVER_GLOBAL_VARIABLE( sema_owning_pid ) = getpid();
+ SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = wine_get_inprocess_tid(); /* We start locked for wineserver */
SERVER_GLOBAL_VARIABLE( sema_recursion_count ) = 1; /* We start locked for wineserver */
}
#endif /* RECURIVE_CRITSECION_SEMA */
@@ -315,13 +316,14 @@
void acquire_shm_server_semaphore_exclusive(void)
{
static struct sembuf acquire_operation = { 0, -1, 0 };
- pid_t tid;
+ pid_t pid,tid;
/* Don't do anything if we're not running as a shared memory server */
if( !SERVER_GLOBAL_VARIABLE( shared_memory_server ) )
return;
- tid = wine_gettid();
+ pid = getpid();
+ tid = wine_get_inprocess_tid();
if( debug_level > DEBUG_LEVEL ) fprintf( stderr, "%d - Attempting to get sema\n", tid );
@@ -331,7 +333,8 @@
#endif
#if defined( RECURIVE_CRITSECION_SEMA )
- if( tid == SERVER_GLOBAL_VARIABLE( sema_owning_tid ))
+ if( (pid == SERVER_GLOBAL_VARIABLE( sema_owning_pid )) &&
+ (tid == SERVER_GLOBAL_VARIABLE( sema_owning_tid )))
{
SERVER_GLOBAL_VARIABLE( sema_recursion_count )++;
return;
@@ -353,6 +356,7 @@
}
#endif
+ SERVER_GLOBAL_VARIABLE( sema_owning_pid ) = pid;
SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = tid;
SERVER_GLOBAL_VARIABLE( sema_recursion_count ) = 1;
@@ -382,6 +386,7 @@
else
{
SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = 0;
+ SERVER_GLOBAL_VARIABLE( sema_owning_pid ) = 0;
#endif
#if defined( CRITSECTION_SEMA )
if( interlocked_dec( &SERVER_GLOBAL_VARIABLE( sema_lock_count ) ) >= 0 )
@@ -403,7 +408,7 @@
}
#endif /* RECURIVE_CRITSECION_SEMA */
- if( debug_level > DEBUG_LEVEL ) fprintf( stderr, "%d - Released sema\n", wine_gettid() );
+ if( debug_level > DEBUG_LEVEL ) fprintf( stderr, "%d - Released sema\n", wine_gettid_or_pid() );
}
@@ -660,7 +665,8 @@
SERVER_GLOBAL_VARIABLE( serverdir ) = NULL;
SERVER_GLOBAL_VARIABLE( sema_lock_count ) = 0; /* We start locked for wineserver */
#if defined( RECURIVE_CRITSECION_SEMA )
- SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = wine_gettid(); /* We start locked for wineserver */
+ SERVER_GLOBAL_VARIABLE( sema_owning_pid ) = getpid();
+ SERVER_GLOBAL_VARIABLE( sema_owning_tid ) = wine_get_inprocess_tid(); /* We start locked for wineserver */
SERVER_GLOBAL_VARIABLE( sema_recursion_count ) = 1; /* We start locked for wineserver */
#endif
Index: thread.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/thread.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- thread.c 28 Mar 2007 17:52:53 -0000 1.53
+++ thread.c 30 Mar 2007 15:55:03 -0000 1.54
@@ -88,8 +88,20 @@
};
const struct object_ops* get_this_process_thread_ops(void) { return &thread_ops; }
+#ifdef __APPLE__
+typedef struct thread_port_item {
+ int unique_msg_id;
+ mach_port_t port;
+ struct thread_port_item *next;
+} thread_port_item;
+#endif
+
START_FILE_STATIC_VARIABLES(thread)
- struct thread *booting_thread;
+ struct thread *booting_thread;
+#ifdef __APPLE__
+ thread_port_item *unclaimed_ports; /* Apple: list of ports received
+ out-of-order */
+#endif
END_FILE_STATIC_VARIABLES(thread)
extern void set_debug_level( int debuglevel );
@@ -98,7 +110,10 @@
{
int i;
- thread->unix_tid = 0; /* not known yet */
+ thread->unix_tid_or_pid = 0; /* not known yet */
+#ifdef __APPLE__
+ thread->thread_port = 0;
+#endif
thread->id = INVALID_RESOURCE_ID; /* not known yet */
thread->context = NULL;
thread->teb = NULL;
@@ -262,6 +277,11 @@
thread->pollfd_array_size = 0;
thread->active_users = 0;
+#ifdef __APPLE__
+ if (thread->thread_port)
+ mach_port_deallocate (mach_task_self (), thread->thread_port);
+#endif
+
/* move important pending signals to another thread */
for (i = 0; i < MAX_SIG_CODES; i++) {
if (thread->sig_codes[i] > USC_CALLBACK) {
@@ -311,7 +331,8 @@
assert( obj->ops == thread_ops_tag );
fprintf( stderr, "Thread %04x unix tid=%d teb=%p state=%d process=%04x\n",
- get_thread_id( thread ), thread->unix_tid, thread->teb, thread->state, get_process_id( thread->process ) );
+ get_thread_id( thread ), thread->unix_tid_or_pid, thread->teb,
+ thread->state, get_process_id( thread->process ) );
}
static int thread_signaled( struct object *obj, struct wait_queue_entry *entry )
@@ -329,14 +350,6 @@
access, thread_ops_tag );
}
-/* find a thread from a Unix tid */
-struct thread *get_thread_from_tid( int tid )
-{
- struct thread *t = SERVER_GLOBAL_VARIABLE( first_thread );
- while (t && (t->unix_tid != tid)) t = t->next;
- return t;
-}
-
/* set all information about a thread */
static void set_thread_info( struct thread *thread,
const struct set_thread_info_request *req )
@@ -361,9 +374,10 @@
if (!(thread->process->suspend + thread->suspend++) &&
!(thread->sched_mode & SCDM_INTERNAL))
{
- if (!thread->wait && thread->unix_tid && !(thread->sched_mode & SCDM_BLOCKED))
+ if (!thread->wait && thread->unix_tid_or_pid &&
+ !(thread->sched_mode & SCDM_BLOCKED))
dequeue_thread(thread);
- if (thread->wait && thread->unix_tid)
+ if (thread->wait && thread->unix_tid_or_pid)
dequeue_thread_wait(thread);
stop_thread( thread );
check_wait_queue();
@@ -387,11 +401,12 @@
{
continue_thread( thread );
thread->sched_mode &= ~SCDM_CREATED_SUSPENDED;
- if (!thread->wait && thread->unix_tid && !(thread->sched_mode & SCDM_BLOCKED)) {
+ if (!thread->wait && thread->unix_tid_or_pid &&
+ !(thread->sched_mode & SCDM_BLOCKED)) {
thread_not_starved(thread);
queue_thread(thread);
}
- if (thread->wait && thread->unix_tid)
+ if (thread->wait && thread->unix_tid_or_pid)
queue_thread_wait(thread);
wake_thread( thread );
reschedule();
@@ -1001,11 +1016,11 @@
fprintf( stderr, "sig_codes array too small\n" );
}
}
- if (thread->unix_tid && !thread->sig_sent) {
- wine_tkill( thread->unix_tid, SIGUSR1 );
+ if (thread->unix_tid_or_pid && !thread->sig_sent) {
+ wine_tkill_or_kill( thread->unix_tid_or_pid, SIGUSR1 );
thread->sig_sent++;
}
- if (resume && thread->unix_tid && thread->attached) {
+ if (resume && thread->unix_tid_or_pid && thread->attached) {
/* temporarily resume a suspended thread in order to run the signal handler */
if ((thread->process->suspend + thread->suspend) > 0 &&
!(thread->sched_mode & SCDM_INTERNAL))
@@ -1066,7 +1081,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_tid)
+ if (current->unix_tid_or_pid)
{
fatal_protocol_error( current, "init_thread: already running\n" );
goto error;
@@ -1082,21 +1097,25 @@
goto error;
}
- current->unix_tid = req->unix_tid;
+ current->unix_tid_or_pid = req->unix_tid_or_pid;
current->teb = req->teb;
current->reply_fd = reply_fd;
set_context_fd( ¤t->wait_fd, wait_fd );
grab_context_fd( current->wait_fd, NULL );
current->module_status = THREAD_MODULE_INIT;
+#ifndef __APPLE__
if (current->suspend + current->process->suspend > 0) stop_thread( current );
if (current->process->running_threads > 1)
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
+#endif
reply->pid = get_process_id( current->process );
reply->tid = get_thread_id( current );
reply->boot = (current == SERVER_STATIC_VARIABLE(thread,booting_thread));
reply->version = SERVER_PROTOCOL_VERSION;
+ reply->wineserver_pid = getpid ();
+ reply->unique_msg_id = SERVER_GLOBAL_VARIABLE (unique_msg_id)++;
if ( !current->process->init_event )
initschedule(current, current->suspend + current->process->suspend);
@@ -1108,6 +1127,120 @@
if (wait_fd != -1) close( wait_fd );
}
+
+/* Apple-specific message indicating that a thread port has been sent
+ to us; we then receive it and attach it to the thread structure.
+ Note that we need to handle the (rare) case of multiple ports arriving
+ due to multiple threads having completed init_thread simultaneously */
+DECL_HANDLER(thread_port_sent)
+{
+#ifdef __APPLE__
+ mach_msg_empty_rcv_t msg;
+ thread_port_item *unclaimed_port,*last_port;
+ int updating = 0;
+
+ /* Check for already having received the msg */
+ last_port = NULL;
+ unclaimed_port = SERVER_STATIC_VARIABLE (thread, unclaimed_ports);
+ while (unclaimed_port)
+ {
+ if (unclaimed_port->unique_msg_id == req->unique_msg_id)
+ {
+ if (last_port)
+ last_port->next = unclaimed_port->next;
+ else
+ SERVER_STATIC_VARIABLE (thread, unclaimed_ports) =
+ unclaimed_port->next;
+
+ if (req->is_process)
+ current->process->task_port = unclaimed_port->port;
+ else
+ {
+ if (current->thread_port)
+ {
+ mach_port_deallocate (mach_task_self (), current->thread_port);
+ updating = 1;
+ }
+ current->thread_port = unclaimed_port->port;
+ }
+
+ free (unclaimed_port);
+ goto done;
+ }
+
+ last_port = unclaimed_port;
+ unclaimed_port = unclaimed_port->next;
+ }
+
+ /* We may receive more than one message in the case that two (or more)
+ threads are starting at the same time; we thus create a list of
+ the "unexpected" ones for now */
+ while (1)
+ {
+ msg.header.msgh_size = sizeof (mach_msg_empty_rcv_t);
+ if ((mach_msg (&msg.header, MACH_RCV_MSG, 0, msg.header.msgh_size,
+ SERVER_GLOBAL_VARIABLE (bootstrap_port),
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)) == KERN_SUCCESS)
+ {
+ if (!MACH_PORT_VALID (msg.header.msgh_remote_port))
+ {
+ fatal_protocol_error (current, "Invalid mach port received!\n");
+ goto error;
+ }
+
+ if (msg.header.msgh_id != req->unique_msg_id)
+ {
+ thread_port_item *ti = malloc (sizeof (thread_port_item));
+
+ if (!ti)
+ {
+ fatal_protocol_error (current, "malloc failure!\n");
+ goto error;
+ }
+
+ ti->unique_msg_id = msg.header.msgh_id;
+ ti->port = msg.header.msgh_remote_port;
+ ti->next = SERVER_STATIC_VARIABLE (thread, unclaimed_ports);
+ SERVER_STATIC_VARIABLE (thread, unclaimed_ports) = ti;
+ continue;
+ }
+
+ if (req->is_process)
+ current->process->task_port = msg.header.msgh_remote_port;
+ else
+ {
+ if (current->thread_port)
+ {
+ mach_port_deallocate (mach_task_self (), current->thread_port);
+ updating = 1;
+ }
+ current->thread_port = msg.header.msgh_remote_port;
+
+ }
+ break;
+ }
+ else
+ {
+ fatal_protocol_error (current, "Unable to receive mach port!\n");
+ goto error;
+ }
+ }
+
+ done:
+ if (!updating && !req->is_process)
+ {
+ if (current->suspend + current->process->suspend > 0)
+ stop_thread (current);
+ if (current->process->running_threads > 1)
+ generate_debug_event (current, CREATE_THREAD_DEBUG_EVENT, req->entry);
+ }
+
+ error:
+ return;
+#endif
+}
+
+
/* set module load status */
DECL_HANDLER(set_thread_moduleload)
{
@@ -1282,10 +1415,12 @@
DECL_HANDLER(update_thread_tid)
{
- if( current->unix_tid != req->old_unix_tid )
+ if( current->unix_tid_or_pid != req->old_unix_tid )
fatal_protocol_error( current, "Invalid tid update\n" );
- current->unix_tid = req->new_unix_tid;
+ current->unix_tid_or_pid = req->new_unix_tid;
+ reply->wineserver_pid = getpid ();
+ reply->unique_msg_id = SERVER_GLOBAL_VARIABLE (unique_msg_id)++;
}
DECL_HANDLER(send_fast_unix_signal)
Index: thread.h
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/thread.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- thread.h 28 Mar 2007 17:52:53 -0000 1.26
+++ thread.h 30 Mar 2007 15:55:03 -0000 1.27
@@ -14,6 +14,10 @@
#endif
#include "object.h"
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
+
/* thread structure */
struct process;
@@ -93,7 +97,10 @@
enum run_state state; /* running state */
int attached; /* is thread attached with ptrace? */
int exit_code; /* thread exit code */
- int unix_tid; /* Unix tid of client (may be same as pid) */
+ int unix_tid_or_pid; /* Unix tid of client (may be same as pid) */
+#ifdef __APPLE__
+ mach_port_t thread_port; /* Mach port for the thread */
+#endif
CONTEXT *context; /* current context if in an exception handler */
void *teb; /* TEB address (in client address space) */
int priority; /* priority level */
@@ -151,7 +158,6 @@
extern struct thread *create_thread( int fd, struct process *process );
extern struct thread *get_thread_from_id( const thread_id_t id );
extern struct thread *get_thread_from_handle( handle_t handle, unsigned int access );
-extern struct thread *get_thread_from_tid( int pid );
extern int suspend_thread( struct thread *thread, int check_limit );
extern int resume_thread( struct thread *thread );
extern int wake_thread( struct thread *thread );
@@ -172,13 +178,12 @@
/* ptrace functions */
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 detach_thread( struct thread *thread, int sig );
extern int suspend_for_ptrace( struct thread *thread );
extern int read_thread_data( struct thread *thread, uintptr_t addr, size_t len, void* data, size_t *num_read );
-extern int write_thread_data( struct thread *thread, uintptr_t addr, size_t len, const void* data, size_t *num_written );
+extern int write_thread_data( struct thread *thread, uintptr_t addr, size_t len, const void* data );
extern void *get_thread_ip( struct thread *thread );
extern int get_thread_single_step( struct thread *thread );
Index: trace.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/server/trace.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- trace.c 29 Mar 2007 14:03:56 -0000 1.40
+++ trace.c 30 Mar 2007 15:55:03 -0000 1.41
@@ -374,6 +374,8 @@
fprintf( stderr, " hstdout=%d,", req->hstdout );
fprintf( stderr, " hstderr=%d,", req->hstderr );
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
+ fprintf( stderr, " wineserver_pid=%d,", req->wineserver_pid );
+ fprintf( stderr, " unique_msg_id=%d,", req->unique_msg_id );
fprintf( stderr, " filename=" );
dump_varargs_string( cur_size );
}
@@ -400,7 +402,7 @@
static void dump_init_thread_request( const struct init_thread_request *req )
{
- fprintf( stderr, " unix_tid=%d,", req->unix_tid );
+ fprintf( stderr, " unix_tid_or_pid=%d,", req->unix_tid_or_pid );
fprintf( stderr, " teb=%p,", req->teb );
fprintf( stderr, " entry=%p,", req->entry );
fprintf( stderr, " reply_fd=%d,", req->reply_fd );
@@ -411,10 +413,19 @@
{
fprintf( stderr, " pid=%04u,", req->pid );
fprintf( stderr, " tid=%04u,", req->tid );
+ fprintf( stderr, " wineserver_pid=%d,", req->wineserver_pid );
+ fprintf( stderr, " unique_msg_id=%d,", req->unique_msg_id );
fprintf( stderr, " boot=%d,", req->boot );
fprintf( stderr, " version=%d", req->version );
}
+static void dump_thread_port_sent_request( const struct thread_port_sent_request *req )
+{
+ fprintf( stderr, " unique_msg_id=%d,", req->unique_msg_id );
+ fprintf( stderr, " is_process=%d,", req->is_process );
+ fprintf( stderr, " entry=%p", req->entry );
+}
+
static void dump_set_thread_moduleload_request( const struct set_thread_moduleload_request *req )
{
fprintf( stderr, " status=%d", req->status );
@@ -2168,6 +2179,12 @@
fprintf( stderr, " new_unix_tid=%d", req->new_unix_tid );
}
+static void dump_update_thread_tid_reply( const struct update_thread_tid_reply *req )
+{
+ fprintf( stderr, " wineserver_pid=%d,", req->wineserver_pid );
+ fprintf( stderr, " unique_msg_id=%d", req->unique_msg_id );
+}
+
static void dump_send_fast_unix_signal_request( const struct send_fast_unix_signal_request *req )
{
fprintf( stderr, " thread=%04u,", req->thread );
@@ -2254,6 +2271,7 @@
(dump_func)dump_init_process_request,
(dump_func)dump_init_process_done_request,
(dump_func)dump_init_thread_request,
+ (dump_func)dump_thread_port_sent_request,
(dump_func)dump_set_thread_moduleload_request,
(dump_func)dump_get_thread_moduleload_request,
(dump_func)dump_terminate_process_request,
@@ -2426,6 +2444,7 @@
(dump_func)dump_init_process_done_reply,
(dump_func)dump_init_thread_reply,
(dump_func)0,
+ (dump_func)0,
(dump_func)dump_get_thread_moduleload_reply,
(dump_func)dump_terminate_process_reply,
(dump_func)dump_terminate_thread_reply,
@@ -2577,7 +2596,7 @@
(dump_func)0,
(dump_func)0,
(dump_func)dump_resolve_rpc_endpoint_reply,
- (dump_func)0,
+ (dump_func)dump_update_thread_tid_reply,
(dump_func)0,
(dump_func)0,
(dump_func)dump_recv_unix_signal_reply,
@@ -2596,6 +2615,7 @@
"init_process",
"init_process_done",
"init_thread",
+ "thread_port_sent",
"set_thread_moduleload",
"get_thread_moduleload",
"terminate_process",
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.