WineAdoptThread

Paul Davis paul at linuxaudiosystems.com
Wed Mar 31 23:25:45 CST 2004


(this is for review by people who know better than me :)

[ some functions are replaced here by lower case versions 
  because this code is not part of dlls/ntdll/thread.c.
  consequently, we have to dlopen() that library,
  and dlsym() the functions we need. if this ever makes
  it into Wine, this will go away ]

/***********************************************************************
 *  adopt_thread - take an existing linux thread (of some kind) and make win32 aware of it
 */
int
WineAdoptThread (void)
{
    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;

    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));
	}

	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;
}



More information about the wine-devel mailing list