I should note for observers that this is part of work Paul is doing to allow WineLib to be initialized on the fly, so libwine can be dlopened and used directly.
On Thu, 01 Apr 2004 00:25:45 -0500, Paul Davis wrote:
/***********************************************************************
- adopt_thread - take an existing linux thread (of some kind) and make win32 aware of it
*/ int WineAdoptThread (void) {
Which is it - WineAdoptThread or wine_adopt_thread? :) As it's a Wine API it should be the latter, I think.
TEB *teb; void *addr; ULONG size; struct wine_pthread_thread_info thread_info; struct debug_info debug_info; int request_fd; int tid; debug_info.str_pos = debug_info.strings; debug_info.out_pos = debug_info.output; teb = shared_alloc_teb( &size ); teb->tibflags = TEBF_WIN32; teb->exit_code = STILL_ACTIVE; teb->request_fd = -1; teb->reply_fd = -1; teb->wait_fd[0] = -1; teb->wait_fd[1] = -1; teb->debug_info = &debug_info;
teb->htask16 = NtCurrentTeb()->htask16;
This line seems to be (a) a no-op, and (b) NtCurrentTeb requires %fs to be initialized which I thought happened in wine_pthread_init_current_teb()? How does this part work?
thread_info.stack_base = NULL; thread_info.stack_size = 0; thread_info.teb_base = teb; thread_info.teb_size = size; thread_info.teb_sel = teb->teb_sel; wine_pthread_init_current_teb( &thread_info ); SERVER_START_REQ( new_thread ) { size_t rsz = sizeof (*req); req->suspend = FALSE; req->inherit = 0; /* FIXME */
pthread_mutex_lock (&proxy_thread_lock);
if (write (proxy_pipe_request[1], &__req, sizeof (__req)) != sizeof (__req) || read (proxy_pipe_status[0], &__req, sizeof (__req)) != sizeof (__req) || read (proxy_pipe_status[0], &request_fd, sizeof (request_fd)) != sizeof (request_fd)) { fst_error ("cannot read/write proxy thread request (%s)", strerror (errno)); }
I guess this means you went for the butler thread approach?
pthread_mutex_unlock (&proxy_thread_lock);
if (request_fd >= 0) { tid = reply->tid; }
fst_error ("request FD for adopted thread is %d\n", request_fd);
} SERVER_END_REQ; if (request_fd < 0) goto error; teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId(); teb->ClientId.UniqueThread = (HANDLE)tid; teb->request_fd = request_fd; /* don't bother with signal initialization since we redirect all signals back to linux anyway. */ /* SIGNAL_Init(); */ /* server_*/ init_thread( thread_info.pid, thread_info.tid, NULL ); wine_pthread_init_thread( &thread_info ); /* create a memory view for the TEB */ ntallocatevm ( GetCurrentProcess(), &addr, teb, &size, MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); /* allocate a memory view for the stack */ size = thread_info.stack_size; ntallocatevm ( GetCurrentProcess(), &teb->DeallocationStack, thread_info.stack_base, &size, MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); /* limit is lower than base since the stack grows down */ teb->Tib.StackBase = (char *)thread_info.stack_base + thread_info.stack_size; teb->Tib.StackLimit = thread_info.stack_base; /* setup the guard page */ size = 1; ntprotectvm ( GetCurrentProcess(), &teb->DeallocationStack, &size, PAGE_EXECUTE_READWRITE | PAGE_GUARD, NULL ); acquirepeblock (); InsertHeadList( &tls_link_head, &teb->TlsLinks ); releasepeblock (); fprintf (stderr, "thread adopted\n"); return 0;
error: shared_free_teb (teb); /* XXX deallocate VM */ /* close thread handle */ close (request_fd); return -1; }