thread.c 46.3 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
 *
 * 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
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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


53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
#define CPU_FLAG(cpu) (1 << (cpu))
#ifdef __i386__
static const unsigned int supported_cpus = CPU_FLAG(CPU_x86);
#elif defined(__x86_64__)
static const unsigned int supported_cpus = CPU_FLAG(CPU_x86_64) | CPU_FLAG(CPU_x86);
#elif defined(__ALPHA__)
static const unsigned int supported_cpus = CPU_FLAG(CPU_ALPHA);
#elif defined(__powerpc__)
static const unsigned int supported_cpus = CPU_FLAG(CPU_POWERPC);
#elif defined(__sparc__)
static const unsigned int supported_cpus = CPU_FLAG(CPU_SPARC);
#else
#error Unsupported CPU
#endif

Alexandre Julliard's avatar
Alexandre Julliard committed
68 69 70 71
/* thread queues */

struct thread_wait
{
72 73
    struct thread_wait     *next;       /* next wait structure for this thread */
    struct thread          *thread;     /* owner thread */
Alexandre Julliard's avatar
Alexandre Julliard committed
74 75
    int                     count;      /* count of objects */
    int                     flags;
76
    client_ptr_t            cookie;     /* magic cookie to return to client */
77
    timeout_t               timeout;
78
    struct timeout_user    *user;
Alexandre Julliard's avatar
Alexandre Julliard committed
79 80 81
    struct wait_queue_entry queues[1];
};

82 83 84 85
/* asynchronous procedure calls */

struct thread_apc
{
86
    struct object       obj;      /* object header */
87
    struct list         entry;    /* queue linked list */
88
    struct thread      *caller;   /* thread that queued this apc */
89
    struct object      *owner;    /* object that queued this apc */
90
    int                 executed; /* has it been executed by the client? */
91 92
    apc_call_t          call;     /* call arguments */
    apc_result_t        result;   /* call results once executed */
93 94
};

95 96
static void dump_thread_apc( struct object *obj, int verbose );
static int thread_apc_signaled( struct object *obj, struct thread *thread );
97
static void thread_apc_destroy( struct object *obj );
98
static void clear_apc_queue( struct list *queue );
99 100 101 102 103

static const struct object_ops thread_apc_ops =
{
    sizeof(struct thread_apc),  /* size */
    dump_thread_apc,            /* dump */
104
    no_get_type,                /* get_type */
105 106 107 108 109 110 111
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_apc_signaled,        /* signaled */
    no_satisfied,               /* satisfied */
    no_signal,                  /* signal */
    no_get_fd,                  /* get_fd */
    no_map_access,              /* map_access */
112 113
    default_get_sd,             /* get_sd */
    default_set_sd,             /* set_sd */
114
    no_lookup_name,             /* lookup_name */
115
    no_open_file,               /* open_file */
116
    no_close_handle,            /* close_handle */
117
    thread_apc_destroy          /* destroy */
118 119
};

Alexandre Julliard's avatar
Alexandre Julliard committed
120

Alexandre Julliard's avatar
Alexandre Julliard committed
121 122
/* thread operations */

Alexandre Julliard's avatar
Alexandre Julliard committed
123
static void dump_thread( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
124
static int thread_signaled( struct object *obj, struct thread *thread );
125
static unsigned int thread_map_access( struct object *obj, unsigned int access );
126
static void thread_poll_event( struct fd *fd, int event );
Alexandre Julliard's avatar
Alexandre Julliard committed
127 128 129 130
static void destroy_thread( struct object *obj );

static const struct object_ops thread_ops =
{
131 132
    sizeof(struct thread),      /* size */
    dump_thread,                /* dump */
133
    no_get_type,                /* get_type */
134 135 136 137
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_signaled,            /* signaled */
    no_satisfied,               /* satisfied */
138
    no_signal,                  /* signal */
139
    no_get_fd,                  /* get_fd */
140
    thread_map_access,          /* map_access */
141 142
    default_get_sd,             /* get_sd */
    default_set_sd,             /* set_sd */
143
    no_lookup_name,             /* lookup_name */
144
    no_open_file,               /* open_file */
145
    no_close_handle,            /* close_handle */
146 147 148 149 150
    destroy_thread              /* destroy */
};

static const struct fd_ops thread_fd_ops =
{
151 152
    NULL,                       /* get_poll_events */
    thread_poll_event,          /* poll_event */
153 154
    NULL,                       /* flush */
    NULL,                       /* get_fd_type */
155
    NULL,                       /* ioctl */
156
    NULL,                       /* queue_async */
157
    NULL,                       /* reselect_async */
158
    NULL                        /* cancel_async */
Alexandre Julliard's avatar
Alexandre Julliard committed
159 160
};

161
static struct list thread_list = LIST_INIT(thread_list);
Alexandre Julliard's avatar
Alexandre Julliard committed
162

163
/* initialize the structure for a newly allocated thread */
164
static inline void init_thread_structure( struct thread *thread )
165 166 167
{
    int i;

168
    thread->unix_pid        = -1;  /* not known yet */
169
    thread->unix_tid        = -1;  /* not known yet */
170
    thread->context         = NULL;
171
    thread->suspend_context = NULL;
172
    thread->teb             = 0;
173 174
    thread->debug_ctx       = NULL;
    thread->debug_event     = NULL;
175
    thread->debug_break     = 0;
176 177 178
    thread->queue           = NULL;
    thread->wait            = NULL;
    thread->error           = 0;
179 180 181 182
    thread->req_data        = NULL;
    thread->req_toread      = 0;
    thread->reply_data      = NULL;
    thread->reply_towrite   = 0;
183 184 185
    thread->request_fd      = NULL;
    thread->reply_fd        = NULL;
    thread->wait_fd         = NULL;
186 187
    thread->state           = RUNNING;
    thread->exit_code       = 0;
188
    thread->priority        = 0;
189
    thread->affinity        = ~0;
190
    thread->suspend         = 0;
191
    thread->desktop_users   = 0;
192
    thread->token           = NULL;
193

194
    thread->creation_time = current_time;
195
    thread->exit_time     = 0;
196

197
    list_init( &thread->mutex_list );
198 199 200
    list_init( &thread->system_apc );
    list_init( &thread->user_apc );

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

205
/* check if address looks valid for a client-side data structure (TEB etc.) */
206
static inline int is_valid_address( client_ptr_t addr )
207
{
208
    return addr && !(addr % sizeof(int));
209 210
}

211
/* create a new thread */
212
struct thread *create_thread( int fd, struct process *process )
213 214 215
{
    struct thread *thread;

216
    if (!(thread = alloc_object( &thread_ops ))) return NULL;
217

218
    init_thread_structure( thread );
219

220
    thread->process = (struct process *)grab_object( process );
221
    thread->desktop = process->desktop;
222 223
    if (!current) current = thread;

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

226 227 228 229 230
    if (!(thread->id = alloc_ptid( thread )))
    {
        release_object( thread );
        return NULL;
    }
231
    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 )))
232 233 234 235
    {
        release_object( thread );
        return NULL;
    }
236

237
    set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
238
    add_process_thread( thread->process, thread );
239
    return thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
240 241
}

242
/* handle a client event */
243
static void thread_poll_event( struct fd *fd, int event )
244
{
245 246
    struct thread *thread = get_fd_user( fd );
    assert( thread->obj.ops == &thread_ops );
247

248
    if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
249
    else if (event & POLLIN) read_request( thread );
250
    else if (event & POLLOUT) write_reply( thread );
251 252 253 254 255 256 257 258
}

/* 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;

259 260
    clear_apc_queue( &thread->system_apc );
    clear_apc_queue( &thread->user_apc );
261 262
    free( thread->req_data );
    free( thread->reply_data );
263 264 265
    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 );
266
    free( thread->suspend_context );
267
    cleanup_clipboard_thread(thread);
268
    destroy_thread_windows( thread );
269
    free_msg_queue( thread );
270
    close_thread_desktop( thread );
271 272 273 274 275 276 277 278
    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;
        }
    }
279 280
    thread->req_data = NULL;
    thread->reply_data = NULL;
281 282 283
    thread->request_fd = NULL;
    thread->reply_fd = NULL;
    thread->wait_fd = NULL;
284 285
    thread->context = NULL;
    thread->suspend_context = NULL;
286
    thread->desktop = 0;
287 288
}

Alexandre Julliard's avatar
Alexandre Julliard committed
289 290 291 292 293 294
/* 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 );

295
    assert( !thread->debug_ctx );  /* cannot still be debugging something */
296
    list_remove( &thread->entry );
297
    cleanup_thread( thread );
298
    release_object( thread->process );
299
    if (thread->id) free_ptid( thread->id );
300
    if (thread->token) release_object( thread->token );
Alexandre Julliard's avatar
Alexandre Julliard committed
301 302
}

Alexandre Julliard's avatar
Alexandre Julliard committed
303 304 305 306 307 308
/* 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 );

309 310
    fprintf( stderr, "Thread id=%04x unix pid=%d unix tid=%d state=%d\n",
             thread->id, thread->unix_pid, thread->unix_tid, thread->state );
Alexandre Julliard's avatar
Alexandre Julliard committed
311 312
}

Alexandre Julliard's avatar
Alexandre Julliard committed
313 314 315 316 317 318
static int thread_signaled( struct object *obj, struct thread *thread )
{
    struct thread *mythread = (struct thread *)obj;
    return (mythread->state == TERMINATED);
}

319 320 321 322 323 324 325 326 327
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);
}

328 329 330 331 332
static void dump_thread_apc( struct object *obj, int verbose )
{
    struct thread_apc *apc = (struct thread_apc *)obj;
    assert( obj->ops == &thread_apc_ops );

333
    fprintf( stderr, "APC owner=%p type=%u\n", apc->owner, apc->call.type );
334 335 336 337
}

static int thread_apc_signaled( struct object *obj, struct thread *thread )
{
338 339
    struct thread_apc *apc = (struct thread_apc *)obj;
    return apc->executed;
340 341
}

342 343 344 345
static void thread_apc_destroy( struct object *obj )
{
    struct thread_apc *apc = (struct thread_apc *)obj;
    if (apc->caller) release_object( apc->caller );
346
    if (apc->owner) release_object( apc->owner );
347 348
}

349 350 351 352 353 354 355 356
/* queue an async procedure call */
static struct thread_apc *create_apc( struct object *owner, const apc_call_t *call_data )
{
    struct thread_apc *apc;

    if ((apc = alloc_object( &thread_apc_ops )))
    {
        apc->call        = *call_data;
357
        apc->caller      = NULL;
358 359 360
        apc->owner       = owner;
        apc->executed    = 0;
        apc->result.type = APC_NONE;
361
        if (owner) grab_object( owner );
362 363 364 365
    }
    return apc;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
366
/* get a thread pointer from a thread id (and increment the refcount) */
367
struct thread *get_thread_from_id( thread_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
368
{
369 370 371
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &thread_ops) return (struct thread *)grab_object( obj );
372
    set_error( STATUS_INVALID_CID );
373
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
374 375
}

Alexandre Julliard's avatar
Alexandre Julliard committed
376
/* get a thread from a handle (and increment the refcount) */
377
struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
378
{
Alexandre Julliard's avatar
Alexandre Julliard committed
379 380
    return (struct thread *)get_handle_obj( current->process, handle,
                                            access, &thread_ops );
Alexandre Julliard's avatar
Alexandre Julliard committed
381 382
}

383 384
/* find a thread from a Unix tid */
struct thread *get_thread_from_tid( int tid )
385
{
386
    struct thread *thread;
387

388 389
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
390
        if (thread->unix_tid == tid) return thread;
391
    }
392 393 394 395 396 397 398 399
    return NULL;
}

/* find a thread from a Unix pid */
struct thread *get_thread_from_pid( int pid )
{
    struct thread *thread;

400 401 402 403
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
        if (thread->unix_pid == pid) return thread;
    }
404
    return NULL;
405 406
}

407 408 409
#define THREAD_PRIORITY_REALTIME_HIGHEST 6
#define THREAD_PRIORITY_REALTIME_LOWEST -7

410
/* set all information about a thread */
411
static void set_thread_info( struct thread *thread,
412
                             const struct set_thread_info_request *req )
413 414
{
    if (req->mask & SET_THREAD_INFO_PRIORITY)
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
    {
        int max = THREAD_PRIORITY_HIGHEST;
        int min = THREAD_PRIORITY_LOWEST;
        if (thread->process->priority == PROCESS_PRIOCLASS_REALTIME)
        {
            max = THREAD_PRIORITY_REALTIME_HIGHEST;
            min = THREAD_PRIORITY_REALTIME_LOWEST;
        }
        if ((req->priority >= min && req->priority <= max) ||
            req->priority == THREAD_PRIORITY_IDLE ||
            req->priority == THREAD_PRIORITY_TIME_CRITICAL)
            thread->priority = req->priority;
        else
            set_error( STATUS_INVALID_PARAMETER );
    }
430
    if (req->mask & SET_THREAD_INFO_AFFINITY)
431
        thread->affinity = req->affinity;
432 433
    if (req->mask & SET_THREAD_INFO_TOKEN)
        security_set_thread_token( thread, req->token );
434 435
}

436 437 438
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
439
    if (thread->context) return;  /* already inside a debug event, no need for a signal */
440 441 442 443
    /* can't stop a thread while initialisation is in progress */
    if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
}

444
/* suspend a thread */
445
static int suspend_thread( struct thread *thread )
446 447
{
    int old_count = thread->suspend;
448
    if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
449
    {
450
        if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
451
    }
452
    else set_error( STATUS_SUSPEND_COUNT_EXCEEDED );
453 454 455 456
    return old_count;
}

/* resume a thread */
457
static int resume_thread( struct thread *thread )
458 459 460 461
{
    int old_count = thread->suspend;
    if (thread->suspend > 0)
    {
462
        if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
463 464
    }
    return old_count;
Alexandre Julliard's avatar
Alexandre Julliard committed
465 466 467
}

/* add a thread to an object wait queue; return 1 if OK, 0 on error */
468
int add_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
469
{
470
    grab_object( obj );
471 472
    entry->obj = obj;
    list_add_tail( &obj->wait_queue, &entry->entry );
473
    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
474 475 476
}

/* remove a thread from an object wait queue */
477
void remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
478
{
479
    list_remove( &entry->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
480 481 482 483 484 485 486 487 488 489 490
    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 );
491
    thread->wait = wait->next;
492 493
    for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        entry->obj->ops->remove_queue( entry->obj, entry );
494
    if (wait->user) remove_timeout_user( wait->user );
Alexandre Julliard's avatar
Alexandre Julliard committed
495 496 497 498
    free( wait );
}

/* build the thread wait structure */
499
static int wait_on( unsigned int count, struct object *objects[], int flags, timeout_t timeout )
Alexandre Julliard's avatar
Alexandre Julliard committed
500 501 502
{
    struct thread_wait *wait;
    struct wait_queue_entry *entry;
503
    unsigned int i;
Alexandre Julliard's avatar
Alexandre Julliard committed
504

505
    if (!(wait = mem_alloc( FIELD_OFFSET(struct thread_wait, queues[count]) ))) return 0;
506 507
    wait->next    = current->wait;
    wait->thread  = current;
Alexandre Julliard's avatar
Alexandre Julliard committed
508 509
    wait->count   = count;
    wait->flags   = flags;
510
    wait->user    = NULL;
511
    wait->timeout = timeout;
512
    current->wait = wait;
Alexandre Julliard's avatar
Alexandre Julliard committed
513 514 515

    for (i = 0, entry = wait->queues; i < count; i++, entry++)
    {
516 517
        struct object *obj = objects[i];
        entry->thread = current;
518 519
        if (!obj->ops->add_queue( obj, entry ))
        {
520 521
            wait->count = i;
            end_wait( current );
522 523
            return 0;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
524 525 526 527 528
    }
    return 1;
}

/* check if the thread waiting condition is satisfied */
529
static int check_wait( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
530
{
531
    int i, signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
532 533 534
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry = wait->queues;

535 536 537 538 539
    assert( wait );

    if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty( &thread->system_apc ))
        return STATUS_USER_APC;

540
    /* Suspended threads may not acquire locks, but they can run system APCs */
541
    if (thread->process->suspend + thread->suspend > 0) return -1;
542

Alexandre Julliard's avatar
Alexandre Julliard committed
543 544
    if (wait->flags & SELECT_ALL)
    {
545 546 547
        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
548
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
549 550
            not_ok |= !entry->obj->ops->signaled( entry->obj, thread );
        if (not_ok) goto other_checks;
Alexandre Julliard's avatar
Alexandre Julliard committed
551
        /* Wait satisfied: tell it to all objects */
552
        signaled = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
553 554
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
            if (entry->obj->ops->satisfied( entry->obj, thread ))
555 556
                signaled = STATUS_ABANDONED_WAIT_0;
        return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
557 558 559 560 561 562 563
    }
    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 */
564
            signaled = i;
Alexandre Julliard's avatar
Alexandre Julliard committed
565
            if (entry->obj->ops->satisfied( entry->obj, thread ))
566 567
                signaled = i + STATUS_ABANDONED_WAIT_0;
            return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
568 569
        }
    }
570 571

 other_checks:
572
    if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
573
    if (wait->timeout <= current_time) return STATUS_TIMEOUT;
574 575 576
    return -1;
}

577
/* send the wakeup signal to a thread */
578
static int send_thread_wakeup( struct thread *thread, client_ptr_t cookie, int signaled )
579 580 581 582
{
    struct wake_up_reply reply;
    int ret;

583
    memset( &reply, 0, sizeof(reply) );
584 585
    reply.cookie   = cookie;
    reply.signaled = signaled;
586 587
    if ((ret = write( get_unix_fd( thread->wait_fd ), &reply, sizeof(reply) )) == sizeof(reply))
        return 0;
588 589 590 591 592 593 594 595 596
    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
597
/* attempt to wake up a thread */
598
/* return >0 if OK, 0 if the wait condition is still not satisfied */
599
int wake_thread( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
600
{
601
    int signaled, count;
602
    client_ptr_t cookie;
603

604 605 606 607 608
    for (count = 0; thread->wait; count++)
    {
        if ((signaled = check_wait( thread )) == -1) break;

        cookie = thread->wait->cookie;
609
        if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
610
        end_wait( thread );
611 612
        if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
	    break;
613 614
    }
    return count;
Alexandre Julliard's avatar
Alexandre Julliard committed
615 616
}

617 618 619
/* thread wait timeout */
static void thread_timeout( void *ptr )
{
620 621
    struct thread_wait *wait = ptr;
    struct thread *thread = wait->thread;
622
    client_ptr_t cookie = wait->cookie;
623

624 625
    wait->user = NULL;
    if (thread->wait != wait) return; /* not the top-level wait, ignore it */
626
    if (thread->suspend + thread->process->suspend > 0) return;  /* suspended, ignore it */
627

628
    if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id );
629
    end_wait( thread );
630
    if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
631 632
    /* check if other objects have become signaled in the meantime */
    wake_thread( thread );
633 634
}

635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
/* 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;
}

650
/* select on a list of handles */
651
static timeout_t select_on( unsigned int count, client_ptr_t cookie, const obj_handle_t *handles,
652
                            int flags, timeout_t timeout, obj_handle_t signal_obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
653
{
654 655
    int ret;
    unsigned int i;
656
    struct object *objects[MAXIMUM_WAIT_OBJECTS];
657

658 659 660
    if (timeout <= 0) timeout = current_time - timeout;

    if (count > MAXIMUM_WAIT_OBJECTS)
661
    {
662
        set_error( STATUS_INVALID_PARAMETER );
663
        return 0;
664 665 666 667 668 669
    }
    for (i = 0; i < count; i++)
    {
        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
            break;
    }
670 671

    if (i < count) goto done;
672
    if (!wait_on( count, objects, flags, timeout )) goto done;
673

674 675 676 677 678 679 680 681 682 683 684 685
    /* 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;
    }

686 687 688 689 690 691 692 693 694
    if ((ret = check_wait( current )) != -1)
    {
        /* condition is already satisfied */
        end_wait( current );
        set_error( ret );
        goto done;
    }

    /* now we need to wait */
695
    if (current->wait->timeout != TIMEOUT_INFINITE)
696
    {
697
        if (!(current->wait->user = add_timeout_user( current->wait->timeout,
698
                                                      thread_timeout, current->wait )))
699 700 701 702 703
        {
            end_wait( current );
            goto done;
        }
    }
704
    current->wait->cookie = cookie;
705 706 707
    set_error( STATUS_PENDING );

done:
708 709
    while (i > 0) release_object( objects[--i] );
    return timeout;
Alexandre Julliard's avatar
Alexandre Julliard committed
710 711 712 713 714
}

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

717
    LIST_FOR_EACH( ptr, &obj->wait_queue )
Alexandre Julliard's avatar
Alexandre Julliard committed
718
    {
719
        struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
720 721 722 723
        if (!wake_thread( entry->thread )) continue;
        if (max && !--max) break;
        /* restart at the head of the list since a wake up can change the object wait queue */
        ptr = &obj->wait_queue;
Alexandre Julliard's avatar
Alexandre Julliard committed
724 725 726
    }
}

727 728 729 730 731 732 733 734 735 736 737 738 739 740
/* return the apc queue to use for a given apc type */
static inline struct list *get_apc_queue( struct thread *thread, enum apc_type type )
{
    switch(type)
    {
    case APC_NONE:
    case APC_USER:
    case APC_TIMER:
        return &thread->user_apc;
    default:
        return &thread->system_apc;
    }
}

741 742 743 744 745 746 747
/* check if thread is currently waiting for a (system) apc */
static inline int is_in_apc_wait( struct thread *thread )
{
    return (thread->process->suspend || thread->suspend ||
            (thread->wait && (thread->wait->flags & SELECT_INTERRUPTIBLE)));
}

748 749
/* queue an existing APC to a given thread */
static int queue_apc( struct process *process, struct thread *thread, struct thread_apc *apc )
750
{
751 752 753 754 755
    struct list *queue;

    if (!thread)  /* find a suitable thread inside the process */
    {
        struct thread *candidate;
756

757 758 759 760
        /* first try to find a waiting thread */
        LIST_FOR_EACH_ENTRY( candidate, &process->thread_list, struct thread, proc_entry )
        {
            if (candidate->state == TERMINATED) continue;
761
            if (is_in_apc_wait( candidate ))
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
            {
                thread = candidate;
                break;
            }
        }
        if (!thread)
        {
            /* then use the first one that accepts a signal */
            LIST_FOR_EACH_ENTRY( candidate, &process->thread_list, struct thread, proc_entry )
            {
                if (send_thread_signal( candidate, SIGUSR1 ))
                {
                    thread = candidate;
                    break;
                }
            }
        }
        if (!thread) return 0;  /* nothing found */
780
        queue = get_apc_queue( thread, apc->call.type );
781 782 783 784
    }
    else
    {
        if (thread->state == TERMINATED) return 0;
785 786 787 788 789 790
        queue = get_apc_queue( thread, apc->call.type );
        /* send signal for system APCs if needed */
        if (queue == &thread->system_apc && list_empty( queue ) && !is_in_apc_wait( thread ))
        {
            if (!send_thread_signal( thread, SIGUSR1 )) return 0;
        }
791 792 793
        /* cancel a possible previous APC with the same owner */
        if (apc->owner) thread_cancel_apc( thread, apc->owner, apc->call.type );
    }
794

795
    grab_object( apc );
796 797
    list_add_tail( queue, &apc->entry );
    if (!list_prev( queue, &apc->entry ))  /* first one */
798
        wake_thread( thread );
799

800 801 802
    return 1;
}

803 804 805 806 807 808 809 810 811 812 813 814 815 816
/* queue an async procedure call */
int thread_queue_apc( struct thread *thread, struct object *owner, const apc_call_t *call_data )
{
    struct thread_apc *apc;
    int ret = 0;

    if ((apc = create_apc( owner, call_data )))
    {
        ret = queue_apc( NULL, thread, apc );
        release_object( apc );
    }
    return ret;
}

817
/* cancel the async procedure call owned by a specific object */
818
void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_type type )
819 820
{
    struct thread_apc *apc;
821 822
    struct list *queue = get_apc_queue( thread, type );

823
    LIST_FOR_EACH_ENTRY( apc, queue, struct thread_apc, entry )
824 825
    {
        if (apc->owner != owner) continue;
826
        list_remove( &apc->entry );
827 828
        apc->executed = 1;
        wake_up( &apc->obj, 0 );
829
        release_object( apc );
830 831 832 833
        return;
    }
}

834
/* remove the head apc from the queue; the returned object must be released by the caller */
835
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
836
{
837 838
    struct thread_apc *apc = NULL;
    struct list *ptr = list_head( &thread->system_apc );
839

840 841
    if (!ptr && !system_only) ptr = list_head( &thread->user_apc );
    if (ptr)
842
    {
843 844
        apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( ptr );
845 846 847 848
    }
    return apc;
}

849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
/* clear an APC queue, cancelling all the APCs on it */
static void clear_apc_queue( struct list *queue )
{
    struct list *ptr;

    while ((ptr = list_head( queue )))
    {
        struct thread_apc *apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( &apc->entry );
        apc->executed = 1;
        wake_up( &apc->obj, 0 );
        release_object( apc );
    }
}

864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
/* 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;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
920
/* kill a thread on the spot */
921
void kill_thread( struct thread *thread, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
922
{
Alexandre Julliard's avatar
Alexandre Julliard committed
923
    if (thread->state == TERMINATED) return;  /* already killed */
Alexandre Julliard's avatar
Alexandre Julliard committed
924
    thread->state = TERMINATED;
925
    thread->exit_time = current_time;
926
    if (current == thread) current = NULL;
927
    if (debug_level)
928 929
        fprintf( stderr,"%04x: *killed* exit_code=%d\n",
                 thread->id, thread->exit_code );
930 931
    if (thread->wait)
    {
932
        while (thread->wait) end_wait( thread );
933
        send_thread_wakeup( thread, 0, STATUS_PENDING );
934
        /* if it is waiting on the socket, we don't need to send a SIGQUIT */
935 936
        violent_death = 0;
    }
937
    kill_console_processes( thread, 0 );
938
    debug_exit_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
939
    abandon_mutexes( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
940
    wake_up( &thread->obj, 0 );
941
    if (violent_death) send_thread_signal( thread, SIGQUIT );
942
    cleanup_thread( thread );
943
    remove_process_thread( thread->process, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
944
    release_object( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
945
}
946

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
/* copy parts of a context structure */
static void copy_context( context_t *to, const context_t *from, unsigned int flags )
{
    assert( to->cpu == from->cpu );
    to->flags |= flags;
    if (flags & SERVER_CTX_CONTROL) to->ctl = from->ctl;
    if (flags & SERVER_CTX_INTEGER) to->integer = from->integer;
    if (flags & SERVER_CTX_SEGMENTS) to->seg = from->seg;
    if (flags & SERVER_CTX_FLOATING_POINT) to->fp = from->fp;
    if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug;
    if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext;
}

/* return the context flags that correspond to system regs */
/* (system regs are the ones we can't access on the client side) */
static unsigned int get_context_system_regs( enum cpu_type cpu )
{
    switch (cpu)
    {
    case CPU_x86:     return SERVER_CTX_DEBUG_REGISTERS;
    case CPU_x86_64:  return SERVER_CTX_DEBUG_REGISTERS;
    case CPU_ALPHA:   return 0;
    case CPU_POWERPC: return 0;
    case CPU_SPARC:   return 0;
    }
    return 0;
}

975 976 977
/* trigger a breakpoint event in a given thread */
void break_thread( struct thread *thread )
{
978
    debug_event_t data;
979 980 981

    assert( thread->context );

982 983 984 985
    memset( &data, 0, sizeof(data) );
    data.exception.first     = 1;
    data.exception.exc_code  = STATUS_BREAKPOINT;
    data.exception.flags     = EXCEPTION_CONTINUABLE;
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
    switch (thread->context->cpu)
    {
    case CPU_x86:
        data.exception.address = thread->context->ctl.i386_regs.eip;
        break;
    case CPU_x86_64:
        data.exception.address = thread->context->ctl.x86_64_regs.rip;
        break;
    case CPU_ALPHA:
        data.exception.address = thread->context->ctl.alpha_regs.fir;
        break;
    case CPU_POWERPC:
        data.exception.address = thread->context->ctl.powerpc_regs.iar;
        break;
    case CPU_SPARC:
        data.exception.address = thread->context->ctl.sparc_regs.pc;
        break;
    }
1004 1005 1006 1007
    generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
    thread->debug_break = 0;
}

1008 1009 1010 1011 1012 1013 1014
/* 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;

1015
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
1016 1017 1018
        if (thread->state != TERMINATED) total++;
    if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
    ptr = snapshot;
1019
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
    {
        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;
}

1032 1033 1034 1035 1036 1037 1038 1039 1040
/* 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;
}

1041 1042 1043
/* create a new thread */
DECL_HANDLER(new_thread)
{
1044
    struct thread *thread;
1045
    int request_fd = thread_get_inflight_fd( current, req->request_fd );
1046

1047
    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
1048
    {
1049
        if (request_fd != -1) close( request_fd );
1050 1051 1052 1053 1054 1055 1056
        set_error( STATUS_INVALID_HANDLE );
        return;
    }

    if ((thread = create_thread( request_fd, current->process )))
    {
        if (req->suspend) thread->suspend++;
1057
        reply->tid = get_thread_id( thread );
1058
        if ((reply->handle = alloc_handle( current->process, thread, req->access, req->attributes )))
1059
        {
1060 1061
            /* thread object will be released when the thread gets killed */
            return;
1062
        }
1063
        kill_thread( thread, 1 );
1064 1065 1066 1067 1068 1069
    }
}

/* initialize a new thread */
DECL_HANDLER(init_thread)
{
1070
    struct process *process = current->process;
1071 1072 1073
    int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
    int wait_fd = thread_get_inflight_fd( current, req->wait_fd );

1074
    if (current->reply_fd)  /* already initialised */
1075
    {
1076
        set_error( STATUS_INVALID_PARAMETER );
1077 1078
        goto error;
    }
1079 1080 1081

    if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error;

1082
    current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj, 0 );
1083 1084 1085
    reply_fd = -1;
    if (!current->reply_fd) goto error;

1086 1087
    if (wait_fd == -1)
    {
1088 1089
        set_error( STATUS_TOO_MANY_OPENED_FILES );  /* most likely reason */
        return;
1090
    }
1091
    if (!(current->wait_fd  = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj, 0 )))
1092
        return;
1093

1094
    if (!is_valid_address(req->teb))
1095 1096 1097 1098 1099
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }

1100
    current->unix_pid = req->unix_pid;
1101
    current->unix_tid = req->unix_tid;
1102
    current->teb      = req->teb;
1103

1104 1105
    if (!process->peb)  /* first thread, initialize the process too */
    {
1106 1107 1108 1109 1110
        if (!CPU_FLAG(req->cpu) || !(supported_cpus & CPU_FLAG(req->cpu)))
        {
            set_error( STATUS_NOT_SUPPORTED );
            return;
        }
1111
        process->unix_pid = current->unix_pid;
1112
        process->peb      = req->entry;
1113
        process->cpu      = req->cpu;
1114
        reply->info_size  = init_process( current );
1115 1116 1117
    }
    else
    {
1118 1119 1120 1121 1122
        if (req->cpu != process->cpu)
        {
            set_error( STATUS_INVALID_PARAMETER );
            return;
        }
1123 1124
        if (process->unix_pid != current->unix_pid)
            process->unix_pid = -1;  /* can happen with linuxthreads */
1125
        if (current->suspend + process->suspend > 0) stop_thread( current );
1126
        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, &req->entry );
1127 1128
    }
    debug_level = max( debug_level, req->debug_level );
1129

1130
    reply->pid     = get_process_id( process );
1131 1132
    reply->tid     = get_thread_id( current );
    reply->version = SERVER_PROTOCOL_VERSION;
1133
    reply->server_start = server_start_time;
1134
    reply->all_cpus     = supported_cpus;
1135 1136 1137 1138 1139 1140 1141
    return;

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

1142 1143 1144 1145 1146
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
    struct thread *thread;

1147 1148
    reply->self = 0;
    reply->last = 0;
1149 1150
    if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
    {
1151 1152 1153 1154
        thread->exit_code = req->exit_code;
        if (thread != current) kill_thread( thread, 1 );
        else
        {
1155 1156
            reply->self = 1;
            reply->last = (thread->process->running_threads == 1);
1157
        }
1158 1159 1160 1161
        release_object( thread );
    }
}

1162 1163 1164 1165 1166 1167 1168 1169
/* open a handle to a thread */
DECL_HANDLER(open_thread)
{
    struct thread *thread = get_thread_from_id( req->tid );

    reply->handle = 0;
    if (thread)
    {
1170
        reply->handle = alloc_handle( current->process, thread, req->access, req->attributes );
1171 1172 1173 1174
        release_object( thread );
    }
}

1175 1176 1177 1178
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
    struct thread *thread;
1179
    obj_handle_t handle = req->handle;
1180

1181
    if (!handle) thread = get_thread_from_id( req->tid_in );
1182 1183 1184
    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );

    if (thread)
1185
    {
1186
        reply->pid            = get_process_id( thread->process );
1187 1188
        reply->tid            = get_thread_id( thread );
        reply->teb            = thread->teb;
1189
        reply->exit_code      = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING;
1190
        reply->priority       = thread->priority;
1191
        reply->affinity       = thread->affinity;
1192 1193
        reply->creation_time  = thread->creation_time;
        reply->exit_time      = thread->exit_time;
1194
        reply->last           = thread->process->running_threads == 1;
1195

1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
        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;
1216

1217 1218
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1219
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
1220
        else reply->count = suspend_thread( thread );
1221 1222 1223 1224 1225 1226 1227 1228
        release_object( thread );
    }
}

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

1230 1231
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1232
        reply->count = resume_thread( thread );
1233 1234 1235 1236 1237 1238 1239
        release_object( thread );
    }
}

/* select on a handle list */
DECL_HANDLER(select)
{
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
    struct thread_apc *apc;
    unsigned int count;
    const apc_result_t *result = get_req_data();
    const obj_handle_t *handles = (const obj_handle_t *)(result + 1);

    if (get_req_data_size() < sizeof(*result))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    count = (get_req_data_size() - sizeof(*result)) / sizeof(obj_handle_t);

    /* first store results of previous apc */
    if (req->prev_apc)
    {
        if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->prev_apc,
                                                         0, &thread_apc_ops ))) return;
        apc->result = *result;
        apc->executed = 1;
        if (apc->result.type == APC_CREATE_THREAD)  /* transfer the handle to the caller process */
        {
            obj_handle_t handle = duplicate_handle( current->process, apc->result.create_thread.handle,
                                                    apc->caller->process, 0, 0, DUP_HANDLE_SAME_ACCESS );
            close_handle( current->process, apc->result.create_thread.handle );
            apc->result.create_thread.handle = handle;
            clear_error();  /* ignore errors from the above calls */
        }
        else if (apc->result.type == APC_ASYNC_IO)
        {
1269 1270 1271
            if (apc->owner)
                async_set_result( apc->owner, apc->result.async_io.status,
                                  apc->result.async_io.total, apc->result.async_io.apc );
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
        }
        wake_up( &apc->obj, 0 );
        close_handle( current->process, req->prev_apc );
        release_object( apc );
    }

    reply->timeout = select_on( count, req->cookie, handles, req->flags, req->timeout, req->signal );

    if (get_error() == STATUS_USER_APC)
    {
        for (;;)
        {
            if (!(apc = thread_dequeue_apc( current, !(req->flags & SELECT_ALERTABLE) )))
                break;
            /* Optimization: ignore APC_NONE calls, they are only used to
             * wake up a thread, but since we got here the thread woke up already.
             */
            if (apc->call.type != APC_NONE)
            {
                if ((reply->apc_handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
                    reply->call = apc->call;
                release_object( apc );
                break;
            }
            apc->executed = 1;
            wake_up( &apc->obj, 0 );
            release_object( apc );
        }
    }
1301 1302
}

1303
/* queue an APC for a thread or process */
1304 1305
DECL_HANDLER(queue_apc)
{
1306 1307
    struct thread *thread = NULL;
    struct process *process = NULL;
1308 1309 1310 1311 1312
    struct thread_apc *apc;

    if (!(apc = create_apc( NULL, &req->call ))) return;

    switch (apc->call.type)
1313
    {
1314 1315
    case APC_NONE:
    case APC_USER:
1316
        thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT );
1317 1318 1319
        break;
    case APC_VIRTUAL_ALLOC:
    case APC_VIRTUAL_FREE:
1320
    case APC_VIRTUAL_PROTECT:
1321
    case APC_VIRTUAL_FLUSH:
1322 1323
    case APC_VIRTUAL_LOCK:
    case APC_VIRTUAL_UNLOCK:
1324
    case APC_UNMAP_VIEW:
1325
        process = get_process_from_handle( req->handle, PROCESS_VM_OPERATION );
1326 1327
        break;
    case APC_VIRTUAL_QUERY:
1328
        process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION );
1329
        break;
1330
    case APC_MAP_VIEW:
1331
        process = get_process_from_handle( req->handle, PROCESS_VM_OPERATION );
1332
        if (process && process != current->process)
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
        {
            /* duplicate the handle into the target process */
            obj_handle_t handle = duplicate_handle( current->process, apc->call.map_view.handle,
                                                    process, 0, 0, DUP_HANDLE_SAME_ACCESS );
            if (handle) apc->call.map_view.handle = handle;
            else
            {
                release_object( process );
                process = NULL;
            }
        }
        break;
1345
    case APC_CREATE_THREAD:
1346
        process = get_process_from_handle( req->handle, PROCESS_CREATE_THREAD );
1347 1348 1349 1350
        break;
    default:
        set_error( STATUS_INVALID_PARAMETER );
        break;
1351
    }
1352 1353 1354 1355 1356 1357 1358 1359

    if (thread)
    {
        if (!queue_apc( NULL, thread, apc )) set_error( STATUS_THREAD_IS_TERMINATING );
        release_object( thread );
    }
    else if (process)
    {
1360 1361
        reply->self = (process == current->process);
        if (!reply->self)
1362
        {
1363 1364
            obj_handle_t handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 );
            if (handle)
1365
            {
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
                if (queue_apc( process, NULL, apc ))
                {
                    apc->caller = (struct thread *)grab_object( current );
                    reply->handle = handle;
                }
                else
                {
                    close_handle( current->process, handle );
                    set_error( STATUS_PROCESS_IS_TERMINATING );
                }
1376 1377 1378 1379 1380
            }
        }
        release_object( process );
    }

1381
    release_object( apc );
1382
}
1383

1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
/* Get the result of an APC call */
DECL_HANDLER(get_apc_result)
{
    struct thread_apc *apc;

    if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->handle,
                                                     0, &thread_apc_ops ))) return;
    if (!apc->executed) set_error( STATUS_PENDING );
    else
    {
        reply->result = apc->result;
        /* close the handle directly to avoid an extra round-trip */
        close_handle( current->process, req->handle );
    }
    release_object( apc );
}

1401 1402 1403 1404
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{
    struct thread *thread;
1405
    context_t *context;
1406

1407
    if (get_reply_max_size() < sizeof(context_t))
1408 1409 1410 1411 1412 1413
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;

1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
    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;
1424
            set_reply_data_ptr( thread->suspend_context, sizeof(context_t) );
1425 1426 1427 1428 1429 1430 1431 1432 1433
            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 );
    }
1434
    else if ((context = set_reply_data_size( sizeof(context_t) )))
1435
    {
1436
        unsigned int flags = get_context_system_regs( thread->process->cpu );
1437

1438 1439
        memset( context, 0, sizeof(context_t) );
        context->cpu = thread->process->cpu;
1440 1441
        if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
        if (flags) get_thread_context( thread, context, flags );
1442
    }
1443
    reply->self = (thread == current);
1444 1445 1446 1447 1448 1449 1450
    release_object( thread );
}

/* set the current context of a thread */
DECL_HANDLER(set_thread_context)
{
    struct thread *thread;
1451
    const context_t *context = get_req_data();
1452

1453
    if (get_req_data_size() < sizeof(context_t))
1454 1455 1456 1457
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
1458 1459 1460 1461
    if (!(thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) return;

    if (req->suspend)
    {
1462
        if (thread != current || thread->context || context->cpu != thread->process->cpu)
1463 1464 1465 1466
        {
            /* nested suspend or exception, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
1467
        else if ((thread->suspend_context = mem_alloc( sizeof(context_t) )))
1468
        {
1469
            memcpy( thread->suspend_context, get_req_data(), sizeof(context_t) );
1470
            thread->context = thread->suspend_context;
1471
            if (thread->debug_break) break_thread( thread );
1472 1473 1474 1475 1476 1477 1478 1479
        }
    }
    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 );
    }
1480
    else if (context->cpu == thread->process->cpu)
1481
    {
1482 1483
        unsigned int system_flags = get_context_system_regs(context->cpu) & context->flags;
        unsigned int client_flags = context->flags & ~system_flags;
1484

1485 1486
        if (system_flags) set_thread_context( thread, context, system_flags );
        if (thread->context && !get_error()) copy_context( thread->context, context, client_flags );
1487
    }
1488 1489
    else set_error( STATUS_INVALID_PARAMETER );

1490
    reply->self = (thread == current);
1491
    release_object( thread );
1492 1493
}

1494 1495 1496 1497 1498 1499
/* 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 )))
    {
1500
        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
1501 1502 1503
        release_object( thread );
    }
}