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

mutex.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ke/mutex.c
00005  * PURPOSE:         Implements the Mutant Dispatcher Object
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* FUNCTIONS *****************************************************************/
00016 
00017 /*
00018  * @implemented
00019  */
00020 VOID
00021 NTAPI
00022 KeInitializeMutant(IN PKMUTANT Mutant,
00023                    IN BOOLEAN InitialOwner)
00024 {
00025     PKTHREAD CurrentThread;
00026     KIRQL OldIrql;
00027 
00028     /* Check if we have an initial owner */
00029     if (InitialOwner)
00030     {
00031         /* We also need to associate a thread */
00032         CurrentThread = KeGetCurrentThread();
00033         Mutant->OwnerThread = CurrentThread;
00034 
00035         /* We're about to touch the Thread, so lock the Dispatcher */
00036         OldIrql = KiAcquireDispatcherLock();
00037 
00038         /* And insert it into its list */
00039         InsertTailList(&CurrentThread->MutantListHead,
00040                        &Mutant->MutantListEntry);
00041 
00042         /* Release Dispatcher Lock */
00043         KiReleaseDispatcherLock(OldIrql);
00044     }
00045     else
00046     {
00047         /* In this case, we don't have an owner yet */
00048         Mutant->OwnerThread = NULL;
00049     }
00050 
00051     /* Now we set up the Dispatcher Header */
00052     Mutant->Header.Type = MutantObject;
00053     Mutant->Header.Size = sizeof(KMUTANT) / sizeof(ULONG);
00054     Mutant->Header.DpcActive = FALSE;
00055     Mutant->Header.SignalState = InitialOwner ? 0 : 1;
00056     InitializeListHead(&(Mutant->Header.WaitListHead));
00057 
00058     /* Initialize the default data */
00059     Mutant->Abandoned = FALSE;
00060     Mutant->ApcDisable = 0;
00061 }
00062 
00063 /*
00064  * @implemented
00065  */
00066 VOID
00067 NTAPI
00068 KeInitializeMutex(IN PKMUTEX Mutex,
00069                   IN ULONG Level)
00070 {
00071     /* Set up the Dispatcher Header */
00072     Mutex->Header.Type = MutantObject;
00073     Mutex->Header.Size = sizeof(KMUTEX) / sizeof(ULONG);
00074     Mutex->Header.DpcActive = FALSE;
00075     Mutex->Header.SignalState = 1;
00076     InitializeListHead(&(Mutex->Header.WaitListHead));
00077 
00078     /* Initialize the default data */
00079     Mutex->OwnerThread = NULL;
00080     Mutex->Abandoned = FALSE;
00081     Mutex->ApcDisable = 1;
00082 }
00083 
00084 /*
00085  * @implemented
00086  */
00087 LONG
00088 NTAPI
00089 KeReadStateMutant(IN PKMUTANT Mutant)
00090 {
00091     /* Return the Signal State */
00092     return Mutant->Header.SignalState;
00093 }
00094 
00095 /*
00096  * @implemented
00097  */
00098 LONG
00099 NTAPI
00100 KeReleaseMutant(IN PKMUTANT Mutant,
00101                 IN KPRIORITY Increment,
00102                 IN BOOLEAN Abandon,
00103                 IN BOOLEAN Wait)
00104 {
00105     KIRQL OldIrql;
00106     LONG PreviousState;
00107     PKTHREAD CurrentThread = KeGetCurrentThread();
00108     BOOLEAN EnableApc = FALSE;
00109     ASSERT_MUTANT(Mutant);
00110     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00111 
00112     /* Lock the Dispatcher Database */
00113     OldIrql = KiAcquireDispatcherLock();
00114 
00115     /* Save the Previous State */
00116     PreviousState = Mutant->Header.SignalState;
00117 
00118     /* Check if it is to be abandonned */
00119     if (Abandon == FALSE)
00120     {
00121         /* Make sure that the Owner Thread is the current Thread */
00122         if (Mutant->OwnerThread != CurrentThread)
00123         {
00124             /* Release the lock */
00125             KiReleaseDispatcherLock(OldIrql);
00126 
00127             /* Raise an exception */
00128             ExRaiseStatus(Mutant->Abandoned ? STATUS_ABANDONED :
00129                                               STATUS_MUTANT_NOT_OWNED);
00130         }
00131 
00132         /* If the thread owns it, then increase the signal state */
00133         Mutant->Header.SignalState++;
00134     }
00135     else
00136     {
00137         /* It's going to be abandonned */
00138         Mutant->Header.SignalState = 1;
00139         Mutant->Abandoned = TRUE;
00140     }
00141 
00142     /* Check if the signal state is only single */
00143     if (Mutant->Header.SignalState == 1)
00144     {
00145         /* Check if it's below 0 now */
00146         if (PreviousState <= 0)
00147         {
00148             /* Remove the mutant from the list */
00149             RemoveEntryList(&Mutant->MutantListEntry);
00150 
00151             /* Save if we need to re-enable APCs */
00152             EnableApc = Mutant->ApcDisable;
00153         }
00154 
00155         /* Remove the Owning Thread and wake it */
00156         Mutant->OwnerThread = NULL;
00157 
00158         /* Check if the Wait List isn't empty */
00159         if (!IsListEmpty(&Mutant->Header.WaitListHead))
00160         {
00161             /* Wake the Mutant */
00162             KiWaitTest(&Mutant->Header, Increment);
00163         }
00164     }
00165 
00166     /* Check if the caller wants to wait after this release */
00167     if (Wait == FALSE)
00168     {
00169         /* Release the Lock */
00170         KiReleaseDispatcherLock(OldIrql);
00171     }
00172     else
00173     {
00174         /* Set a wait */
00175         CurrentThread->WaitNext = TRUE;
00176         CurrentThread->WaitIrql = OldIrql;
00177     }
00178 
00179     /* Check if we need to re-enable APCs */
00180     if (EnableApc) KeLeaveCriticalRegion();
00181 
00182     /* Return the previous state */
00183     return PreviousState;
00184 }
00185 
00186 /*
00187  * @implemented
00188  */
00189 LONG
00190 NTAPI
00191 KeReleaseMutex(IN PKMUTEX Mutex,
00192                IN BOOLEAN Wait)
00193 {
00194     ASSERT_MUTANT(Mutex);
00195 
00196     /* There's no difference at this level between the two */
00197     return KeReleaseMutant(Mutex, 1, FALSE, Wait);
00198 }
00199 
00200 /* EOF */

Generated on Sat May 26 2012 04:36: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.