Keep an internal copy of the icon.
[wine] / server / semaphore.c
1 /*
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 "winnt.h"
12
13 #include "handle.h"
14 #include "thread.h"
15 #include "request.h"
16
17 struct semaphore
18 {
19     struct object  obj;    /* object header */
20     unsigned int   count;  /* current count */
21     unsigned int   max;    /* maximum possible count */
22 };
23
24 static void semaphore_dump( struct object *obj, int verbose );
25 static int semaphore_signaled( struct object *obj, struct thread *thread );
26 static int semaphore_satisfied( struct object *obj, struct thread *thread );
27
28 static const struct object_ops semaphore_ops =
29 {
30     sizeof(struct semaphore),      /* size */
31     semaphore_dump,                /* dump */
32     add_queue,                     /* add_queue */
33     remove_queue,                  /* remove_queue */
34     semaphore_signaled,            /* signaled */
35     semaphore_satisfied,           /* satisfied */
36     NULL,                          /* get_poll_events */
37     NULL,                          /* poll_event */
38     no_read_fd,                    /* get_read_fd */
39     no_write_fd,                   /* get_write_fd */
40     no_flush,                      /* flush */
41     no_get_file_info,              /* get_file_info */
42     no_destroy                     /* destroy */
43 };
44
45
46 static struct semaphore *create_semaphore( const WCHAR *name, size_t len,
47                                            unsigned int initial, unsigned int max )
48 {
49     struct semaphore *sem;
50
51     if (!max || (initial > max))
52     {
53         set_error( STATUS_INVALID_PARAMETER );
54         return NULL;
55     }
56     if ((sem = create_named_object( &semaphore_ops, name, len )))
57     {
58         if (get_error() != STATUS_OBJECT_NAME_COLLISION)
59         {
60             /* initialize it if it didn't already exist */
61             sem->count = initial;
62             sem->max   = max;
63         }
64     }
65     return sem;
66 }
67
68 static unsigned int release_semaphore( int handle, unsigned int count )
69 {
70     struct semaphore *sem;
71     unsigned int prev = 0;
72
73     if ((sem = (struct semaphore *)get_handle_obj( current->process, handle,
74                                                    SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
75     {
76         prev = sem->count;
77         if (sem->count + count < sem->count || sem->count + count > sem->max)
78         {
79             set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
80         }
81         else if (sem->count)
82         {
83             /* there cannot be any thread waiting if the count is != 0 */
84             assert( !sem->obj.head );
85             sem->count += count;
86         }
87         else
88         {
89             sem->count = count;
90             wake_up( &sem->obj, count );
91         }
92         release_object( sem );
93     }
94     return prev;
95 }
96
97 static void semaphore_dump( struct object *obj, int verbose )
98 {
99     struct semaphore *sem = (struct semaphore *)obj;
100     assert( obj->ops == &semaphore_ops );
101     fprintf( stderr, "Semaphore count=%d max=%d ", sem->count, sem->max );
102     dump_object_name( &sem->obj );
103     fputc( '\n', stderr );
104 }
105
106 static int semaphore_signaled( struct object *obj, struct thread *thread )
107 {
108     struct semaphore *sem = (struct semaphore *)obj;
109     assert( obj->ops == &semaphore_ops );
110     return (sem->count > 0);
111 }
112
113 static int semaphore_satisfied( struct object *obj, struct thread *thread )
114 {
115     struct semaphore *sem = (struct semaphore *)obj;
116     assert( obj->ops == &semaphore_ops );
117     assert( sem->count );
118     sem->count--;
119     return 0;  /* not abandoned */
120 }
121
122 /* create a semaphore */
123 DECL_HANDLER(create_semaphore)
124 {
125     size_t len = get_req_strlenW( req, req->name );
126     struct semaphore *sem;
127
128     req->handle = -1;
129     if ((sem = create_semaphore( req->name, len, req->initial, req->max )))
130     {
131         req->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
132         release_object( sem );
133     }
134 }
135
136 /* open a handle to a semaphore */
137 DECL_HANDLER(open_semaphore)
138 {
139     size_t len = get_req_strlenW( req, req->name );
140     req->handle = open_object( req->name, len, &semaphore_ops, req->access, req->inherit );
141 }
142
143 /* release a semaphore */
144 DECL_HANDLER(release_semaphore)
145 {
146     req->prev_count = release_semaphore( req->handle, req->count );
147 }