blob: 6b2caecb01aeb619cbfb6312ccd98d9e67542ca4 [file] [log] [blame]
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001/*
2 * Server-side semaphore management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
5 */
6
7#include <assert.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11#include "winerror.h"
12#include "winnt.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000013
14#include "handle.h"
15#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000016#include "request.h"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000017
18struct semaphore
19{
20 struct object obj; /* object header */
21 unsigned int count; /* current count */
22 unsigned int max; /* maximum possible count */
23};
24
Alexandre Julliard338e7571998-12-27 15:28:54 +000025static void semaphore_dump( struct object *obj, int verbose );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000026static int semaphore_signaled( struct object *obj, struct thread *thread );
27static int semaphore_satisfied( struct object *obj, struct thread *thread );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000028
29static const struct object_ops semaphore_ops =
30{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000031 sizeof(struct semaphore),
Alexandre Julliard338e7571998-12-27 15:28:54 +000032 semaphore_dump,
Alexandre Julliardc6e45ed1998-12-27 08:35:39 +000033 add_queue,
34 remove_queue,
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000035 semaphore_signaled,
36 semaphore_satisfied,
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000037 no_read_fd,
38 no_write_fd,
39 no_flush,
Alexandre Julliard05625391999-01-03 11:55:56 +000040 no_get_file_info,
Alexandre Julliard5bc78081999-06-22 17:26:53 +000041 no_destroy
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000042};
43
44
Alexandre Julliard5bc78081999-06-22 17:26:53 +000045static struct semaphore *create_semaphore( const char *name, size_t len,
46 unsigned int initial, unsigned int max )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000047{
48 struct semaphore *sem;
49
50 if (!max || (initial > max))
51 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000052 set_error( ERROR_INVALID_PARAMETER );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000053 return NULL;
54 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000055 if ((sem = create_named_object( &semaphore_ops, name, len )))
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000056 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000057 if (get_error() != ERROR_ALREADY_EXISTS)
58 {
59 /* initialize it if it didn't already exist */
60 sem->count = initial;
61 sem->max = max;
62 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000063 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000064 return sem;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000065}
66
Alexandre Julliard5bc78081999-06-22 17:26:53 +000067static void release_semaphore( int handle, unsigned int count, unsigned int *prev_count )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000068{
69 struct semaphore *sem;
70
71 if (!(sem = (struct semaphore *)get_handle_obj( current->process, handle,
72 SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
Alexandre Julliard5bc78081999-06-22 17:26:53 +000073 return;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000074
75 *prev_count = sem->count;
76 if (sem->count + count < sem->count || sem->count + count > sem->max)
77 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000078 set_error( ERROR_TOO_MANY_POSTS );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000079 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000080 else if (sem->count)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000081 {
82 /* there cannot be any thread waiting if the count is != 0 */
83 assert( !sem->obj.head );
84 sem->count += count;
85 }
86 else
87 {
88 sem->count = count;
89 wake_up( &sem->obj, count );
90 }
91 release_object( sem );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000092}
93
Alexandre Julliard338e7571998-12-27 15:28:54 +000094static void semaphore_dump( struct object *obj, int verbose )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000095{
96 struct semaphore *sem = (struct semaphore *)obj;
97 assert( obj->ops == &semaphore_ops );
Alexandre Julliard05625391999-01-03 11:55:56 +000098 fprintf( stderr, "Semaphore count=%d max=%d name='%s'\n",
99 sem->count, sem->max, get_object_name( &sem->obj ) );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000100}
101
102static int semaphore_signaled( struct object *obj, struct thread *thread )
103{
104 struct semaphore *sem = (struct semaphore *)obj;
105 assert( obj->ops == &semaphore_ops );
106 return (sem->count > 0);
107}
108
109static int semaphore_satisfied( struct object *obj, struct thread *thread )
110{
111 struct semaphore *sem = (struct semaphore *)obj;
112 assert( obj->ops == &semaphore_ops );
113 assert( sem->count );
114 sem->count--;
115 return 0; /* not abandoned */
116}
117
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000118/* create a semaphore */
119DECL_HANDLER(create_semaphore)
120{
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000121 size_t len = get_req_strlen();
122 struct create_semaphore_reply *reply = push_reply_data( current, sizeof(*reply) );
123 struct semaphore *sem;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000124
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000125 if ((sem = create_semaphore( get_req_data( len + 1 ), len, req->initial, req->max )))
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000126 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000127 reply->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
128 release_object( sem );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000129 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000130 else reply->handle = -1;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000131}
132
133/* open a handle to a semaphore */
134DECL_HANDLER(open_semaphore)
135{
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000136 size_t len = get_req_strlen();
137 struct open_semaphore_reply *reply = push_reply_data( current, sizeof(*reply) );
138 reply->handle = open_object( get_req_data( len + 1 ), len, &semaphore_ops,
139 req->access, req->inherit );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000140}
141
142/* release a semaphore */
143DECL_HANDLER(release_semaphore)
144{
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000145 struct release_semaphore_reply *reply = push_reply_data( current, sizeof(*reply) );
146 release_semaphore( req->handle, req->count, &reply->prev_count );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000147}