ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

resource.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.