thread.c 36.5 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


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

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

67 68 69 70
/* asynchronous procedure calls */

struct thread_apc
{
71
    struct object       obj;      /* object header */
72
    struct list         entry;    /* queue linked list */
73
    struct object      *owner;    /* object that queued this apc */
74
    int                 executed; /* has it been executed by the client? */
75
    apc_call_t          call;
76 77
};

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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 );

static const struct object_ops thread_apc_ops =
{
    sizeof(struct thread_apc),  /* size */
    dump_thread_apc,            /* dump */
    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 */
    no_lookup_name,             /* lookup_name */
    no_close_handle,            /* close_handle */
    no_destroy                  /* destroy */
};

Alexandre Julliard's avatar
Alexandre Julliard committed
97

Alexandre Julliard's avatar
Alexandre Julliard committed
98 99
/* thread operations */

Alexandre Julliard's avatar
Alexandre Julliard committed
100
static void dump_thread( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
101
static int thread_signaled( struct object *obj, struct thread *thread );
102
static unsigned int thread_map_access( struct object *obj, unsigned int access );
103
static void thread_poll_event( struct fd *fd, int event );
Alexandre Julliard's avatar
Alexandre Julliard committed
104
static void destroy_thread( struct object *obj );
105
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only );
Alexandre Julliard's avatar
Alexandre Julliard committed
106 107 108

static const struct object_ops thread_ops =
{
109 110 111 112 113 114
    sizeof(struct thread),      /* size */
    dump_thread,                /* dump */
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_signaled,            /* signaled */
    no_satisfied,               /* satisfied */
115
    no_signal,                  /* signal */
116
    no_get_fd,                  /* get_fd */
117
    thread_map_access,          /* map_access */
118
    no_lookup_name,             /* lookup_name */
119
    no_close_handle,            /* close_handle */
120 121 122 123 124
    destroy_thread              /* destroy */
};

static const struct fd_ops thread_fd_ops =
{
125 126 127 128
    NULL,                       /* get_poll_events */
    thread_poll_event,          /* poll_event */
    no_flush,                   /* flush */
    no_get_file_info,           /* get_file_info */
129 130
    no_queue_async,             /* queue_async */
    no_cancel_async             /* cancel_async */
Alexandre Julliard's avatar
Alexandre Julliard committed
131 132
};

133
static struct list thread_list = LIST_INIT(thread_list);
Alexandre Julliard's avatar
Alexandre Julliard committed
134

135 136 137 138 139
/* initialize the structure for a newly allocated thread */
inline static void init_thread_structure( struct thread *thread )
{
    int i;

140
    thread->unix_pid        = -1;  /* not known yet */
141
    thread->unix_tid        = -1;  /* not known yet */
142
    thread->context         = NULL;
143
    thread->suspend_context = NULL;
144 145 146
    thread->teb             = NULL;
    thread->debug_ctx       = NULL;
    thread->debug_event     = NULL;
147
    thread->debug_break     = 0;
148 149 150
    thread->queue           = NULL;
    thread->wait            = NULL;
    thread->error           = 0;
151 152 153 154
    thread->req_data        = NULL;
    thread->req_toread      = 0;
    thread->reply_data      = NULL;
    thread->reply_towrite   = 0;
155 156 157
    thread->request_fd      = NULL;
    thread->reply_fd        = NULL;
    thread->wait_fd         = NULL;
158 159
    thread->state           = RUNNING;
    thread->exit_code       = 0;
160
    thread->priority        = 0;
161 162
    thread->affinity        = 1;
    thread->suspend         = 0;
163
    thread->desktop_users   = 0;
164
    thread->token           = NULL;
165

166
    thread->creation_time = current_time;
167 168
    thread->exit_time.tv_sec = thread->exit_time.tv_usec = 0;

169
    list_init( &thread->mutex_list );
170 171 172
    list_init( &thread->system_apc );
    list_init( &thread->user_apc );

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

177 178 179
/* check if address looks valid for a client-side data structure (TEB etc.) */
static inline int is_valid_address( void *addr )
{
180
    return addr && !((unsigned long)addr % sizeof(int));
181 182
}

183
/* create a new thread */
184
struct thread *create_thread( int fd, struct process *process )
185 186 187
{
    struct thread *thread;

188
    if (!(thread = alloc_object( &thread_ops ))) return NULL;
189

190
    init_thread_structure( thread );
191

192
    thread->process = (struct process *)grab_object( process );
193
    thread->desktop = process->desktop;
194 195
    if (!current) current = thread;

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

198 199 200 201 202
    if (!(thread->id = alloc_ptid( thread )))
    {
        release_object( thread );
        return NULL;
    }
203
    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj )))
204 205 206 207
    {
        release_object( thread );
        return NULL;
    }
208

209
    set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
210
    add_process_thread( thread->process, thread );
211
    return thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
212 213
}

214
/* handle a client event */
215
static void thread_poll_event( struct fd *fd, int event )
216
{
217 218
    struct thread *thread = get_fd_user( fd );
    assert( thread->obj.ops == &thread_ops );
219

220
    if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
221
    else if (event & POLLIN) read_request( thread );
222
    else if (event & POLLOUT) write_reply( thread );
223 224 225 226 227 228 229 230 231
}

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

232
    while ((apc = thread_dequeue_apc( thread, 0 ))) release_object( apc );
233 234
    free( thread->req_data );
    free( thread->reply_data );
235 236 237
    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 );
238
    free( thread->suspend_context );
239
    free_msg_queue( thread );
240
    cleanup_clipboard_thread(thread);
241
    destroy_thread_windows( thread );
242
    close_thread_desktop( thread );
243 244 245 246 247 248 249 250
    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;
        }
    }
251 252
    thread->req_data = NULL;
    thread->reply_data = NULL;
253 254 255
    thread->request_fd = NULL;
    thread->reply_fd = NULL;
    thread->wait_fd = NULL;
256 257
    thread->context = NULL;
    thread->suspend_context = NULL;
258
    thread->desktop = 0;
259 260
}

Alexandre Julliard's avatar
Alexandre Julliard committed
261 262 263 264 265 266
/* 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 );

267
    assert( !thread->debug_ctx );  /* cannot still be debugging something */
268
    list_remove( &thread->entry );
269
    cleanup_thread( thread );
270
    release_object( thread->process );
271
    if (thread->id) free_ptid( thread->id );
272
    if (thread->token) release_object( thread->token );
Alexandre Julliard's avatar
Alexandre Julliard committed
273 274
}

Alexandre Julliard's avatar
Alexandre Julliard committed
275 276 277 278 279 280
/* 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 );

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

Alexandre Julliard's avatar
Alexandre Julliard committed
285 286 287 288 289 290
static int thread_signaled( struct object *obj, struct thread *thread )
{
    struct thread *mythread = (struct thread *)obj;
    return (mythread->state == TERMINATED);
}

291 292 293 294 295 296 297 298 299
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);
}

300 301 302 303 304
static void dump_thread_apc( struct object *obj, int verbose )
{
    struct thread_apc *apc = (struct thread_apc *)obj;
    assert( obj->ops == &thread_apc_ops );

305
    fprintf( stderr, "APC owner=%p type=%u\n", apc->owner, apc->call.type );
306 307 308 309
}

static int thread_apc_signaled( struct object *obj, struct thread *thread )
{
310 311
    struct thread_apc *apc = (struct thread_apc *)obj;
    return apc->executed;
312 313
}

Alexandre Julliard's avatar
Alexandre Julliard committed
314
/* get a thread pointer from a thread id (and increment the refcount) */
315
struct thread *get_thread_from_id( thread_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
316
{
317 318 319
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &thread_ops) return (struct thread *)grab_object( obj );
320
    set_error( STATUS_INVALID_CID );
321
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
322 323
}

Alexandre Julliard's avatar
Alexandre Julliard committed
324
/* get a thread from a handle (and increment the refcount) */
325
struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
326
{
Alexandre Julliard's avatar
Alexandre Julliard committed
327 328
    return (struct thread *)get_handle_obj( current->process, handle,
                                            access, &thread_ops );
Alexandre Julliard's avatar
Alexandre Julliard committed
329 330
}

331 332
/* find a thread from a Unix tid */
struct thread *get_thread_from_tid( int tid )
333
{
334
    struct thread *thread;
335

336 337
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
338
        if (thread->unix_tid == tid) return thread;
339
    }
340 341 342 343 344 345 346 347
    return NULL;
}

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

348 349 350 351
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
        if (thread->unix_pid == pid) return thread;
    }
352
    return NULL;
353 354
}

355
/* set all information about a thread */
356
static void set_thread_info( struct thread *thread,
357
                             const struct set_thread_info_request *req )
358 359 360 361 362
{
    if (req->mask & SET_THREAD_INFO_PRIORITY)
        thread->priority = req->priority;
    if (req->mask & SET_THREAD_INFO_AFFINITY)
    {
363
        if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
364 365
        else thread->affinity = req->affinity;
    }
366 367
    if (req->mask & SET_THREAD_INFO_TOKEN)
        security_set_thread_token( thread, req->token );
368 369
}

370 371 372
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
373
    if (thread->context) return;  /* already inside a debug event, no need for a signal */
374 375 376 377
    /* can't stop a thread while initialisation is in progress */
    if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
}

378
/* suspend a thread */
379
static int suspend_thread( struct thread *thread )
380 381
{
    int old_count = thread->suspend;
382
    if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
383
    {
384
        if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
385
    }
386
    else set_error( STATUS_SUSPEND_COUNT_EXCEEDED );
387 388 389 390
    return old_count;
}

/* resume a thread */
391
static int resume_thread( struct thread *thread )
392 393 394 395
{
    int old_count = thread->suspend;
    if (thread->suspend > 0)
    {
396
        if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
397 398
    }
    return old_count;
Alexandre Julliard's avatar
Alexandre Julliard committed
399 400 401
}

/* add a thread to an object wait queue; return 1 if OK, 0 on error */
402
int add_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
403
{
404
    grab_object( obj );
405 406
    entry->obj = obj;
    list_add_tail( &obj->wait_queue, &entry->entry );
407
    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
408 409 410
}

/* remove a thread from an object wait queue */
411
void remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
412
{
413
    list_remove( &entry->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
414 415 416 417 418 419 420 421 422 423 424
    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 );
425 426
    for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        entry->obj->ops->remove_queue( entry->obj, entry );
427
    if (wait->user) remove_timeout_user( wait->user );
428
    thread->wait = wait->next;
Alexandre Julliard's avatar
Alexandre Julliard committed
429 430 431 432
    free( wait );
}

/* build the thread wait structure */
433
static int wait_on( int count, struct object *objects[], int flags, const abs_time_t *timeout )
Alexandre Julliard's avatar
Alexandre Julliard committed
434 435 436 437 438
{
    struct thread_wait *wait;
    struct wait_queue_entry *entry;
    int i;

Alexandre Julliard's avatar
Alexandre Julliard committed
439
    if (!(wait = mem_alloc( sizeof(*wait) + (count-1) * sizeof(*entry) ))) return 0;
440 441
    wait->next    = current->wait;
    wait->thread  = current;
Alexandre Julliard's avatar
Alexandre Julliard committed
442 443
    wait->count   = count;
    wait->flags   = flags;
444
    wait->user    = NULL;
445
    current->wait = wait;
446 447
    if (flags & SELECT_TIMEOUT)
    {
448 449
        wait->timeout.tv_sec  = timeout->sec;
        wait->timeout.tv_usec = timeout->usec;
450
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
451 452 453

    for (i = 0, entry = wait->queues; i < count; i++, entry++)
    {
454 455
        struct object *obj = objects[i];
        entry->thread = current;
456 457
        if (!obj->ops->add_queue( obj, entry ))
        {
458 459
            wait->count = i;
            end_wait( current );
460 461
            return 0;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
462 463 464 465 466
    }
    return 1;
}

/* check if the thread waiting condition is satisfied */
467
static int check_wait( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
468
{
469
    int i, signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
470 471 472
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry = wait->queues;

473
    /* Suspended threads may not acquire locks */
474
    if (thread->process->suspend + thread->suspend > 0) return -1;
475

Alexandre Julliard's avatar
Alexandre Julliard committed
476 477 478
    assert( wait );
    if (wait->flags & SELECT_ALL)
    {
479 480 481
        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
482
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
483 484
            not_ok |= !entry->obj->ops->signaled( entry->obj, thread );
        if (not_ok) goto other_checks;
Alexandre Julliard's avatar
Alexandre Julliard committed
485
        /* Wait satisfied: tell it to all objects */
486
        signaled = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
487 488
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
            if (entry->obj->ops->satisfied( entry->obj, thread ))
489 490
                signaled = STATUS_ABANDONED_WAIT_0;
        return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
491 492 493 494 495 496 497
    }
    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 */
498
            signaled = i;
Alexandre Julliard's avatar
Alexandre Julliard committed
499
            if (entry->obj->ops->satisfied( entry->obj, thread ))
500 501
                signaled = i + STATUS_ABANDONED_WAIT_0;
            return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
502 503
        }
    }
504 505

 other_checks:
506 507
    if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty(&thread->system_apc)) return STATUS_USER_APC;
    if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
508 509
    if (wait->flags & SELECT_TIMEOUT)
    {
510
        if (!time_before( &current_time, &wait->timeout )) return STATUS_TIMEOUT;
511
    }
512 513 514
    return -1;
}

515 516 517 518 519 520 521 522
/* 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;
523 524
    if ((ret = write( get_unix_fd( thread->wait_fd ), &reply, sizeof(reply) )) == sizeof(reply))
        return 0;
525 526 527 528 529 530 531 532 533
    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
534
/* attempt to wake up a thread */
535
/* return >0 if OK, 0 if the wait condition is still not satisfied */
536
int wake_thread( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
537
{
538 539
    int signaled, count;
    void *cookie;
540

541 542 543 544 545
    for (count = 0; thread->wait; count++)
    {
        if ((signaled = check_wait( thread )) == -1) break;

        cookie = thread->wait->cookie;
546 547
        if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
                                  thread->id, signaled, cookie );
548
        end_wait( thread );
549 550
        if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
	    break;
551 552
    }
    return count;
Alexandre Julliard's avatar
Alexandre Julliard committed
553 554
}

555 556 557
/* thread wait timeout */
static void thread_timeout( void *ptr )
{
558 559 560
    struct thread_wait *wait = ptr;
    struct thread *thread = wait->thread;
    void *cookie = wait->cookie;
561

562 563
    wait->user = NULL;
    if (thread->wait != wait) return; /* not the top-level wait, ignore it */
564
    if (thread->suspend + thread->process->suspend > 0) return;  /* suspended, ignore it */
565

566
    if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
567
                              thread->id, (int)STATUS_TIMEOUT, cookie );
568
    end_wait( thread );
569
    if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
570 571
    /* check if other objects have become signaled in the meantime */
    wake_thread( thread );
572 573
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
/* 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;
}

589
/* select on a list of handles */
590
static void select_on( int count, void *cookie, const obj_handle_t *handles,
591
                       int flags, const abs_time_t *timeout, obj_handle_t signal_obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
592
{
593
    int ret, i;
594
    struct object *objects[MAXIMUM_WAIT_OBJECTS];
595

596 597
    if ((count < 0) || (count > MAXIMUM_WAIT_OBJECTS))
    {
598
        set_error( STATUS_INVALID_PARAMETER );
599
        return;
600 601 602 603 604 605
    }
    for (i = 0; i < count; i++)
    {
        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
            break;
    }
606 607

    if (i < count) goto done;
608
    if (!wait_on( count, objects, flags, timeout )) goto done;
609

610 611 612 613 614 615 616 617 618 619 620 621
    /* 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;
    }

622 623 624 625 626 627 628 629 630 631 632 633
    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,
634
                                                      thread_timeout, current->wait )))
635 636 637 638 639
        {
            end_wait( current );
            goto done;
        }
    }
640
    current->wait->cookie = cookie;
641 642 643
    set_error( STATUS_PENDING );

done:
644
    while (--i >= 0) release_object( objects[i] );
Alexandre Julliard's avatar
Alexandre Julliard committed
645 646 647 648 649
}

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

652
    LIST_FOR_EACH_SAFE( ptr, next, &obj->wait_queue )
Alexandre Julliard's avatar
Alexandre Julliard committed
653
    {
654 655
        struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
        if (wake_thread( entry->thread ))
Alexandre Julliard's avatar
Alexandre Julliard committed
656 657 658 659 660 661
        {
            if (max && !--max) break;
        }
    }
}

662 663 664 665 666 667 668 669 670 671 672 673 674 675
/* 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;
    }
}

676
/* queue an async procedure call */
677
int thread_queue_apc( struct thread *thread, struct object *owner, const apc_call_t *call_data )
678 679
{
    struct thread_apc *apc;
680
    struct list *queue = get_apc_queue( thread, call_data->type );
681 682

    /* cancel a possible previous APC with the same owner */
683
    if (owner) thread_cancel_apc( thread, owner, call_data->type );
684
    if (thread->state == TERMINATED) return 0;
685

686
    if (!(apc = alloc_object( &thread_apc_ops ))) return 0;
687 688
    apc->call     = *call_data;
    apc->owner    = owner;
689
    apc->executed = 0;
690 691
    list_add_tail( queue, &apc->entry );
    if (!list_prev( queue, &apc->entry ))  /* first one */
692
        wake_thread( thread );
693

694 695 696
    return 1;
}

697
/* cancel the async procedure call owned by a specific object */
698
void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_type type )
699 700
{
    struct thread_apc *apc;
701 702
    struct list *queue = get_apc_queue( thread, type );

703
    LIST_FOR_EACH_ENTRY( apc, queue, struct thread_apc, entry )
704 705
    {
        if (apc->owner != owner) continue;
706
        list_remove( &apc->entry );
707
        release_object( apc );
708 709 710 711 712
        return;
    }
}

/* remove the head apc from the queue; the returned pointer must be freed by the caller */
713
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
714
{
715 716
    struct thread_apc *apc = NULL;
    struct list *ptr = list_head( &thread->system_apc );
717

718 719
    if (!ptr && !system_only) ptr = list_head( &thread->user_apc );
    if (ptr)
720
    {
721 722
        apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( ptr );
723 724 725 726
    }
    return apc;
}

727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
/* 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
783
/* kill a thread on the spot */
784
void kill_thread( struct thread *thread, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
785
{
Alexandre Julliard's avatar
Alexandre Julliard committed
786
    if (thread->state == TERMINATED) return;  /* already killed */
Alexandre Julliard's avatar
Alexandre Julliard committed
787
    thread->state = TERMINATED;
788
    thread->exit_time = current_time;
789
    if (current == thread) current = NULL;
790
    if (debug_level)
791 792
        fprintf( stderr,"%04x: *killed* exit_code=%d\n",
                 thread->id, thread->exit_code );
793 794
    if (thread->wait)
    {
795 796
        while (thread->wait) end_wait( thread );
        send_thread_wakeup( thread, NULL, STATUS_PENDING );
797 798 799
        /* if it is waiting on the socket, we don't need to send a SIGTERM */
        violent_death = 0;
    }
800
    kill_console_processes( thread, 0 );
801
    debug_exit_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
802
    abandon_mutexes( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
803
    wake_up( &thread->obj, 0 );
804
    if (violent_death) send_thread_signal( thread, SIGTERM );
805
    cleanup_thread( thread );
806
    remove_process_thread( thread->process, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
807
    release_object( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
808
}
809

810 811 812 813 814 815 816
/* trigger a breakpoint event in a given thread */
void break_thread( struct thread *thread )
{
    struct debug_event_exception data;

    assert( thread->context );

817
    data.record.ExceptionCode    = STATUS_BREAKPOINT;
818 819 820 821 822 823 824 825 826
    data.record.ExceptionFlags   = EXCEPTION_CONTINUABLE;
    data.record.ExceptionRecord  = NULL;
    data.record.ExceptionAddress = get_context_ip( thread->context );
    data.record.NumberParameters = 0;
    data.first = 1;
    generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
    thread->debug_break = 0;
}

827 828 829 830 831 832 833
/* 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;

834
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
835 836 837
        if (thread->state != TERMINATED) total++;
    if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
    ptr = snapshot;
838
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
839 840 841 842 843 844 845 846 847 848 849 850
    {
        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;
}

851 852 853 854 855 856 857 858 859
/* 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;
}

860 861 862
/* create a new thread */
DECL_HANDLER(new_thread)
{
863
    struct thread *thread;
864
    int request_fd = thread_get_inflight_fd( current, req->request_fd );
865

866
    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
867
    {
868
        if (request_fd != -1) close( request_fd );
869 870 871 872 873 874 875
        set_error( STATUS_INVALID_HANDLE );
        return;
    }

    if ((thread = create_thread( request_fd, current->process )))
    {
        if (req->suspend) thread->suspend++;
876
        reply->tid = get_thread_id( thread );
877
        if ((reply->handle = alloc_handle( current->process, thread, req->access, req->attributes )))
878
        {
879 880
            /* thread object will be released when the thread gets killed */
            return;
881
        }
882
        kill_thread( thread, 1 );
883 884 885 886 887 888
    }
}

/* initialize a new thread */
DECL_HANDLER(init_thread)
{
889
    struct process *process = current->process;
890 891 892
    int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
    int wait_fd = thread_get_inflight_fd( current, req->wait_fd );

893
    if (current->reply_fd)  /* already initialised */
894
    {
895
        set_error( STATUS_INVALID_PARAMETER );
896 897
        goto error;
    }
898 899 900 901 902 903 904

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

    current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj );
    reply_fd = -1;
    if (!current->reply_fd) goto error;

905 906
    if (wait_fd == -1)
    {
907 908
        set_error( STATUS_TOO_MANY_OPENED_FILES );  /* most likely reason */
        return;
909 910 911
    }
    if (!(current->wait_fd  = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj )))
        return;
912

913 914 915 916 917 918
    if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }

919
    current->unix_pid = req->unix_pid;
920
    current->unix_tid = req->unix_tid;
921
    current->teb      = req->teb;
922

923 924
    if (!process->peb)  /* first thread, initialize the process too */
    {
925
        process->unix_pid = current->unix_pid;
926 927
        process->peb      = req->peb;
        process->ldt_copy = req->ldt_copy;
928
        reply->info_size  = init_process( current );
929 930 931
    }
    else
    {
932 933
        if (process->unix_pid != current->unix_pid)
            process->unix_pid = -1;  /* can happen with linuxthreads */
934
        if (current->suspend + process->suspend > 0) stop_thread( current );
935
        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
936 937
    }
    debug_level = max( debug_level, req->debug_level );
938

939
    reply->pid     = get_process_id( process );
940 941
    reply->tid     = get_thread_id( current );
    reply->version = SERVER_PROTOCOL_VERSION;
942 943
    reply->server_start.sec  = server_start_time.tv_sec;
    reply->server_start.usec = server_start_time.tv_usec;
944 945 946 947 948 949 950
    return;

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

951 952 953 954 955
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
    struct thread *thread;

956 957
    reply->self = 0;
    reply->last = 0;
958 959
    if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
    {
960 961 962 963
        thread->exit_code = req->exit_code;
        if (thread != current) kill_thread( thread, 1 );
        else
        {
964 965
            reply->self = 1;
            reply->last = (thread->process->running_threads == 1);
966
        }
967 968 969 970
        release_object( thread );
    }
}

971 972 973 974 975 976 977 978
/* open a handle to a thread */
DECL_HANDLER(open_thread)
{
    struct thread *thread = get_thread_from_id( req->tid );

    reply->handle = 0;
    if (thread)
    {
979
        reply->handle = alloc_handle( current->process, thread, req->access, req->attributes );
980 981 982 983
        release_object( thread );
    }
}

984 985 986 987
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
    struct thread *thread;
988
    obj_handle_t handle = req->handle;
989

990
    if (!handle) thread = get_thread_from_id( req->tid_in );
991 992 993
    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );

    if (thread)
994
    {
995
        reply->pid            = get_process_id( thread->process );
996 997
        reply->tid            = get_thread_id( thread );
        reply->teb            = thread->teb;
998
        reply->exit_code      = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING;
999
        reply->priority       = thread->priority;
1000
        reply->affinity       = thread->affinity;
1001 1002
        reply->creation_time.sec  = thread->creation_time.tv_sec;
        reply->creation_time.usec = thread->creation_time.tv_usec;
1003 1004 1005
        reply->exit_time.sec  = thread->exit_time.tv_sec;
        reply->exit_time.usec = thread->exit_time.tv_usec;
        reply->last           = thread->process->running_threads == 1;
1006

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
        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;
1027

1028 1029
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1030
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
1031
        else reply->count = suspend_thread( thread );
1032 1033 1034 1035 1036 1037 1038 1039
        release_object( thread );
    }
}

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

1041 1042
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1043 1044
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
        else reply->count = resume_thread( thread );
1045 1046 1047 1048 1049 1050 1051
        release_object( thread );
    }
}

/* select on a handle list */
DECL_HANDLER(select)
{
1052
    int count = get_req_data_size() / sizeof(obj_handle_t);
1053
    select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout, req->signal );
1054 1055 1056 1057 1058 1059 1060 1061
}

/* queue an APC for a thread */
DECL_HANDLER(queue_apc)
{
    struct thread *thread;
    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
    {
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
        switch( req->call.type )
        {
        case APC_NONE:
        case APC_USER:
            thread_queue_apc( thread, NULL, &req->call );
            break;
        default:
            set_error( STATUS_INVALID_PARAMETER );
            break;
        }
1072 1073 1074
        release_object( thread );
    }
}
1075

1076 1077
/* get next APC to call */
DECL_HANDLER(get_apc)
1078
{
1079 1080
    struct thread_apc *apc;

1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
    if (req->prev)
    {
        if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->prev,
                                                         0, &thread_apc_ops ))) return;
        apc->executed = 1;
        wake_up( &apc->obj, 0 );
        close_handle( current->process, req->prev );
        release_object( apc );
    }

1091
    for (;;)
1092
    {
1093
        if (!(apc = thread_dequeue_apc( current, !req->alertable )))
1094 1095
        {
            /* no more APCs */
1096
            set_error( STATUS_PENDING );
1097 1098
            return;
        }
1099 1100
        /* Optimization: ignore APC_NONE calls, they are only used to
         * wake up a thread, but since we got here the thread woke up already.
1101
         */
1102
        if (apc->call.type != APC_NONE) break;
1103
        release_object( apc );
1104
    }
1105 1106

    if ((reply->handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
1107
        reply->call = apc->call;
1108
    release_object( apc );
1109
}
1110

1111 1112 1113 1114
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{
    struct thread *thread;
1115
    CONTEXT *context;
1116 1117 1118 1119 1120 1121 1122 1123

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

1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
    if (req->suspend)
    {
        if (thread != current || !thread->suspend_context)
        {
            /* not suspended, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else
        {
            if (thread->context == thread->suspend_context) thread->context = NULL;
            set_reply_data_ptr( thread->suspend_context, sizeof(CONTEXT) );
            thread->suspend_context = NULL;
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
1144
    else if ((context = set_reply_data_size( sizeof(CONTEXT) )))
1145
    {
1146 1147 1148 1149 1150 1151
        unsigned int flags = get_context_system_regs( req->flags );

        memset( context, 0, sizeof(CONTEXT) );
        context->ContextFlags = get_context_cpu_flag();
        if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
        if (flags) get_thread_context( thread, context, flags );
1152
    }
1153
    reply->self = (thread == current);
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
    release_object( thread );
}

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

    if (get_req_data_size() < sizeof(CONTEXT))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    if (!(thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) return;

    if (req->suspend)
    {
        if (thread != current || thread->context)
        {
            /* nested suspend or exception, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else if ((thread->suspend_context = mem_alloc( sizeof(CONTEXT) )))
        {
            memcpy( thread->suspend_context, get_req_data(), sizeof(CONTEXT) );
            thread->context = thread->suspend_context;
1180
            if (thread->debug_break) break_thread( thread );
1181 1182 1183 1184 1185 1186 1187 1188 1189
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
    else
1190
    {
1191 1192 1193 1194 1195 1196
        const CONTEXT *context = get_req_data();
        unsigned int flags = get_context_system_regs( req->flags );

        if (flags) set_thread_context( thread, context, flags );
        if (thread->context && !get_error())
            copy_context( thread->context, context, req->flags & ~flags );
1197
    }
1198
    reply->self = (thread == current);
1199
    release_object( thread );
1200 1201
}

1202 1203 1204 1205 1206 1207
/* 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 )))
    {
1208
        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
1209 1210 1211
        release_object( thread );
    }
}