Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenresource.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * FILE: lib/rtl/resource.c 00005 * PURPOSE: Resource (multiple-reader-single-writer lock) functions 00006 * PROGRAMMER: Partially takem from Wine: 00007 * Copyright 1996-1998 Marcus Meissner 00008 * 1999 Alex Korobka 00009 */ 00010 00011 /* INCLUDES *****************************************************************/ 00012 00013 #include <rtl.h> 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* FUNCTIONS ***************************************************************/ 00019 00020 /* 00021 * @implemented 00022 */ 00023 VOID NTAPI 00024 RtlInitializeResource(PRTL_RESOURCE Resource) 00025 { 00026 NTSTATUS Status; 00027 00028 Status = RtlInitializeCriticalSection(&Resource->Lock); 00029 if (!NT_SUCCESS(Status)) 00030 { 00031 RtlRaiseStatus(Status); 00032 } 00033 00034 Status = NtCreateSemaphore(&Resource->SharedSemaphore, 00035 SEMAPHORE_ALL_ACCESS, 00036 NULL, 00037 0, 00038 65535); 00039 if (!NT_SUCCESS(Status)) 00040 { 00041 RtlRaiseStatus(Status); 00042 } 00043 Resource->SharedWaiters = 0; 00044 00045 Status = NtCreateSemaphore(&Resource->ExclusiveSemaphore, 00046 SEMAPHORE_ALL_ACCESS, 00047 NULL, 00048 0, 00049 65535); 00050 if (!NT_SUCCESS(Status)) 00051 { 00052 RtlRaiseStatus(Status); 00053 } 00054 Resource->ExclusiveWaiters = 0; 00055 00056 Resource->NumberActive = 0; 00057 Resource->OwningThread = NULL; 00058 Resource->TimeoutBoost = 0; /* no info on this one, default value is 0 */ 00059 } 00060 00061 00062 /* 00063 * @implemented 00064 */ 00065 VOID NTAPI 00066 RtlDeleteResource(PRTL_RESOURCE Resource) 00067 { 00068 RtlDeleteCriticalSection(&Resource->Lock); 00069 NtClose(Resource->ExclusiveSemaphore); 00070 NtClose(Resource->SharedSemaphore); 00071 Resource->OwningThread = NULL; 00072 Resource->ExclusiveWaiters = 0; 00073 Resource->SharedWaiters = 0; 00074 Resource->NumberActive = 0; 00075 } 00076 00077 00078 /* 00079 * @implemented 00080 */ 00081 BOOLEAN NTAPI 00082 RtlAcquireResourceExclusive(PRTL_RESOURCE Resource, 00083 BOOLEAN Wait) 00084 { 00085 NTSTATUS Status; 00086 BOOLEAN retVal = FALSE; 00087 00088 start: 00089 RtlEnterCriticalSection(&Resource->Lock); 00090 if (Resource->NumberActive == 0) /* lock is free */ 00091 { 00092 Resource->NumberActive = -1; 00093 retVal = TRUE; 00094 } 00095 else if (Resource->NumberActive < 0) /* exclusive lock in progress */ 00096 { 00097 if (Resource->OwningThread == NtCurrentTeb()->ClientId.UniqueThread) 00098 { 00099 retVal = TRUE; 00100 Resource->NumberActive--; 00101 goto done; 00102 } 00103 wait: 00104 if (Wait == TRUE) 00105 { 00106 Resource->ExclusiveWaiters++; 00107 00108 RtlLeaveCriticalSection(&Resource->Lock); 00109 Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore, 00110 FALSE, 00111 NULL); 00112 if (!NT_SUCCESS(Status)) 00113 goto done; 00114 goto start; /* restart the acquisition to avoid deadlocks */ 00115 } 00116 } 00117 else /* one or more shared locks are in progress */ 00118 { 00119 if (Wait == TRUE) 00120 goto wait; 00121 } 00122 if (retVal == TRUE) 00123 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; 00124 done: 00125 RtlLeaveCriticalSection(&Resource->Lock); 00126 return retVal; 00127 } 00128 00129 00130 /* 00131 * @implemented 00132 */ 00133 BOOLEAN NTAPI 00134 RtlAcquireResourceShared(PRTL_RESOURCE Resource, 00135 BOOLEAN Wait) 00136 { 00137 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00138 BOOLEAN retVal = FALSE; 00139 00140 start: 00141 RtlEnterCriticalSection(&Resource->Lock); 00142 if (Resource->NumberActive < 0) 00143 { 00144 if (Resource->OwningThread == NtCurrentTeb()->ClientId.UniqueThread) 00145 { 00146 Resource->NumberActive--; 00147 retVal = TRUE; 00148 goto done; 00149 } 00150 00151 if (Wait == TRUE) 00152 { 00153 Resource->SharedWaiters++; 00154 RtlLeaveCriticalSection(&Resource->Lock); 00155 Status = NtWaitForSingleObject(Resource->SharedSemaphore, 00156 FALSE, 00157 NULL); 00158 if (!NT_SUCCESS(Status)) 00159 goto done; 00160 goto start; 00161 } 00162 } 00163 else 00164 { 00165 if (Status != STATUS_WAIT_0) /* otherwise RtlReleaseResource() has already done it */ 00166 Resource->NumberActive++; 00167 retVal = TRUE; 00168 } 00169 done: 00170 RtlLeaveCriticalSection(&Resource->Lock); 00171 return retVal; 00172 } 00173 00174 00175 /* 00176 * @implemented 00177 */ 00178 VOID NTAPI 00179 RtlConvertExclusiveToShared(PRTL_RESOURCE Resource) 00180 { 00181 RtlEnterCriticalSection(&Resource->Lock); 00182 00183 if (Resource->NumberActive == -1) 00184 { 00185 Resource->OwningThread = NULL; 00186 00187 if (Resource->SharedWaiters > 0) 00188 { 00189 ULONG n; 00190 /* prevent new writers from joining until 00191 * all queued readers have done their thing */ 00192 n = Resource->SharedWaiters; 00193 Resource->NumberActive = Resource->SharedWaiters + 1; 00194 Resource->SharedWaiters = 0; 00195 NtReleaseSemaphore(Resource->SharedSemaphore, 00196 n, 00197 NULL); 00198 } 00199 else 00200 { 00201 Resource->NumberActive = 1; 00202 } 00203 } 00204 00205 RtlLeaveCriticalSection(&Resource->Lock); 00206 } 00207 00208 00209 /* 00210 * @implemented 00211 */ 00212 VOID NTAPI 00213 RtlConvertSharedToExclusive(PRTL_RESOURCE Resource) 00214 { 00215 NTSTATUS Status; 00216 00217 RtlEnterCriticalSection(&Resource->Lock); 00218 00219 if (Resource->NumberActive == 1) 00220 { 00221 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; 00222 Resource->NumberActive = -1; 00223 } 00224 else 00225 { 00226 Resource->ExclusiveWaiters++; 00227 00228 RtlLeaveCriticalSection(&Resource->Lock); 00229 Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore, 00230 FALSE, 00231 NULL); 00232 if (!NT_SUCCESS(Status)) 00233 return; 00234 00235 RtlEnterCriticalSection(&Resource->Lock); 00236 Resource->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; 00237 Resource->NumberActive = -1; 00238 } 00239 RtlLeaveCriticalSection(&Resource->Lock); 00240 } 00241 00242 00243 /* 00244 * @implemented 00245 */ 00246 VOID NTAPI 00247 RtlReleaseResource(PRTL_RESOURCE Resource) 00248 { 00249 RtlEnterCriticalSection(&Resource->Lock); 00250 00251 if (Resource->NumberActive > 0) /* have one or more readers */ 00252 { 00253 Resource->NumberActive--; 00254 if (Resource->NumberActive == 0) 00255 { 00256 if (Resource->ExclusiveWaiters > 0) 00257 { 00258 wake_exclusive: 00259 Resource->ExclusiveWaiters--; 00260 NtReleaseSemaphore(Resource->ExclusiveSemaphore, 00261 1, 00262 NULL); 00263 } 00264 } 00265 } 00266 else if (Resource->NumberActive < 0) /* have a writer, possibly recursive */ 00267 { 00268 Resource->NumberActive++; 00269 if (Resource->NumberActive == 0) 00270 { 00271 Resource->OwningThread = 0; 00272 if (Resource->ExclusiveWaiters > 0) 00273 { 00274 goto wake_exclusive; 00275 } 00276 else 00277 { 00278 if (Resource->SharedWaiters > 0) 00279 { 00280 ULONG n; 00281 /* prevent new writers from joining until 00282 * all queued readers have done their thing */ 00283 n = Resource->SharedWaiters; 00284 Resource->NumberActive = Resource->SharedWaiters; 00285 Resource->SharedWaiters = 0; 00286 NtReleaseSemaphore(Resource->SharedSemaphore, 00287 n, 00288 NULL); 00289 } 00290 } 00291 } 00292 } 00293 RtlLeaveCriticalSection(&Resource->Lock); 00294 } 00295 00296 00297 /* 00298 * @implemented 00299 */ 00300 VOID NTAPI 00301 RtlDumpResource(PRTL_RESOURCE Resource) 00302 { 00303 DbgPrint("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n", 00304 Resource, 00305 Resource->NumberActive, 00306 Resource->SharedWaiters, 00307 Resource->ExclusiveWaiters); 00308 if (Resource->NumberActive != 0) 00309 { 00310 DbgPrint("\towner thread = %08x\n", 00311 Resource->OwningThread); 00312 } 00313 } 00314 00315 /* EOF */ Generated on Sun May 27 2012 04:22:20 for ReactOS by
1.7.6.1
|