Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / ex / resource.c
1 /* $Id$
2  * reactos ERESOURCE handling by libcaptive
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "reactos/ddk/exfuncs.h"        /* self */
23 #include <glib/gmessages.h>
24 #include "reactos/ddk/extypes.h"        /* for ERESOURCE */
25 #include "captive/macros.h"
26
27
28 #define ERESOURCE_OWNING_COUNT_SHARED(Resource)    ((Resource)->OwnerThreads[0].OwnerCount)
29 #define ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource) ((Resource)->OwnerThreads[1].OwnerCount)
30
31
32 static gboolean PERESOURE_validate(PERESOURCE Resource)
33 {
34         g_return_val_if_fail(Resource!=NULL,FALSE);
35
36         g_return_val_if_fail(Resource->ActiveCount
37                         ==ERESOURCE_OWNING_COUNT_SHARED(Resource)+ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource),FALSE);
38
39         return TRUE;
40 }
41
42
43 /**
44  * ExAcquireResourceExclusiveLite:
45  * @Resource: Resource to acquire for exclusive access.
46  * %NULL value is forbidden.
47  * @Wait: %TRUE if the caller may wait to acquire @Resource.
48  *
49  * Acquires a resource exclusively for the calling thread.
50  *
51  * Returns: %TRUE if the resource was acquired.
52  * libcaptive always returns %TRUE.
53  */
54 BOOLEAN ExAcquireResourceExclusiveLite(PERESOURCE Resource,BOOLEAN Wait)
55 {
56         g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
57
58         Resource->ActiveCount++;
59         ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)++;
60
61         g_assert(PERESOURE_validate(Resource));
62         return TRUE;
63 }
64
65
66 /**
67  * ExAcquireResourceSharedLite:
68  * @Resource: Resource to acquire.
69  * %NULL value is forbidden.
70  * @Wait: %TRUE if the caller may wait to acquire @Resource.
71  *
72  * Shared acquire of resource for the calling thread.
73  *
74  * Returns: %TRUE if the resource was acquired.
75  * libcaptive always returns %TRUE.
76  */
77 BOOLEAN ExAcquireResourceSharedLite(PERESOURCE Resource,BOOLEAN Wait)
78 {
79         g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
80
81         Resource->ActiveCount++;
82         ERESOURCE_OWNING_COUNT_SHARED(Resource)++;
83
84         g_assert(PERESOURE_validate(Resource));
85         return TRUE;
86 }
87
88
89 /**
90  * ExConvertExclusiveToSharedLite:
91  * @Resource: Resource to convert access mode.
92  * %NULL value is forbidden.
93  *
94  * Converts a given resource from acquired for exclusive access to being
95  * acquired for shared access.
96  *
97  * You must already have exclusive access to @Resource before the call.
98  */
99 VOID ExConvertExclusiveToSharedLite(PERESOURCE Resource)
100 {
101         g_return_if_fail(PERESOURE_validate(Resource));
102         g_return_if_fail(ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0);
103
104         ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)--;
105         ERESOURCE_OWNING_COUNT_SHARED(Resource)++;
106
107         g_assert(PERESOURE_validate(Resource));
108 }
109
110
111 /**
112  * ExAcquireSharedStarveExclusive:
113  * @Resource: Resource to acquire for shared access.
114  * %NULL value is forbidden.
115  * @Wait: %TRUE if the caller should wait to acquire @Resource.
116  *
117  * Acquires a given resource for shared access. Current thread has priority
118  * over any threads currently wating for exclusive access to this @Resource.
119  *
120  * libcaptive has the same implementation as ExAcquireResourceSharedLite().
121  *
122  * Returns: %TRUE if the resource was acquired.
123  * libcaptive always returns %TRUE.
124  */
125 BOOLEAN ExAcquireSharedStarveExclusive(PERESOURCE Resource,BOOLEAN Wait)
126 {
127         g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
128
129   return ExAcquireResourceSharedLite(Resource,Wait);
130 }
131
132
133 /**
134  * ExAcquireSharedWaitForExclusive:
135  * @Resource: Resource to acquire for shared access.
136  * %NULL value is forbidden.
137  * @Wait: %TRUE if the caller should wait to acquire @Resource.
138  *
139  * Acquires a given resource for shared access. Any threads currently wating
140  * for exclusive access to this @Resource have priority over the current
141  * thread.
142  *
143  * libcaptive has the same implementation as ExAcquireResourceSharedLite().
144  *
145  * Returns: %TRUE if the resource was acquired.
146  * libcaptive always returns %TRUE.
147  */
148 BOOLEAN ExAcquireSharedWaitForExclusive(PERESOURCE Resource,BOOLEAN Wait)
149 {
150         g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
151
152   return ExAcquireResourceSharedLite(Resource,Wait);
153 }
154
155
156 /**
157  * ExReleaseResourceForThreadLite:
158  * @Resource: Resource to release.
159  * %NULL value is forbidden.
160  * @ResourceThreadId: Thread which currently owns @Resource.
161  * %NULL value is forbidden.
162  * Value ExGetCurrentResourceThread() required by libcaptive.
163  *
164  * Function releases @Resource. @ResourceThreadId must be either exclusive or
165  * shared owner of @Resource.
166  * FIXME: W32 undocumented: Ownership counter is decremented by 1;
167  * @ResourceThreadId may still own @Resource after this function finishes.
168  * FIXME: W32 undocumented: It is expected shared ownership should be released first.
169  * ntfs.sys of NT-5.1sp1 behaviour: Init,AcqExcl,AcqShared,Rel,expectExcl.
170  * Maybe acquire ordering also makes sense?
171  */
172 VOID ExReleaseResourceForThreadLite(PERESOURCE Resource,ERESOURCE_THREAD ResourceThreadId)
173 {
174         g_return_if_fail(PERESOURE_validate(Resource));
175         g_return_if_fail(ResourceThreadId==ExGetCurrentResourceThread());
176         g_return_if_fail(Resource->ActiveCount>0);
177
178         /**/ if (ERESOURCE_OWNING_COUNT_SHARED(Resource)>0)
179                 ERESOURCE_OWNING_COUNT_SHARED(Resource)--;
180         else if (ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0)
181                 ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)--;
182         else g_assert_not_reached();
183
184         Resource->ActiveCount--;
185
186         g_assert(PERESOURE_validate(Resource));
187 }
188
189
190 /**
191  * ExReleaseResourceForThreadLite:
192  * @Resource: Resource to release.
193  * %NULL value is forbidden.
194  *
195  * Function releases @Resource. Current thread must be either exclusive or
196  * shared owner of @Resource.
197  * FIXME: W32 undocumented: Ownership counter is decremented by 1;
198  * Current thread may still own @Resource after this function finishes.
199  * FIXME: W32 undocumented: It is expected exclusive ownership should be released first.
200  */
201 VOID ExReleaseResourceLite(PERESOURCE Resource)
202 {
203         g_return_if_fail(PERESOURE_validate(Resource));
204
205   return ExReleaseResourceForThreadLite(Resource,ExGetCurrentResourceThread());
206 }
207
208
209 /**
210  * ExGetExclusiveWaiterCount:
211  * @Resource: Resource to query.
212  * %NULL value is forbidden.
213  *
214  * Reports the number of waiters for exclusive access.
215  *
216  * Returns: Number of waiters for exclusive access.
217  * This function always returns 0 by libcaptive.
218  */
219 ULONG ExGetExclusiveWaiterCount(PERESOURCE Resource)
220 {
221         g_return_val_if_fail(PERESOURE_validate(Resource),0);
222
223         return 0;
224 }
225
226
227 /**
228  * ExGetSharedWaiterCount:
229  * @Resource: Resource to query.
230  * %NULL value is forbidden.
231  *
232  * Reports the number of currently pending waiters for shared access to
233  * @Resource.
234  *
235  * Returns: Number of waiters for shared access.
236  * This function always returns 0 by libcaptive.
237  */
238 ULONG ExGetSharedWaiterCount(PERESOURCE Resource)
239 {
240         g_return_val_if_fail(PERESOURE_validate(Resource),0);
241
242         return 0;
243 }
244
245
246 /*
247  * ExIsResourceAcquiredExclusiveLite:
248  * @Resource: Resource to query.
249  * %NULL value is forbidden.
250  *
251  * Query if the calling thread owns exclusive access to @Resource.
252  *
253  * Returns: %TRUE if the caller has exclusive access to @Resource,
254  */
255 BOOLEAN ExIsResourceAcquiredExclusiveLite(PERESOURCE Resource)
256 {
257         g_return_val_if_fail(PERESOURE_validate(Resource),FALSE);
258
259         return ERESOURCE_OWNING_COUNT_EXCLUSIVE(Resource)>0;
260 }
261
262
263 /*
264  * ExIsResourceAcquiredSharedLite:
265  * @Resource: Resource to query.
266  * %NULL value is forbidden.
267  *
268  * Query if the calling thread owns shared access to @Resource.
269  * Exclusive access is considered equivalent to shared access in this case.
270  *
271  * Returns: Count how many times the caller owns @Resource for any access,
272  * Value 0 is returned if the resource is not owned at all.
273  */
274 USHORT ExIsResourceAcquiredSharedLite(PERESOURCE Resource)
275 {
276         g_return_val_if_fail(PERESOURE_validate(Resource),0);
277
278         g_assert(Resource->ActiveCount==(USHORT)Resource->ActiveCount);
279         return Resource->ActiveCount;
280 }
281
282
283 /**
284  * ExInitializeResourceLite:
285  * @Resource: Memory block of size #PERESOURCE to initialize.
286  * %NULL value is forbidden.
287  *
288  * Initializes fields of #PERESOURCE structure.
289  *
290  * Returns: %STATUS_SUCCESS if the resource was initialized successfully.
291  * libcaptive always returns %STATUS_SUCCESS.
292  */
293 NTSTATUS ExInitializeResourceLite(PERESOURCE Resource)
294 {
295         g_return_val_if_fail(Resource!=NULL,STATUS_INVALID_PARAMETER);
296
297         CAPTIVE_MEMZERO(Resource);
298         KeInitializeSpinLock(&Resource->SpinLock);
299
300         g_assert(PERESOURE_validate(Resource));
301         return STATUS_SUCCESS;
302 }
303
304
305 /*
306  * ExReinitializeResourceLite:
307  * @Resource: Resource to reinitialize sized as #ERESOURCE.
308  * %NULL value is forbidden.
309  *
310  * Reinitialize data fields of @Resource. @Resource must be already initialized
311  * by ExInitializeResourceLite(). Its state is lost and it becomes a fresh new
312  * #ERESOURCED without any its owners.
313  */
314 VOID ExReinitializeResourceLite(PERESOURCE Resource)
315 {
316         g_return_if_fail(PERESOURE_validate(Resource));
317
318         ExDeleteResourceLite(Resource); /* errors ignored */
319         ExInitializeResourceLite(Resource);     /* errors ignored */
320 }
321
322
323 /**
324  * ExDeleteResourceLite:
325  * @Resource: Resource to delete.
326  * %NULL value is forbidden.
327  *
328  * Deletes any resources allocated for @Resource. Memory of #ERESOURCE pointer
329  * directly by @Resource is not freed - its storage belongs to the caller.
330  *
331  * This function is a NOP for libcaptive.
332  *
333  * Returns: %STATUS_SUCCESS if the resource was successfully deleted.
334  * libcaptive always returns %STATUS_SUCCESS.
335  */
336 NTSTATUS ExDeleteResourceLite(PERESOURCE Resource)
337 {
338         g_return_val_if_fail(PERESOURE_validate(Resource),STATUS_INVALID_PARAMETER);
339
340         return STATUS_SUCCESS;
341 }