blob: 221d5333afb221ef0cce9a4801e23df84791ab10 [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 Julliard1dca5e22000-01-01 00:56:27 +000031 sizeof(struct semaphore), /* size */
32 semaphore_dump, /* dump */
33 add_queue, /* add_queue */
34 remove_queue, /* remove_queue */
35 semaphore_signaled, /* signaled */
36 semaphore_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 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000044};
45
46
Alexandre Julliardd16319c1999-11-25 21:30:24 +000047static struct semaphore *create_semaphore( const WCHAR *name, size_t len,
Alexandre Julliard5bc78081999-06-22 17:26:53 +000048 unsigned int initial, unsigned int max )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000049{
50 struct semaphore *sem;
51
52 if (!max || (initial > max))
53 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000054 set_error( ERROR_INVALID_PARAMETER );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000055 return NULL;
56 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000057 if ((sem = create_named_object( &semaphore_ops, name, len )))
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000058 {
Alexandre Julliard5bc78081999-06-22 17:26:53 +000059 if (get_error() != ERROR_ALREADY_EXISTS)
60 {
61 /* initialize it if it didn't already exist */
62 sem->count = initial;
63 sem->max = max;
64 }
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000065 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +000066 return sem;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000067}
68
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000069static unsigned int release_semaphore( int handle, unsigned int count )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000070{
71 struct semaphore *sem;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000072 unsigned int prev = 0;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000073
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000074 if ((sem = (struct semaphore *)get_handle_obj( current->process, handle,
75 SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000076 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000077 prev = sem->count;
78 if (sem->count + count < sem->count || sem->count + count > sem->max)
79 {
80 set_error( ERROR_TOO_MANY_POSTS );
81 }
82 else if (sem->count)
83 {
84 /* there cannot be any thread waiting if the count is != 0 */
85 assert( !sem->obj.head );
86 sem->count += count;
87 }
88 else
89 {
90 sem->count = count;
91 wake_up( &sem->obj, count );
92 }
93 release_object( sem );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000094 }
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000095 return prev;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000096}
97
Alexandre Julliard338e7571998-12-27 15:28:54 +000098static void semaphore_dump( struct object *obj, int verbose )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000099{
100 struct semaphore *sem = (struct semaphore *)obj;
101 assert( obj->ops == &semaphore_ops );
Alexandre Julliardd16319c1999-11-25 21:30:24 +0000102 fprintf( stderr, "Semaphore count=%d max=%d ", sem->count, sem->max );
103 dump_object_name( &sem->obj );
104 fputc( '\n', stderr );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000105}
106
107static int semaphore_signaled( struct object *obj, struct thread *thread )
108{
109 struct semaphore *sem = (struct semaphore *)obj;
110 assert( obj->ops == &semaphore_ops );
111 return (sem->count > 0);
112}
113
114static int semaphore_satisfied( struct object *obj, struct thread *thread )
115{
116 struct semaphore *sem = (struct semaphore *)obj;
117 assert( obj->ops == &semaphore_ops );
118 assert( sem->count );
119 sem->count--;
120 return 0; /* not abandoned */
121}
122
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000123/* create a semaphore */
124DECL_HANDLER(create_semaphore)
125{
Alexandre Julliardd16319c1999-11-25 21:30:24 +0000126 size_t len = get_req_strlenW( req->name );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000127 struct semaphore *sem;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000128
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000129 req->handle = -1;
130 if ((sem = create_semaphore( req->name, len, req->initial, req->max )))
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000131 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000132 req->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000133 release_object( sem );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000134 }
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000135}
136
137/* open a handle to a semaphore */
138DECL_HANDLER(open_semaphore)
139{
Alexandre Julliardd16319c1999-11-25 21:30:24 +0000140 size_t len = get_req_strlenW( req->name );
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000141 req->handle = open_object( req->name, len, &semaphore_ops, req->access, req->inherit );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000142}
143
144/* release a semaphore */
145DECL_HANDLER(release_semaphore)
146{
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000147 req->prev_count = release_semaphore( req->handle, req->count );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000148}