Added support for a WINELOADER environment variable which allows the
[wine] / server / queue.c
1 /*
2  * Server-side message queues
3  *
4  * Copyright (C) 2000 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "handle.h"
12 #include "thread.h"
13 #include "process.h"
14 #include "request.h"
15
16 struct msg_queue
17 {
18     struct object  obj;             /* object header */
19     struct thread *thread;          /* thread owning this queue */
20     int            signaled;        /* queue has been signaled */
21 };
22
23 static void msg_queue_dump( struct object *obj, int verbose );
24 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
25 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
26 static int msg_queue_signaled( struct object *obj, struct thread *thread );
27 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
28
29 static const struct object_ops msg_queue_ops =
30 {
31     sizeof(struct msg_queue),  /* size */
32     msg_queue_dump,            /* dump */
33     msg_queue_add_queue,       /* add_queue */
34     msg_queue_remove_queue,    /* remove_queue */
35     msg_queue_signaled,        /* signaled */
36     msg_queue_satisfied,       /* satisfied */
37     NULL,                      /* get_poll_events */
38     NULL,                      /* poll_event */
39     no_read_fd,                /* get_read_fd */
40     no_write_fd,               /* get_write_fd */
41     no_flush,                  /* flush */
42     no_get_file_info,          /* get_file_info */
43     no_destroy                 /* destroy */
44 };
45
46
47 static struct msg_queue *create_msg_queue( struct thread *thread )
48 {
49     struct msg_queue *queue;
50
51     if ((queue = alloc_object( &msg_queue_ops, -1 )))
52     {
53         queue->signaled = 0;
54         queue->thread = thread;
55         thread->queue = queue;
56         if (!thread->process->queue)
57             thread->process->queue = (struct msg_queue *)grab_object( queue );
58     }
59     return queue;
60 }
61
62 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
63 {
64     struct msg_queue *queue = (struct msg_queue *)obj;
65     struct process *process = entry->thread->process;
66
67     /* if waiting on the main process queue, set the idle event */
68     if (entry->thread == queue->thread && process->queue == queue)
69     {
70         if (process->idle_event) set_event( process->idle_event );
71     }
72     add_queue( obj, entry );
73     return 1;
74 }
75
76 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
77 {
78     struct msg_queue *queue = (struct msg_queue *)obj;
79     struct process *process = entry->thread->process;
80
81     remove_queue( obj, entry );
82
83     /* if waiting on the main process queue, reset the idle event */
84     if (entry->thread == queue->thread && process->queue == queue)
85     {
86         if (process->idle_event) reset_event( process->idle_event );
87     }
88 }
89
90 static void msg_queue_dump( struct object *obj, int verbose )
91 {
92     struct msg_queue *queue = (struct msg_queue *)obj;
93     fprintf( stderr, "Msg queue signaled=%d owner=%p\n", queue->signaled, queue->thread );
94 }
95
96 static int msg_queue_signaled( struct object *obj, struct thread *thread )
97 {
98     struct msg_queue *queue = (struct msg_queue *)obj;
99     return queue->signaled;
100 }
101
102 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
103 {
104     struct msg_queue *queue = (struct msg_queue *)obj;
105     queue->signaled = 0;
106     return 0;  /* Not abandoned */
107 }
108
109 /* get the message queue of the current thread */
110 DECL_HANDLER(get_msg_queue)
111 {
112     struct msg_queue *queue = current->queue;
113
114     req->handle = -1;
115     if (!queue) queue = create_msg_queue( current );
116     if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
117 }
118
119 /* wake up a message queue */
120 DECL_HANDLER(wake_queue)
121 {
122     struct msg_queue *queue = (struct msg_queue *)get_handle_obj( current->process, req->handle,
123                                                                   0, &msg_queue_ops );
124     if (queue)
125     {
126         queue->signaled = 1;
127         wake_up( &queue->obj, 0 );
128         release_object( queue );
129     }
130 }