thread.c 28 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5 6
/*
 * Server-side thread management
 *
 * Copyright (C) 1998 Alexandre Julliard
 */

7 8
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
9
#include <assert.h>
10
#include <errno.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
11
#include <fcntl.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
12
#include <signal.h>
13
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
14 15 16
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
17
#include <sys/types.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
18
#include <unistd.h>
19
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
20

21
#include "winbase.h"
22 23 24 25

#include "handle.h"
#include "process.h"
#include "thread.h"
26
#include "request.h"
27
#include "user.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
28 29


Alexandre Julliard's avatar
Alexandre Julliard committed
30 31 32 33
/* thread queues */

struct thread_wait
{
34 35
    struct thread_wait     *next;       /* next wait structure for this thread */
    struct thread          *thread;     /* owner thread */
Alexandre Julliard's avatar
Alexandre Julliard committed
36 37
    int                     count;      /* count of objects */
    int                     flags;
38
    void                   *cookie;     /* magic cookie to return to client */
Alexandre Julliard's avatar
Alexandre Julliard committed
39
    struct timeval          timeout;
40
    struct timeout_user    *user;
Alexandre Julliard's avatar
Alexandre Julliard committed
41 42 43
    struct wait_queue_entry queues[1];
};

44 45 46 47
/* asynchronous procedure calls */

struct thread_apc
{
48 49 50 51 52 53 54
    struct thread_apc  *next;     /* queue linked list */
    struct thread_apc  *prev;
    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 */
    void               *args[1];  /* function arguments */
55 56
};

Alexandre Julliard's avatar
Alexandre Julliard committed
57

Alexandre Julliard's avatar
Alexandre Julliard committed
58 59
/* thread operations */

Alexandre Julliard's avatar
Alexandre Julliard committed
60
static void dump_thread( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
61
static int thread_signaled( struct object *obj, struct thread *thread );
62
static void thread_poll_event( struct object *obj, int event );
Alexandre Julliard's avatar
Alexandre Julliard committed
63
static void destroy_thread( struct object *obj );
64
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only );
Alexandre Julliard's avatar
Alexandre Julliard committed
65 66 67

static const struct object_ops thread_ops =
{
68 69 70 71 72 73 74 75
    sizeof(struct thread),      /* size */
    dump_thread,                /* dump */
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_signaled,            /* signaled */
    no_satisfied,               /* satisfied */
    NULL,                       /* get_poll_events */
    thread_poll_event,          /* poll_event */
76
    no_get_fd,                  /* get_fd */
77 78
    no_flush,                   /* flush */
    no_get_file_info,           /* get_file_info */
79
    NULL,                       /* queue_async */
80
    destroy_thread              /* destroy */
Alexandre Julliard's avatar
Alexandre Julliard committed
81 82
};

83
static struct thread *first_thread;
84
static struct thread *booting_thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
85

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/* initialize the structure for a newly allocated thread */
inline static void init_thread_structure( struct thread *thread )
{
    int i;

    thread->unix_pid        = 0;  /* not known yet */
    thread->context         = NULL;
    thread->teb             = NULL;
    thread->mutex           = NULL;
    thread->debug_ctx       = NULL;
    thread->debug_event     = NULL;
    thread->queue           = NULL;
    thread->info            = NULL;
    thread->wait            = NULL;
    thread->system_apc.head = NULL;
    thread->system_apc.tail = NULL;
    thread->user_apc.head   = NULL;
    thread->user_apc.tail   = NULL;
    thread->error           = 0;
105 106 107 108
    thread->req_data        = NULL;
    thread->req_toread      = 0;
    thread->reply_data      = NULL;
    thread->reply_towrite   = 0;
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    thread->reply_fd        = -1;
    thread->wait_fd         = -1;
    thread->state           = RUNNING;
    thread->attached        = 0;
    thread->exit_code       = 0;
    thread->next            = NULL;
    thread->prev            = NULL;
    thread->priority        = THREAD_PRIORITY_NORMAL;
    thread->affinity        = 1;
    thread->suspend         = 0;

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

124
/* create a new thread */
125
struct thread *create_thread( int fd, struct process *process )
126 127 128
{
    struct thread *thread;

129
    if (!(thread = alloc_object( &thread_ops, fd ))) return NULL;
130

131
    init_thread_structure( thread );
132

133
    thread->process = (struct process *)grab_object( process );
134
    thread->request_fd = fd;
135 136 137
    if (!current) current = thread;

    if (!booting_thread)  /* first thread ever */
Alexandre Julliard's avatar
Alexandre Julliard committed
138
    {
139 140
        booting_thread = thread;
        lock_master_socket(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
141
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
142

143
    if ((thread->next = first_thread) != NULL) thread->next->prev = thread;
144
    first_thread = thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
145

146
    set_select_events( &thread->obj, POLLIN );  /* start listening to events */
147
    add_process_thread( thread->process, thread );
148
    return thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
149 150
}

151
/* handle a client event */
152
static void thread_poll_event( struct object *obj, int event )
153 154 155 156
{
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

157
    if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
158
    else if (event & POLLIN) read_request( thread );
159
    else if (event & POLLOUT) write_reply( thread );
160 161 162 163 164 165 166 167 168 169
}

/* 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 );
170 171 172
    if (thread->req_data) free( thread->req_data );
    if (thread->reply_data) free( thread->reply_data );
    if (thread->request_fd != -1) close( thread->request_fd );
173 174
    if (thread->reply_fd != -1) close( thread->reply_fd );
    if (thread->wait_fd != -1) close( thread->wait_fd );
175 176 177 178 179 180 181 182 183 184
    if (thread->queue)
    {
        if (thread->process->queue == thread->queue)
        {
            release_object( thread->process->queue );
            thread->process->queue = NULL;
        }
        release_object( thread->queue );
        thread->queue = NULL;
    }
185
    destroy_thread_windows( thread );
186 187 188 189 190 191 192 193
    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;
        }
    }
194 195 196
    thread->req_data = NULL;
    thread->reply_data = NULL;
    thread->request_fd = -1;
197 198
    thread->reply_fd = -1;
    thread->wait_fd = -1;
199 200
}

Alexandre Julliard's avatar
Alexandre Julliard committed
201 202 203
/* destroy a thread when its refcount is 0 */
static void destroy_thread( struct object *obj )
{
204
    struct thread_apc *apc;
Alexandre Julliard's avatar
Alexandre Julliard committed
205 206 207
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

208
    assert( !thread->debug_ctx );  /* cannot still be debugging something */
Alexandre Julliard's avatar
Alexandre Julliard committed
209 210 211
    if (thread->next) thread->next->prev = thread->prev;
    if (thread->prev) thread->prev->next = thread->next;
    else first_thread = thread->next;
212
    while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
213
    if (thread->info) release_object( thread->info );
214
    cleanup_thread( thread );
215
    release_object( thread->process );
Alexandre Julliard's avatar
Alexandre Julliard committed
216 217
}

Alexandre Julliard's avatar
Alexandre Julliard committed
218 219 220 221 222 223
/* 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 );

224 225
    fprintf( stderr, "Thread pid=%d teb=%p state=%d\n",
             thread->unix_pid, thread->teb, thread->state );
Alexandre Julliard's avatar
Alexandre Julliard committed
226 227
}

Alexandre Julliard's avatar
Alexandre Julliard committed
228 229 230 231 232 233
static int thread_signaled( struct object *obj, struct thread *thread )
{
    struct thread *mythread = (struct thread *)obj;
    return (mythread->state == TERMINATED);
}

Alexandre Julliard's avatar
Alexandre Julliard committed
234
/* get a thread pointer from a thread id (and increment the refcount) */
Alexandre Julliard's avatar
Alexandre Julliard committed
235 236 237 238
struct thread *get_thread_from_id( void *id )
{
    struct thread *t = first_thread;
    while (t && (t != id)) t = t->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
239
    if (t) grab_object( t );
240
    else set_error( STATUS_INVALID_PARAMETER );
Alexandre Julliard's avatar
Alexandre Julliard committed
241 242 243
    return t;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
244
/* get a thread from a handle (and increment the refcount) */
245
struct thread *get_thread_from_handle( handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
246
{
Alexandre Julliard's avatar
Alexandre Julliard committed
247 248
    return (struct thread *)get_handle_obj( current->process, handle,
                                            access, &thread_ops );
Alexandre Julliard's avatar
Alexandre Julliard committed
249 250
}

251 252 253 254 255 256 257 258
/* find a thread from a Unix pid */
struct thread *get_thread_from_pid( int pid )
{
    struct thread *t = first_thread;
    while (t && (t->unix_pid != pid)) t = t->next;
    return t;
}

259
/* set all information about a thread */
260
static void set_thread_info( struct thread *thread,
261
                             const struct set_thread_info_request *req )
262 263 264 265 266
{
    if (req->mask & SET_THREAD_INFO_PRIORITY)
        thread->priority = req->priority;
    if (req->mask & SET_THREAD_INFO_AFFINITY)
    {
267
        if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
268 269 270 271 272
        else thread->affinity = req->affinity;
    }
}

/* suspend a thread */
273
int suspend_thread( struct thread *thread, int check_limit )
274 275
{
    int old_count = thread->suspend;
276
    if (thread->suspend < MAXIMUM_SUSPEND_COUNT || !check_limit)
277
    {
278
        if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
279
    }
280
    else set_error( STATUS_SUSPEND_COUNT_EXCEEDED );
281 282 283 284
    return old_count;
}

/* resume a thread */
285
int resume_thread( struct thread *thread )
286 287 288 289
{
    int old_count = thread->suspend;
    if (thread->suspend > 0)
    {
290
        if (!(--thread->suspend + thread->process->suspend)) continue_thread( thread );
291 292
    }
    return old_count;
Alexandre Julliard's avatar
Alexandre Julliard committed
293 294 295
}

/* add a thread to an object wait queue; return 1 if OK, 0 on error */
296
int add_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
297
{
298
    grab_object( obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
299 300 301 302 303 304
    entry->obj    = obj;
    entry->prev   = obj->tail;
    entry->next   = NULL;
    if (obj->tail) obj->tail->next = entry;
    else obj->head = entry;
    obj->tail = entry;
305
    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
306 307 308
}

/* remove a thread from an object wait queue */
309
void remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
{
    if (entry->next) entry->next->prev = entry->prev;
    else obj->tail = entry->prev;
    if (entry->prev) entry->prev->next = entry->next;
    else obj->head = entry->next;
    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 );
326 327
    for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        entry->obj->ops->remove_queue( entry->obj, entry );
328
    if (wait->user) remove_timeout_user( wait->user );
329
    thread->wait = wait->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
330 331 332 333
    free( wait );
}

/* build the thread wait structure */
334
static int wait_on( int count, struct object *objects[], int flags, int sec, int usec )
Alexandre Julliard's avatar
Alexandre Julliard committed
335 336 337 338 339
{
    struct thread_wait *wait;
    struct wait_queue_entry *entry;
    int i;

Alexandre Julliard's avatar
Alexandre Julliard committed
340
    if (!(wait = mem_alloc( sizeof(*wait) + (count-1) * sizeof(*entry) ))) return 0;
341 342
    wait->next    = current->wait;
    wait->thread  = current;
Alexandre Julliard's avatar
Alexandre Julliard committed
343 344
    wait->count   = count;
    wait->flags   = flags;
345
    wait->user    = NULL;
346
    current->wait = wait;
347 348
    if (flags & SELECT_TIMEOUT)
    {
349 350
        wait->timeout.tv_sec = sec;
        wait->timeout.tv_usec = usec;
351
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
352 353 354

    for (i = 0, entry = wait->queues; i < count; i++, entry++)
    {
355 356
        struct object *obj = objects[i];
        entry->thread = current;
357 358
        if (!obj->ops->add_queue( obj, entry ))
        {
359 360
            wait->count = i;
            end_wait( current );
361 362
            return 0;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
363 364 365 366 367
    }
    return 1;
}

/* check if the thread waiting condition is satisfied */
368
static int check_wait( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
369
{
370
    int i, signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
371 372 373 374 375 376
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry = wait->queues;

    assert( wait );
    if (wait->flags & SELECT_ALL)
    {
377 378 379
        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
380
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
381 382
            not_ok |= !entry->obj->ops->signaled( entry->obj, thread );
        if (not_ok) goto other_checks;
Alexandre Julliard's avatar
Alexandre Julliard committed
383
        /* Wait satisfied: tell it to all objects */
384
        signaled = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
385 386
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
            if (entry->obj->ops->satisfied( entry->obj, thread ))
387 388
                signaled = STATUS_ABANDONED_WAIT_0;
        return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
389 390 391 392 393 394 395
    }
    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 */
396
            signaled = i;
Alexandre Julliard's avatar
Alexandre Julliard committed
397
            if (entry->obj->ops->satisfied( entry->obj, thread ))
398 399
                signaled = i + STATUS_ABANDONED_WAIT_0;
            return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
400 401
        }
    }
402 403

 other_checks:
404 405
    if ((wait->flags & SELECT_INTERRUPTIBLE) && thread->system_apc.head) return STATUS_USER_APC;
    if ((wait->flags & SELECT_ALERTABLE) && thread->user_apc.head) return STATUS_USER_APC;
406 407 408 409
    if (wait->flags & SELECT_TIMEOUT)
    {
        struct timeval now;
        gettimeofday( &now, NULL );
410
        if (!time_before( &now, &wait->timeout )) return STATUS_TIMEOUT;
411
    }
412 413 414
    return -1;
}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
/* 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;
    if ((ret = write( thread->wait_fd, &reply, sizeof(reply) )) == sizeof(reply)) return 0;
    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
433
/* attempt to wake up a thread */
434
/* return >0 if OK, 0 if the wait condition is still not satisfied */
Alexandre Julliard's avatar
Alexandre Julliard committed
435 436
static int wake_thread( struct thread *thread )
{
437 438
    int signaled, count;
    void *cookie;
439

440 441 442 443 444 445 446 447
    for (count = 0; thread->wait; count++)
    {
        if ((signaled = check_wait( thread )) == -1) break;

        cookie = thread->wait->cookie;
        if (debug_level) fprintf( stderr, "%08x: *wakeup* signaled=%d cookie=%p\n",
                                  (unsigned int)thread, signaled, cookie );
        end_wait( thread );
448 449
        if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
	    break;
450 451
    }
    return count;
Alexandre Julliard's avatar
Alexandre Julliard committed
452 453
}

454 455 456
/* thread wait timeout */
static void thread_timeout( void *ptr )
{
457 458 459
    struct thread_wait *wait = ptr;
    struct thread *thread = wait->thread;
    void *cookie = wait->cookie;
460

461 462
    wait->user = NULL;
    if (thread->wait != wait) return; /* not the top-level wait, ignore it */
463

464 465
    if (debug_level) fprintf( stderr, "%08x: *wakeup* signaled=%d cookie=%p\n",
                              (unsigned int)thread, STATUS_TIMEOUT, cookie );
466
    end_wait( thread );
467 468 469
    send_thread_wakeup( thread, cookie, STATUS_TIMEOUT );
    /* check if other objects have become signaled in the meantime */
    wake_thread( thread );
470 471
}

472
/* select on a list of handles */
473 474
static void select_on( int count, void *cookie, const handle_t *handles,
                       int flags, int sec, int usec )
Alexandre Julliard's avatar
Alexandre Julliard committed
475
{
476
    int ret, i;
477
    struct object *objects[MAXIMUM_WAIT_OBJECTS];
478

479 480
    if ((count < 0) || (count > MAXIMUM_WAIT_OBJECTS))
    {
481
        set_error( STATUS_INVALID_PARAMETER );
482
        return;
483 484 485 486 487 488
    }
    for (i = 0; i < count; i++)
    {
        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
            break;
    }
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504

    if (i < count) goto done;
    if (!wait_on( count, objects, flags, sec, usec )) goto done;

    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,
505
                                                      thread_timeout, current->wait )))
506 507 508 509 510
        {
            end_wait( current );
            goto done;
        }
    }
511
    current->wait->cookie = cookie;
512 513 514
    set_error( STATUS_PENDING );

done:
515
    while (--i >= 0) release_object( objects[i] );
Alexandre Julliard's avatar
Alexandre Julliard committed
516 517 518 519 520 521 522 523 524
}

/* attempt to wake threads sleeping on the object wait queue */
void wake_up( struct object *obj, int max )
{
    struct wait_queue_entry *entry = obj->head;

    while (entry)
    {
525 526 527
        struct thread *thread = entry->thread;
        entry = entry->next;
        if (wake_thread( thread ))
Alexandre Julliard's avatar
Alexandre Julliard committed
528 529 530 531 532 533
        {
            if (max && !--max) break;
        }
    }
}

534
/* queue an async procedure call */
535
int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
536
                      enum apc_type type, int system, int nb_args, ... )
537 538
{
    struct thread_apc *apc;
539
    struct apc_queue *queue = system ? &thread->system_apc : &thread->user_apc;
540 541

    /* cancel a possible previous APC with the same owner */
542
    if (owner) thread_cancel_apc( thread, owner, system );
543 544

    if (!(apc = mem_alloc( sizeof(*apc) + (nb_args-1)*sizeof(apc->args[0]) ))) return 0;
545
    apc->prev    = queue->tail;
546 547 548 549 550 551
    apc->next    = NULL;
    apc->owner   = owner;
    apc->func    = func;
    apc->type    = type;
    apc->nb_args = nb_args;
    if (nb_args)
552
    {
553 554 555 556 557
        int i;
        va_list args;
        va_start( args, nb_args );
        for (i = 0; i < nb_args; i++) apc->args[i] = va_arg( args, void * );
        va_end( args );
558
    }
559
    queue->tail = apc;
560
    if (!apc->prev)  /* first one */
561
    {
562
        queue->head = apc;
563
        wake_thread( thread );
564
    }
565 566
    else apc->prev->next = apc;

567 568 569
    return 1;
}

570
/* cancel the async procedure call owned by a specific object */
571
void thread_cancel_apc( struct thread *thread, struct object *owner, int system )
572 573
{
    struct thread_apc *apc;
574 575
    struct apc_queue *queue = system ? &thread->system_apc : &thread->user_apc;
    for (apc = queue->head; apc; apc = apc->next)
576 577 578
    {
        if (apc->owner != owner) continue;
        if (apc->next) apc->next->prev = apc->prev;
579
        else queue->tail = apc->prev;
580
        if (apc->prev) apc->prev->next = apc->next;
581
        else queue->head = apc->next;
582 583 584 585 586 587
        free( apc );
        return;
    }
}

/* remove the head apc from the queue; the returned pointer must be freed by the caller */
588
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
589
{
590 591 592 593 594
    struct thread_apc *apc;
    struct apc_queue *queue = &thread->system_apc;

    if (!queue->head && !system_only) queue = &thread->user_apc;
    if ((apc = queue->head))
595 596
    {
        if (apc->next) apc->next->prev = NULL;
597 598
        else queue->tail = NULL;
        queue->head = apc->next;
599 600 601 602
    }
    return apc;
}

603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
/* 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;
}

659 660 661 662 663
/* retrieve an LDT selector entry */
static void get_selector_entry( struct thread *thread, int entry,
                                unsigned int *base, unsigned int *limit,
                                unsigned char *flags )
{
664
    if (!thread->process->ldt_copy)
665 666 667 668 669 670 671 672 673
    {
        set_error( STATUS_ACCESS_DENIED );
        return;
    }
    if (entry >= 8192)
    {
        set_error( STATUS_INVALID_PARAMETER );  /* FIXME */
        return;
    }
674
    if (suspend_for_ptrace( thread ))
675 676
    {
        unsigned char flags_buf[4];
677
        int *addr = (int *)thread->process->ldt_copy + entry;
678
        if (read_thread_int( thread, addr, base ) == -1) goto done;
679 680
        if (read_thread_int( thread, addr + 8192, limit ) == -1) goto done;
        addr = (int *)thread->process->ldt_copy + 2*8192 + (entry >> 2);
681 682
        if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
        *flags = flags_buf[entry & 3];
683 684
    done:
        resume_thread( thread );
685 686 687
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
688
/* kill a thread on the spot */
689
void kill_thread( struct thread *thread, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
690
{
Alexandre Julliard's avatar
Alexandre Julliard committed
691
    if (thread->state == TERMINATED) return;  /* already killed */
Alexandre Julliard's avatar
Alexandre Julliard committed
692
    thread->state = TERMINATED;
693
    if (current == thread) current = NULL;
694
    if (debug_level)
695 696 697 698
        fprintf( stderr,"%08x: *killed* exit_code=%d\n",
                 (unsigned int)thread, thread->exit_code );
    if (thread->wait)
    {
699 700
        while (thread->wait) end_wait( thread );
        send_thread_wakeup( thread, NULL, STATUS_PENDING );
701 702 703
        /* if it is waiting on the socket, we don't need to send a SIGTERM */
        violent_death = 0;
    }
704
    kill_console_processes( thread, 0 );
705
    debug_exit_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
706
    abandon_mutexes( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
707
    remove_process_thread( thread->process, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
708
    wake_up( &thread->obj, 0 );
709
    detach_thread( thread, violent_death ? SIGTERM : 0 );
710 711
    if (thread->request_fd == thread->obj.fd) thread->request_fd = -1;
    if (thread->reply_fd == thread->obj.fd) thread->reply_fd = -1;
712
    remove_select_user( &thread->obj );
713
    cleanup_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
714
    release_object( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
715
}
716

717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
/* 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;

    for (thread = first_thread; thread; thread = thread->next)
        if (thread->state != TERMINATED) total++;
    if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
    ptr = snapshot;
    for (thread = first_thread; thread; thread = thread->next)
    {
        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;
}

741 742 743
/* signal that we are finished booting on the client side */
DECL_HANDLER(boot_done)
{
744
    debug_level = max( debug_level, req->debug_level );
745 746 747 748 749 750 751
    if (current == booting_thread)
    {
        booting_thread = (struct thread *)~0UL;  /* make sure it doesn't match other threads */
        lock_master_socket(0);  /* allow other clients now */
    }
}

752 753 754
/* create a new thread */
DECL_HANDLER(new_thread)
{
755
    struct thread *thread;
756
    int request_fd = thread_get_inflight_fd( current, req->request_fd );
757

758
    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
759
    {
760
        if (request_fd != -1) close( request_fd );
761 762 763 764 765 766 767
        set_error( STATUS_INVALID_HANDLE );
        return;
    }

    if ((thread = create_thread( request_fd, current->process )))
    {
        if (req->suspend) thread->suspend++;
768 769 770
        reply->tid = thread;
        if ((reply->handle = alloc_handle( current->process, thread,
                                           THREAD_ALL_ACCESS, req->inherit )))
771
        {
772 773
            /* thread object will be released when the thread gets killed */
            return;
774
        }
775 776
        kill_thread( thread, 1 );
        request_fd = -1;
777 778 779 780 781 782
    }
}

/* initialize a new thread */
DECL_HANDLER(init_thread)
{
783 784 785
    int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
    int wait_fd = thread_get_inflight_fd( current, req->wait_fd );

786
    if (current->unix_pid)
787
    {
788
        fatal_protocol_error( current, "init_thread: already running\n" );
789 790
        goto error;
    }
791
    if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1)
792 793 794 795 796 797 798 799
    {
        fatal_protocol_error( current, "bad reply fd\n" );
        goto error;
    }
    if (wait_fd == -1)
    {
        fatal_protocol_error( current, "bad wait fd\n" );
        goto error;
800
    }
801

802
    current->unix_pid = req->unix_pid;
803
    current->teb      = req->teb;
804 805 806
    current->reply_fd = reply_fd;
    current->wait_fd  = wait_fd;

807
    if (current->suspend + current->process->suspend > 0) stop_thread( current );
808
    if (current->process->running_threads > 1)
809
        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
810

811 812 813 814
    reply->pid     = get_process_id( current->process );
    reply->tid     = get_thread_id( current );
    reply->boot    = (current == booting_thread);
    reply->version = SERVER_PROTOCOL_VERSION;
815 816 817 818 819 820 821
    return;

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

822 823 824 825 826
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
    struct thread *thread;

827 828
    reply->self = 0;
    reply->last = 0;
829 830
    if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
    {
831 832 833 834
        thread->exit_code = req->exit_code;
        if (thread != current) kill_thread( thread, 1 );
        else
        {
835 836
            reply->self = 1;
            reply->last = (thread->process->running_threads == 1);
837
        }
838 839 840 841 842 843 844 845
        release_object( thread );
    }
}

/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
    struct thread *thread;
846
    handle_t handle = req->handle;
847

848
    if (!handle) thread = get_thread_from_id( req->tid_in );
849 850 851
    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );

    if (thread)
852
    {
853 854 855 856
        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;
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
        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;
877

878 879
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
880
        reply->count = suspend_thread( thread, 1 );
881 882 883 884 885 886 887 888
        release_object( thread );
    }
}

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

890 891
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
892
        reply->count = resume_thread( thread );
893 894 895 896 897 898 899
        release_object( thread );
    }
}

/* select on a handle list */
DECL_HANDLER(select)
{
900 901
    int count = get_req_data_size() / sizeof(int);
    select_on( count, req->cookie, get_req_data(), req->flags, req->sec, req->usec );
902 903 904 905 906 907 908 909
}

/* queue an APC for a thread */
DECL_HANDLER(queue_apc)
{
    struct thread *thread;
    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
    {
910
        thread_queue_apc( thread, NULL, req->func, APC_USER, !req->user, 1, req->param );
911 912 913
        release_object( thread );
    }
}
914

915 916
/* get next APC to call */
DECL_HANDLER(get_apc)
917
{
918
    struct thread_apc *apc;
919
    size_t size;
920

921
    for (;;)
922
    {
923
        if (!(apc = thread_dequeue_apc( current, !req->alertable )))
924 925
        {
            /* no more APCs */
926 927
            reply->func = NULL;
            reply->type = APC_NONE;
928 929 930 931 932 933
            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.
         */
        if (apc->func) break;
934 935
        free( apc );
    }
936
    size = apc->nb_args * sizeof(apc->args[0]);
937 938 939 940
    if (size > get_reply_max_size()) size = get_reply_max_size();
    reply->func = apc->func;
    reply->type = apc->type;
    set_reply_data( apc->args, size );
941
    free( apc );
942
}
943 944 945 946 947 948 949

/* 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 )))
    {
950
        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
951 952 953
        release_object( thread );
    }
}