Implemented waitable timers.
[wine/multimedia.git] / server / pipe.c
blob5459f3e094895d1ffb27545e59f5989aacca9846
1 /*
2 * Server-side pipe management
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #ifdef HAVE_SYS_ERRNO_H
15 #include <sys/errno.h>
16 #endif
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <time.h>
21 #include <unistd.h>
23 #include "winerror.h"
24 #include "winbase.h"
26 #include "handle.h"
27 #include "thread.h"
28 #include "request.h"
30 enum side { READ_SIDE, WRITE_SIDE };
32 struct pipe
34 struct object obj; /* object header */
35 struct pipe *other; /* the pipe other end */
36 struct select_user select; /* select user */
37 enum side side; /* which side of the pipe is this */
40 static void pipe_dump( struct object *obj, int verbose );
41 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
42 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
43 static int pipe_signaled( struct object *obj, struct thread *thread );
44 static int pipe_get_read_fd( struct object *obj );
45 static int pipe_get_write_fd( struct object *obj );
46 static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
47 static void pipe_destroy( struct object *obj );
49 static const struct object_ops pipe_ops =
51 sizeof(struct pipe),
52 pipe_dump,
53 pipe_add_queue,
54 pipe_remove_queue,
55 pipe_signaled,
56 no_satisfied,
57 pipe_get_read_fd,
58 pipe_get_write_fd,
59 no_flush,
60 pipe_get_info,
61 pipe_destroy
65 static struct pipe *create_pipe_side( int fd, int side )
67 struct pipe *pipe;
69 if ((pipe = alloc_object( &pipe_ops )))
71 pipe->select.fd = fd;
72 pipe->select.func = default_select_event;
73 pipe->select.private = pipe;
74 pipe->other = NULL;
75 pipe->side = side;
76 register_select_user( &pipe->select );
78 return pipe;
81 static int create_pipe( struct object *obj[2] )
83 struct pipe *read_pipe;
84 struct pipe *write_pipe;
85 int fd[2];
87 if (pipe( fd ) == -1)
89 file_set_error();
90 return 0;
92 if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
94 if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
96 write_pipe->other = read_pipe;
97 read_pipe->other = write_pipe;
98 obj[0] = &read_pipe->obj;
99 obj[1] = &write_pipe->obj;
100 return 1;
102 release_object( read_pipe );
104 close( fd[0] );
105 close( fd[1] );
106 return 0;
109 static void pipe_dump( struct object *obj, int verbose )
111 struct pipe *pipe = (struct pipe *)obj;
112 assert( obj->ops == &pipe_ops );
113 fprintf( stderr, "Pipe %s-side fd=%d\n",
114 (pipe->side == READ_SIDE) ? "read" : "write", pipe->select.fd );
117 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
119 struct pipe *pipe = (struct pipe *)obj;
120 assert( obj->ops == &pipe_ops );
121 if (!obj->head) /* first on the queue */
122 set_select_events( &pipe->select,
123 (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT );
124 add_queue( obj, entry );
125 return 1;
128 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
130 struct pipe *pipe = (struct pipe *)grab_object(obj);
131 assert( obj->ops == &pipe_ops );
133 remove_queue( obj, entry );
134 if (!obj->head) /* last on the queue is gone */
135 set_select_events( &pipe->select, 0 );
136 release_object( obj );
139 static int pipe_signaled( struct object *obj, struct thread *thread )
141 int event;
142 struct pipe *pipe = (struct pipe *)obj;
143 assert( obj->ops == &pipe_ops );
145 event = (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT;
146 if (check_select_events( &pipe->select, event ))
148 /* stop waiting on select() if we are signaled */
149 set_select_events( &pipe->select, 0 );
150 return 1;
152 else
154 /* restart waiting on select() if we are no longer signaled */
155 if (obj->head) set_select_events( &pipe->select, event );
156 return 0;
160 static int pipe_get_read_fd( struct object *obj )
162 struct pipe *pipe = (struct pipe *)obj;
163 assert( obj->ops == &pipe_ops );
165 if (!pipe->other)
167 set_error( ERROR_BROKEN_PIPE );
168 return -1;
170 if (pipe->side != READ_SIDE) /* FIXME: should not be necessary */
172 set_error( ERROR_ACCESS_DENIED );
173 return -1;
175 return dup( pipe->select.fd );
178 static int pipe_get_write_fd( struct object *obj )
180 struct pipe *pipe = (struct pipe *)obj;
181 assert( obj->ops == &pipe_ops );
183 if (!pipe->other)
185 set_error( ERROR_BROKEN_PIPE );
186 return -1;
188 if (pipe->side != WRITE_SIDE) /* FIXME: should not be necessary */
190 set_error( ERROR_ACCESS_DENIED );
191 return -1;
193 return dup( pipe->select.fd );
196 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
198 req->type = FILE_TYPE_PIPE;
199 req->attr = 0;
200 req->access_time = 0;
201 req->write_time = 0;
202 req->size_high = 0;
203 req->size_low = 0;
204 req->links = 0;
205 req->index_high = 0;
206 req->index_low = 0;
207 req->serial = 0;
208 return 1;
211 static void pipe_destroy( struct object *obj )
213 struct pipe *pipe = (struct pipe *)obj;
214 assert( obj->ops == &pipe_ops );
216 if (pipe->other) pipe->other->other = NULL;
217 unregister_select_user( &pipe->select );
218 close( pipe->select.fd );
221 /* create an anonymous pipe */
222 DECL_HANDLER(create_pipe)
224 struct object *obj[2];
225 int hread = -1, hwrite = -1;
227 if (create_pipe( obj ))
229 hread = alloc_handle( current->process, obj[0],
230 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
231 req->inherit );
232 if (hread != -1)
234 hwrite = alloc_handle( current->process, obj[1],
235 STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
236 req->inherit );
237 if (hwrite == -1)
238 close_handle( current->process, hread );
240 release_object( obj[0] );
241 release_object( obj[1] );
243 req->handle_read = hread;
244 req->handle_write = hwrite;