thread.c 34.6 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Server-side thread management
 *
 * Copyright (C) 1998 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21
#include "config.h"
22
#include "wine/port.h"
23

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <assert.h>
25
#include <errno.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
26
#include <fcntl.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <signal.h>
28
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
29 30 31
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
32
#include <sys/types.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
33
#include <unistd.h>
34
#include <time.h>
35 36 37
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
38

39 40
#include "ntstatus.h"
#define WIN32_NO_STATUS
41
#include "windef.h"
42
#include "winternl.h"
43

44
#include "file.h"
45 46 47
#include "handle.h"
#include "process.h"
#include "thread.h"
48
#include "request.h"
49
#include "user.h"
50
#include "security.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
51 52


Alexandre Julliard's avatar
Alexandre Julliard committed
53 54 55 56
/* thread queues */

struct thread_wait
{
57 58
    struct thread_wait     *next;       /* next wait structure for this thread */
    struct thread          *thread;     /* owner thread */
Alexandre Julliard's avatar
Alexandre Julliard committed
59 60
    int                     count;      /* count of objects */
    int                     flags;
61
    void                   *cookie;     /* magic cookie to return to client */
Alexandre Julliard's avatar
Alexandre Julliard committed
62
    struct timeval          timeout;
63
    struct timeout_user    *user;
Alexandre Julliard's avatar
Alexandre Julliard committed
64 65 66
    struct wait_queue_entry queues[1];
};

67 68 69 70
/* asynchronous procedure calls */

struct thread_apc
{
71
    struct list         entry;    /* queue linked list */
72 73 74 75
    struct object      *owner;    /* object that queued this apc */
    void               *func;     /* function to call in client */
    enum apc_type       type;     /* type of apc function */
    int                 nb_args;  /* number of arguments */
76 77 78
    void               *arg1;     /* function arguments */
    void               *arg2;
    void               *arg3;
79 80
};

Alexandre Julliard's avatar
Alexandre Julliard committed
81

Alexandre Julliard's avatar
Alexandre Julliard committed
82 83
/* thread operations */

Alexandre Julliard's avatar
Alexandre Julliard committed
84
static void dump_thread( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
85
static int thread_signaled( struct object *obj, struct thread *thread );
86
static unsigned int thread_map_access( struct object *obj, unsigned int access );
87
static void thread_poll_event( struct fd *fd, int event );
Alexandre Julliard's avatar
Alexandre Julliard committed
88
static void destroy_thread( struct object *obj );
89
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only );
Alexandre Julliard's avatar
Alexandre Julliard committed
90 91 92

static const struct object_ops thread_ops =
{
93 94 95 96 97 98
    sizeof(struct thread),      /* size */
    dump_thread,                /* dump */
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_signaled,            /* signaled */
    no_satisfied,               /* satisfied */
99
    no_signal,                  /* signal */
100
    no_get_fd,                  /* get_fd */
101
    thread_map_access,          /* map_access */
102
    no_lookup_name,             /* lookup_name */
103
    no_close_handle,            /* close_handle */
104 105 106 107 108
    destroy_thread              /* destroy */
};

static const struct fd_ops thread_fd_ops =
{
109 110 111 112
    NULL,                       /* get_poll_events */
    thread_poll_event,          /* poll_event */
    no_flush,                   /* flush */
    no_get_file_info,           /* get_file_info */
113 114
    no_queue_async,             /* queue_async */
    no_cancel_async             /* cancel_async */
Alexandre Julliard's avatar
Alexandre Julliard committed
115 116
};

117
static struct list thread_list = LIST_INIT(thread_list);
Alexandre Julliard's avatar
Alexandre Julliard committed
118

119 120 121 122 123
/* initialize the structure for a newly allocated thread */
inline static void init_thread_structure( struct thread *thread )
{
    int i;

124
    thread->unix_pid        = -1;  /* not known yet */
125
    thread->unix_tid        = -1;  /* not known yet */
126
    thread->context         = NULL;
127
    thread->suspend_context = NULL;
128 129 130 131 132 133
    thread->teb             = NULL;
    thread->debug_ctx       = NULL;
    thread->debug_event     = NULL;
    thread->queue           = NULL;
    thread->wait            = NULL;
    thread->error           = 0;
134 135 136 137
    thread->req_data        = NULL;
    thread->req_toread      = 0;
    thread->reply_data      = NULL;
    thread->reply_towrite   = 0;
138 139 140
    thread->request_fd      = NULL;
    thread->reply_fd        = NULL;
    thread->wait_fd         = NULL;
141 142 143 144 145 146
    thread->state           = RUNNING;
    thread->attached        = 0;
    thread->exit_code       = 0;
    thread->priority        = THREAD_PRIORITY_NORMAL;
    thread->affinity        = 1;
    thread->suspend         = 0;
147 148
    thread->creation_time   = time(NULL);
    thread->exit_time       = 0;
149
    thread->desktop_users   = 0;
150

151
    list_init( &thread->mutex_list );
152 153 154
    list_init( &thread->system_apc );
    list_init( &thread->user_apc );

155 156 157 158
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        thread->inflight[i].server = thread->inflight[i].client = -1;
}

159 160 161 162 163 164
/* check if address looks valid for a client-side data structure (TEB etc.) */
static inline int is_valid_address( void *addr )
{
    return addr && !((unsigned int)addr % sizeof(int));
}

165
/* create a new thread */
166
struct thread *create_thread( int fd, struct process *process )
167 168 169
{
    struct thread *thread;

170
    if (!(thread = alloc_object( &thread_ops ))) return NULL;
171

172
    init_thread_structure( thread );
173

174
    thread->process = (struct process *)grab_object( process );
175
    thread->desktop = process->desktop;
176 177
    if (!current) current = thread;

178
    list_add_head( &thread_list, &thread->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
179

180 181 182 183 184
    if (!(thread->id = alloc_ptid( thread )))
    {
        release_object( thread );
        return NULL;
    }
185
    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj )))
186 187 188 189
    {
        release_object( thread );
        return NULL;
    }
190

191 192
    thread->token = (struct token *) grab_object( process->token );

193
    set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
194
    add_process_thread( thread->process, thread );
195
    return thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
196 197
}

198
/* handle a client event */
199
static void thread_poll_event( struct fd *fd, int event )
200
{
201 202
    struct thread *thread = get_fd_user( fd );
    assert( thread->obj.ops == &thread_ops );
203

204
    if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
205
    else if (event & POLLIN) read_request( thread );
206
    else if (event & POLLOUT) write_reply( thread );
207 208 209 210 211 212 213 214 215 216
}

/* cleanup everything that is no longer needed by a dead thread */
/* used by destroy_thread and kill_thread */
static void cleanup_thread( struct thread *thread )
{
    int i;
    struct thread_apc *apc;

    while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
217 218
    if (thread->req_data) free( thread->req_data );
    if (thread->reply_data) free( thread->reply_data );
219 220 221
    if (thread->request_fd) release_object( thread->request_fd );
    if (thread->reply_fd) release_object( thread->reply_fd );
    if (thread->wait_fd) release_object( thread->wait_fd );
222
    if (thread->suspend_context) free( thread->suspend_context );
223
    free_msg_queue( thread );
224
    cleanup_clipboard_thread(thread);
225
    destroy_thread_windows( thread );
226
    close_thread_desktop( thread );
227 228 229 230 231 232 233 234
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
    {
        if (thread->inflight[i].client != -1)
        {
            close( thread->inflight[i].server );
            thread->inflight[i].client = thread->inflight[i].server = -1;
        }
    }
235 236
    thread->req_data = NULL;
    thread->reply_data = NULL;
237 238 239
    thread->request_fd = NULL;
    thread->reply_fd = NULL;
    thread->wait_fd = NULL;
240 241
    thread->context = NULL;
    thread->suspend_context = NULL;
242
    thread->desktop = 0;
243 244
}

Alexandre Julliard's avatar
Alexandre Julliard committed
245 246 247 248 249 250
/* destroy a thread when its refcount is 0 */
static void destroy_thread( struct object *obj )
{
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

251
    assert( !thread->debug_ctx );  /* cannot still be debugging something */
252
    list_remove( &thread->entry );
253
    cleanup_thread( thread );
254
    release_object( thread->process );
255
    if (thread->id) free_ptid( thread->id );
256
    if (thread->token) release_object( thread->token );
Alexandre Julliard's avatar
Alexandre Julliard committed
257 258
}

Alexandre Julliard's avatar
Alexandre Julliard committed
259 260 261 262 263 264
/* dump a thread on stdout for debugging purposes */
static void dump_thread( struct object *obj, int verbose )
{
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

265 266
    fprintf( stderr, "Thread id=%04x unix pid=%d unix tid=%d teb=%p state=%d\n",
             thread->id, thread->unix_pid, thread->unix_tid, thread->teb, thread->state );
Alexandre Julliard's avatar
Alexandre Julliard committed
267 268
}

Alexandre Julliard's avatar
Alexandre Julliard committed
269 270 271 272 273 274
static int thread_signaled( struct object *obj, struct thread *thread )
{
    struct thread *mythread = (struct thread *)obj;
    return (mythread->state == TERMINATED);
}

275 276 277 278 279 280 281 282 283
static unsigned int thread_map_access( struct object *obj, unsigned int access )
{
    if (access & GENERIC_READ)    access |= STANDARD_RIGHTS_READ | SYNCHRONIZE;
    if (access & GENERIC_WRITE)   access |= STANDARD_RIGHTS_WRITE | SYNCHRONIZE;
    if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
    if (access & GENERIC_ALL)     access |= THREAD_ALL_ACCESS;
    return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}

Alexandre Julliard's avatar
Alexandre Julliard committed
284
/* get a thread pointer from a thread id (and increment the refcount) */
285
struct thread *get_thread_from_id( thread_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
286
{
287 288 289
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &thread_ops) return (struct thread *)grab_object( obj );
290
    set_error( STATUS_INVALID_CID );
291
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
292 293
}

Alexandre Julliard's avatar
Alexandre Julliard committed
294
/* get a thread from a handle (and increment the refcount) */
295
struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
296
{
Alexandre Julliard's avatar
Alexandre Julliard committed
297 298
    return (struct thread *)get_handle_obj( current->process, handle,
                                            access, &thread_ops );
Alexandre Julliard's avatar
Alexandre Julliard committed
299 300
}

301 302 303
/* find a thread from a Unix pid */
struct thread *get_thread_from_pid( int pid )
{
304
    struct thread *thread;
305

306 307 308 309 310 311 312 313
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
        if (thread->unix_tid == pid) return thread;
    }
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
        if (thread->unix_pid == pid) return thread;
    }
314
    return NULL;
315 316
}

317
/* set all information about a thread */
318
static void set_thread_info( struct thread *thread,
319
                             const struct set_thread_info_request *req )
320 321 322 323 324
{
    if (req->mask & SET_THREAD_INFO_PRIORITY)
        thread->priority = req->priority;
    if (req->mask & SET_THREAD_INFO_AFFINITY)
    {
325
        if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
326 327
        else thread->affinity = req->affinity;
    }
328 329
    if (req->mask & SET_THREAD_INFO_TOKEN)
        security_set_thread_token( thread, req->token );
330 331
}

332 333 334
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
335
    if (thread->context) return;  /* already inside a debug event, no need for a signal */
336 337 338 339
    /* can't stop a thread while initialisation is in progress */
    if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
}

340
/* suspend a thread */
341
static int suspend_thread( struct thread *thread )
342 343
{
    int old_count = thread->suspend;
344
    if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
345
    {
346
        if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
347
    }
348
    else set_error( STATUS_SUSPEND_COUNT_EXCEEDED );
349 350 351 352
    return old_count;
}

/* resume a thread */
353
static int resume_thread( struct thread *thread )
354 355 356 357
{
    int old_count = thread->suspend;
    if (thread->suspend > 0)
    {
358
        if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
359 360
    }
    return old_count;
Alexandre Julliard's avatar
Alexandre Julliard committed
361 362 363
}

/* add a thread to an object wait queue; return 1 if OK, 0 on error */
364
int add_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
365
{
366
    grab_object( obj );
367 368
    entry->obj = obj;
    list_add_tail( &obj->wait_queue, &entry->entry );
369
    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
370 371 372
}

/* remove a thread from an object wait queue */
373
void remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
374
{
375
    list_remove( &entry->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
376 377 378 379 380 381 382 383 384 385 386
    release_object( obj );
}

/* finish waiting */
static void end_wait( struct thread *thread )
{
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry;
    int i;

    assert( wait );
387 388
    for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        entry->obj->ops->remove_queue( entry->obj, entry );
389
    if (wait->user) remove_timeout_user( wait->user );
390
    thread->wait = wait->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
391 392 393 394
    free( wait );
}

/* build the thread wait structure */
395
static int wait_on( int count, struct object *objects[], int flags, const abs_time_t *timeout )
Alexandre Julliard's avatar
Alexandre Julliard committed
396 397 398 399 400
{
    struct thread_wait *wait;
    struct wait_queue_entry *entry;
    int i;

Alexandre Julliard's avatar
Alexandre Julliard committed
401
    if (!(wait = mem_alloc( sizeof(*wait) + (count-1) * sizeof(*entry) ))) return 0;
402 403
    wait->next    = current->wait;
    wait->thread  = current;
Alexandre Julliard's avatar
Alexandre Julliard committed
404 405
    wait->count   = count;
    wait->flags   = flags;
406
    wait->user    = NULL;
407
    current->wait = wait;
408 409
    if (flags & SELECT_TIMEOUT)
    {
410 411
        wait->timeout.tv_sec  = timeout->sec;
        wait->timeout.tv_usec = timeout->usec;
412
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
413 414 415

    for (i = 0, entry = wait->queues; i < count; i++, entry++)
    {
416 417
        struct object *obj = objects[i];
        entry->thread = current;
418 419
        if (!obj->ops->add_queue( obj, entry ))
        {
420 421
            wait->count = i;
            end_wait( current );
422 423
            return 0;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425 426 427 428
    }
    return 1;
}

/* check if the thread waiting condition is satisfied */
429
static int check_wait( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
430
{
431
    int i, signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
432 433 434
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry = wait->queues;

435
    /* Suspended threads may not acquire locks */
436
    if (thread->process->suspend + thread->suspend > 0) return -1;
437

Alexandre Julliard's avatar
Alexandre Julliard committed
438 439 440
    assert( wait );
    if (wait->flags & SELECT_ALL)
    {
441 442 443
        int not_ok = 0;
        /* Note: we must check them all anyway, as some objects may
         * want to do something when signaled, even if others are not */
Alexandre Julliard's avatar
Alexandre Julliard committed
444
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
445 446
            not_ok |= !entry->obj->ops->signaled( entry->obj, thread );
        if (not_ok) goto other_checks;
Alexandre Julliard's avatar
Alexandre Julliard committed
447
        /* Wait satisfied: tell it to all objects */
448
        signaled = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
449 450
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
            if (entry->obj->ops->satisfied( entry->obj, thread ))
451 452
                signaled = STATUS_ABANDONED_WAIT_0;
        return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
453 454 455 456 457 458 459
    }
    else
    {
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        {
            if (!entry->obj->ops->signaled( entry->obj, thread )) continue;
            /* Wait satisfied: tell it to the object */
460
            signaled = i;
Alexandre Julliard's avatar
Alexandre Julliard committed
461
            if (entry->obj->ops->satisfied( entry->obj, thread ))
462 463
                signaled = i + STATUS_ABANDONED_WAIT_0;
            return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
464 465
        }
    }
466 467

 other_checks:
468 469
    if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty(&thread->system_apc)) return STATUS_USER_APC;
    if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
470 471 472 473
    if (wait->flags & SELECT_TIMEOUT)
    {
        struct timeval now;
        gettimeofday( &now, NULL );
474
        if (!time_before( &now, &wait->timeout )) return STATUS_TIMEOUT;
475
    }
476 477 478
    return -1;
}

479 480 481 482 483 484 485 486
/* send the wakeup signal to a thread */
static int send_thread_wakeup( struct thread *thread, void *cookie, int signaled )
{
    struct wake_up_reply reply;
    int ret;

    reply.cookie   = cookie;
    reply.signaled = signaled;
487 488
    if ((ret = write( get_unix_fd( thread->wait_fd ), &reply, sizeof(reply) )) == sizeof(reply))
        return 0;
489 490 491 492 493 494 495 496 497
    if (ret >= 0)
        fatal_protocol_error( thread, "partial wakeup write %d\n", ret );
    else if (errno == EPIPE)
        kill_thread( thread, 0 );  /* normal death */
    else
        fatal_protocol_perror( thread, "write" );
    return -1;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
498
/* attempt to wake up a thread */
499
/* return >0 if OK, 0 if the wait condition is still not satisfied */
500
int wake_thread( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
501
{
502 503
    int signaled, count;
    void *cookie;
504

505 506 507 508 509
    for (count = 0; thread->wait; count++)
    {
        if ((signaled = check_wait( thread )) == -1) break;

        cookie = thread->wait->cookie;
510 511
        if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
                                  thread->id, signaled, cookie );
512
        end_wait( thread );
513 514
        if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
	    break;
515 516
    }
    return count;
Alexandre Julliard's avatar
Alexandre Julliard committed
517 518
}

519 520 521
/* thread wait timeout */
static void thread_timeout( void *ptr )
{
522 523 524
    struct thread_wait *wait = ptr;
    struct thread *thread = wait->thread;
    void *cookie = wait->cookie;
525

526 527
    wait->user = NULL;
    if (thread->wait != wait) return; /* not the top-level wait, ignore it */
528
    if (thread->suspend + thread->process->suspend > 0) return;  /* suspended, ignore it */
529

530
    if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
531
                              thread->id, (int)STATUS_TIMEOUT, cookie );
532
    end_wait( thread );
533
    if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
534 535
    /* check if other objects have become signaled in the meantime */
    wake_thread( thread );
536 537
}

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
/* try signaling an event flag, a semaphore or a mutex */
static int signal_object( obj_handle_t handle )
{
    struct object *obj;
    int ret = 0;

    obj = get_handle_obj( current->process, handle, 0, NULL );
    if (obj)
    {
        ret = obj->ops->signal( obj, get_handle_access( current->process, handle ));
        release_object( obj );
    }
    return ret;
}

553
/* select on a list of handles */
554
static void select_on( int count, void *cookie, const obj_handle_t *handles,
555
                       int flags, const abs_time_t *timeout, obj_handle_t signal_obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
556
{
557
    int ret, i;
558
    struct object *objects[MAXIMUM_WAIT_OBJECTS];
559

560 561
    if ((count < 0) || (count > MAXIMUM_WAIT_OBJECTS))
    {
562
        set_error( STATUS_INVALID_PARAMETER );
563
        return;
564 565 566 567 568 569
    }
    for (i = 0; i < count; i++)
    {
        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
            break;
    }
570 571

    if (i < count) goto done;
572
    if (!wait_on( count, objects, flags, timeout )) goto done;
573

574 575 576 577 578 579 580 581 582 583 584 585
    /* signal the object */
    if (signal_obj)
    {
        if (!signal_object( signal_obj ))
        {
            end_wait( current );
            goto done;
        }
        /* check if we woke ourselves up */
        if (!current->wait) goto done;
    }

586 587 588 589 590 591 592 593 594 595 596 597
    if ((ret = check_wait( current )) != -1)
    {
        /* condition is already satisfied */
        end_wait( current );
        set_error( ret );
        goto done;
    }

    /* now we need to wait */
    if (flags & SELECT_TIMEOUT)
    {
        if (!(current->wait->user = add_timeout_user( &current->wait->timeout,
598
                                                      thread_timeout, current->wait )))
599 600 601 602 603
        {
            end_wait( current );
            goto done;
        }
    }
604
    current->wait->cookie = cookie;
605 606 607
    set_error( STATUS_PENDING );

done:
608
    while (--i >= 0) release_object( objects[i] );
Alexandre Julliard's avatar
Alexandre Julliard committed
609 610 611 612 613
}

/* attempt to wake threads sleeping on the object wait queue */
void wake_up( struct object *obj, int max )
{
614
    struct list *ptr, *next;
Alexandre Julliard's avatar
Alexandre Julliard committed
615

616
    LIST_FOR_EACH_SAFE( ptr, next, &obj->wait_queue )
Alexandre Julliard's avatar
Alexandre Julliard committed
617
    {
618 619
        struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
        if (wake_thread( entry->thread ))
Alexandre Julliard's avatar
Alexandre Julliard committed
620 621 622 623 624 625
        {
            if (max && !--max) break;
        }
    }
}

626
/* queue an async procedure call */
627
int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
628
                      enum apc_type type, int system, void *arg1, void *arg2, void *arg3 )
629 630
{
    struct thread_apc *apc;
631
    struct list *queue = system ? &thread->system_apc : &thread->user_apc;
632 633

    /* cancel a possible previous APC with the same owner */
634
    if (owner) thread_cancel_apc( thread, owner, system );
635
    if (thread->state == TERMINATED) return 0;
636

637 638 639 640 641 642 643
    if (!(apc = mem_alloc( sizeof(*apc) ))) return 0;
    apc->owner  = owner;
    apc->func   = func;
    apc->type   = type;
    apc->arg1   = arg1;
    apc->arg2   = arg2;
    apc->arg3   = arg3;
644 645
    list_add_tail( queue, &apc->entry );
    if (!list_prev( queue, &apc->entry ))  /* first one */
646
        wake_thread( thread );
647

648 649 650
    return 1;
}

651
/* cancel the async procedure call owned by a specific object */
652
void thread_cancel_apc( struct thread *thread, struct object *owner, int system )
653 654
{
    struct thread_apc *apc;
655 656
    struct list *queue = system ? &thread->system_apc : &thread->user_apc;
    LIST_FOR_EACH_ENTRY( apc, queue, struct thread_apc, entry )
657 658
    {
        if (apc->owner != owner) continue;
659
        list_remove( &apc->entry );
660 661 662 663 664 665
        free( apc );
        return;
    }
}

/* remove the head apc from the queue; the returned pointer must be freed by the caller */
666
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
667
{
668 669
    struct thread_apc *apc = NULL;
    struct list *ptr = list_head( &thread->system_apc );
670

671 672
    if (!ptr && !system_only) ptr = list_head( &thread->user_apc );
    if (ptr)
673
    {
674 675
        apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( ptr );
676 677 678 679
    }
    return apc;
}

680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
/* add an fd to the inflight list */
/* return list index, or -1 on error */
int thread_add_inflight_fd( struct thread *thread, int client, int server )
{
    int i;

    if (server == -1) return -1;
    if (client == -1)
    {
        close( server );
        return -1;
    }

    /* first check if we already have an entry for this fd */
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        if (thread->inflight[i].client == client)
        {
            close( thread->inflight[i].server );
            thread->inflight[i].server = server;
            return i;
        }

    /* now find a free spot to store it */
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        if (thread->inflight[i].client == -1)
        {
            thread->inflight[i].client = client;
            thread->inflight[i].server = server;
            return i;
        }
    return -1;
}

/* get an inflight fd and purge it from the list */
/* the fd must be closed when no longer used */
int thread_get_inflight_fd( struct thread *thread, int client )
{
    int i, ret;

    if (client == -1) return -1;

    do
    {
        for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        {
            if (thread->inflight[i].client == client)
            {
                ret = thread->inflight[i].server;
                thread->inflight[i].server = thread->inflight[i].client = -1;
                return ret;
            }
        }
    } while (!receive_fd( thread->process ));  /* in case it is still in the socket buffer */
    return -1;
}

736 737 738 739 740
/* retrieve an LDT selector entry */
static void get_selector_entry( struct thread *thread, int entry,
                                unsigned int *base, unsigned int *limit,
                                unsigned char *flags )
{
741
    if (!thread->process->ldt_copy)
742 743 744 745 746 747 748 749 750
    {
        set_error( STATUS_ACCESS_DENIED );
        return;
    }
    if (entry >= 8192)
    {
        set_error( STATUS_INVALID_PARAMETER );  /* FIXME */
        return;
    }
751
    if (suspend_for_ptrace( thread ))
752 753
    {
        unsigned char flags_buf[4];
754
        int *addr = (int *)thread->process->ldt_copy + entry;
755 756
        if (read_thread_int( thread, addr, (int *)base ) == -1) goto done;
        if (read_thread_int( thread, addr + 8192, (int *)limit ) == -1) goto done;
757
        addr = (int *)thread->process->ldt_copy + 2*8192 + (entry >> 2);
758 759
        if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
        *flags = flags_buf[entry & 3];
760
    done:
761
        resume_after_ptrace( thread );
762 763 764
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
765
/* kill a thread on the spot */
766
void kill_thread( struct thread *thread, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
767
{
Alexandre Julliard's avatar
Alexandre Julliard committed
768
    if (thread->state == TERMINATED) return;  /* already killed */
Alexandre Julliard's avatar
Alexandre Julliard committed
769
    thread->state = TERMINATED;
770
    thread->exit_time = time(NULL);
771
    if (current == thread) current = NULL;
772
    if (debug_level)
773 774
        fprintf( stderr,"%04x: *killed* exit_code=%d\n",
                 thread->id, thread->exit_code );
775 776
    if (thread->wait)
    {
777 778
        while (thread->wait) end_wait( thread );
        send_thread_wakeup( thread, NULL, STATUS_PENDING );
779 780 781
        /* if it is waiting on the socket, we don't need to send a SIGTERM */
        violent_death = 0;
    }
782
    kill_console_processes( thread, 0 );
783
    debug_exit_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
784
    abandon_mutexes( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
785
    wake_up( &thread->obj, 0 );
786
    if (violent_death) send_thread_signal( thread, SIGTERM );
787
    cleanup_thread( thread );
788
    remove_process_thread( thread->process, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
789
    release_object( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
790
}
791

792 793 794 795 796 797 798
/* take a snapshot of currently running threads */
struct thread_snapshot *thread_snap( int *count )
{
    struct thread_snapshot *snapshot, *ptr;
    struct thread *thread;
    int total = 0;

799
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
800 801 802
        if (thread->state != TERMINATED) total++;
    if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
    ptr = snapshot;
803
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
804 805 806 807 808 809 810 811 812 813 814 815
    {
        if (thread->state == TERMINATED) continue;
        ptr->thread   = thread;
        ptr->count    = thread->obj.refcount;
        ptr->priority = thread->priority;
        grab_object( thread );
        ptr++;
    }
    *count = total;
    return snapshot;
}

816 817 818 819 820 821 822 823 824
/* gets the current impersonation token */
struct token *thread_get_impersonation_token( struct thread *thread )
{
    if (thread->token)
        return thread->token;
    else
        return thread->process->token;
}

825 826 827
/* create a new thread */
DECL_HANDLER(new_thread)
{
828
    struct thread *thread;
829
    int request_fd = thread_get_inflight_fd( current, req->request_fd );
830

831
    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
832
    {
833
        if (request_fd != -1) close( request_fd );
834 835 836 837 838 839 840
        set_error( STATUS_INVALID_HANDLE );
        return;
    }

    if ((thread = create_thread( request_fd, current->process )))
    {
        if (req->suspend) thread->suspend++;
841
        reply->tid = get_thread_id( thread );
842
        if ((reply->handle = alloc_handle( current->process, thread, req->access, req->attributes )))
843
        {
844 845
            /* thread object will be released when the thread gets killed */
            return;
846
        }
847
        kill_thread( thread, 1 );
848 849 850 851 852 853
    }
}

/* initialize a new thread */
DECL_HANDLER(init_thread)
{
854
    struct process *process = current->process;
855 856 857
    int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
    int wait_fd = thread_get_inflight_fd( current, req->wait_fd );

858
    if (current->unix_pid != -1)
859
    {
860
        fatal_protocol_error( current, "init_thread: already running\n" );
861 862
        goto error;
    }
863
    if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1)
864 865 866 867 868 869 870 871
    {
        fatal_protocol_error( current, "bad reply fd\n" );
        goto error;
    }
    if (wait_fd == -1)
    {
        fatal_protocol_error( current, "bad wait fd\n" );
        goto error;
872
    }
873 874 875 876 877 878 879 880
    if (!(current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj )))
    {
        reply_fd = -1;
        fatal_protocol_error( current, "could not allocate reply fd\n" );
        goto error;
    }
    if (!(current->wait_fd  = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj )))
        return;
881

882 883 884 885 886 887
    if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }

888
    current->unix_pid = req->unix_pid;
889
    current->unix_tid = req->unix_tid;
890
    current->teb      = req->teb;
891

892 893 894 895
    if (!process->peb)  /* first thread, initialize the process too */
    {
        process->peb      = req->peb;
        process->ldt_copy = req->ldt_copy;
896
        reply->info_size  = init_process( current );
897 898 899 900
    }
    else
    {
        if (current->suspend + process->suspend > 0) stop_thread( current );
901
        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
902 903
    }
    debug_level = max( debug_level, req->debug_level );
904

905
    reply->pid     = get_process_id( process );
906 907
    reply->tid     = get_thread_id( current );
    reply->version = SERVER_PROTOCOL_VERSION;
908
    reply->server_start = server_start_time;
909 910 911 912 913 914 915
    return;

 error:
    if (reply_fd != -1) close( reply_fd );
    if (wait_fd != -1) close( wait_fd );
}

916 917 918 919 920
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
    struct thread *thread;

921 922
    reply->self = 0;
    reply->last = 0;
923 924
    if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
    {
925 926 927 928
        thread->exit_code = req->exit_code;
        if (thread != current) kill_thread( thread, 1 );
        else
        {
929 930
            reply->self = 1;
            reply->last = (thread->process->running_threads == 1);
931
        }
932 933 934 935
        release_object( thread );
    }
}

936 937 938 939 940 941 942 943
/* open a handle to a thread */
DECL_HANDLER(open_thread)
{
    struct thread *thread = get_thread_from_id( req->tid );

    reply->handle = 0;
    if (thread)
    {
944
        reply->handle = alloc_handle( current->process, thread, req->access, req->attributes );
945 946 947 948
        release_object( thread );
    }
}

949 950 951 952
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
    struct thread *thread;
953
    obj_handle_t handle = req->handle;
954

955
    if (!handle) thread = get_thread_from_id( req->tid_in );
956 957 958
    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );

    if (thread)
959
    {
960
        reply->pid            = get_process_id( thread->process );
961 962 963 964
        reply->tid            = get_thread_id( thread );
        reply->teb            = thread->teb;
        reply->exit_code      = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
        reply->priority       = thread->priority;
965
        reply->affinity       = thread->affinity;
966 967 968
        reply->creation_time  = thread->creation_time;
        reply->exit_time      = thread->exit_time;

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
        release_object( thread );
    }
}

/* set information about a thread */
DECL_HANDLER(set_thread_info)
{
    struct thread *thread;

    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
    {
        set_thread_info( thread, req );
        release_object( thread );
    }
}

/* suspend a thread */
DECL_HANDLER(suspend_thread)
{
    struct thread *thread;
989

990 991
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
992
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
993
        else reply->count = suspend_thread( thread );
994 995 996 997 998 999 1000 1001
        release_object( thread );
    }
}

/* resume a thread */
DECL_HANDLER(resume_thread)
{
    struct thread *thread;
1002

1003 1004
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1005 1006
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
        else reply->count = resume_thread( thread );
1007 1008 1009 1010 1011 1012 1013
        release_object( thread );
    }
}

/* select on a handle list */
DECL_HANDLER(select)
{
1014
    int count = get_req_data_size() / sizeof(int);
1015
    select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout, req->signal );
1016 1017 1018 1019 1020 1021 1022 1023
}

/* queue an APC for a thread */
DECL_HANDLER(queue_apc)
{
    struct thread *thread;
    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
    {
1024 1025
        thread_queue_apc( thread, NULL, req->func, APC_USER, !req->user,
                          req->arg1, req->arg2, req->arg3 );
1026 1027 1028
        release_object( thread );
    }
}
1029

1030 1031
/* get next APC to call */
DECL_HANDLER(get_apc)
1032
{
1033 1034
    struct thread_apc *apc;

1035
    for (;;)
1036
    {
1037
        if (!(apc = thread_dequeue_apc( current, !req->alertable )))
1038 1039
        {
            /* no more APCs */
1040 1041
            reply->func = NULL;
            reply->type = APC_NONE;
1042 1043 1044 1045
            return;
        }
        /* Optimization: ignore APCs that have a NULL func; they are only used
         * to wake up a thread, but since we got here the thread woke up already.
1046
         * Exception: for APC_ASYNC_IO, func == NULL is legal.
1047
         */
1048
        if (apc->func || apc->type == APC_ASYNC_IO) break;
1049 1050
        free( apc );
    }
1051 1052
    reply->func = apc->func;
    reply->type = apc->type;
1053 1054 1055
    reply->arg1 = apc->arg1;
    reply->arg2 = apc->arg2;
    reply->arg3 = apc->arg3;
1056
    free( apc );
1057
}
1058

1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{
    struct thread *thread;
    void *data;

    if (get_reply_max_size() < sizeof(CONTEXT))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;

1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    if (req->suspend)
    {
        if (thread != current || !thread->suspend_context)
        {
            /* not suspended, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else
        {
            if (thread->context == thread->suspend_context) thread->context = NULL;
            set_reply_data_ptr( thread->suspend_context, sizeof(CONTEXT) );
            thread->suspend_context = NULL;
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
    else if ((data = set_reply_data_size( sizeof(CONTEXT) )))
1093 1094 1095 1096
    {
        memset( data, 0, sizeof(CONTEXT) );
        get_thread_context( thread, data, req->flags );
    }
1097
    reply->self = (thread == current);
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    release_object( thread );
}

/* set the current context of a thread */
DECL_HANDLER(set_thread_context)
{
    struct thread *thread;

    if (get_req_data_size() < sizeof(CONTEXT))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
    if (!(thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) return;

    if (req->suspend)
    {
        if (thread != current || thread->context)
        {
            /* nested suspend or exception, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else if ((thread->suspend_context = mem_alloc( sizeof(CONTEXT) )))
        {
            memcpy( thread->suspend_context, get_req_data(), sizeof(CONTEXT) );
            thread->context = thread->suspend_context;
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
    else
1133 1134 1135
    {
        set_thread_context( thread, get_req_data(), req->flags );
    }
1136
    reply->self = (thread == current);
1137
    release_object( thread );
1138 1139
}

1140 1141 1142 1143 1144 1145
/* fetch a selector entry for a thread */
DECL_HANDLER(get_selector_entry)
{
    struct thread *thread;
    if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
    {
1146
        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
1147 1148 1149
        release_object( thread );
    }
}