KD System Rewrite:
[reactos.git] / reactos / ntoskrnl / ke / sem.c
index a0a0855..2d3fe4d 100644 (file)
@@ -1,65 +1,57 @@
-/*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: sem.c,v 1.10 2002/09/07 15:12:57 chorns Exp $
+/* $Id$
  *
+ * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/sem.c
  * PURPOSE:         Implements kernel semaphores
- * PROGRAMMER:      David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ * 
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
-
 #define NDEBUG
 #include <internal/debug.h>
 
-
 /* FUNCTIONS *****************************************************************/
 
-VOID STDCALL 
-KeInitializeSemaphore (PKSEMAPHORE     Semaphore,
-                      LONG             Count,
-                      LONG             Limit)
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+KeInitializeSemaphore(PKSEMAPHORE Semaphore,
+                      LONG Count,
+                      LONG Limit)
 {
-   KeInitializeDispatcherHeader(&Semaphore->Header,
-                               InternalSemaphoreType,
-                               sizeof(KSEMAPHORE)/sizeof(ULONG),
-                               Count);
-   Semaphore->Limit=Limit;
+
+    DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
+    
+    /* Simply Initialize the Header */
+    KeInitializeDispatcherHeader(&Semaphore->Header,
+                                 SemaphoreObject,
+                                 sizeof(KSEMAPHORE)/sizeof(ULONG),
+                                 Count);
+
+    /* Set the Limit */
+    Semaphore->Limit = Limit;  
 }
 
-LONG STDCALL 
-KeReadStateSemaphore (PKSEMAPHORE      Semaphore)
+/*
+ * @implemented
+ */
+LONG 
+STDCALL
+KeReadStateSemaphore(PKSEMAPHORE Semaphore)
 {
-   return(Semaphore->Header.SignalState);
+    /* Just return the Signal State */
+    return(Semaphore->Header.SignalState);
 }
 
-LONG STDCALL 
-KeReleaseSemaphore (PKSEMAPHORE        Semaphore,
-                   KPRIORITY   Increment,
-                   LONG                Adjustment,
-                   BOOLEAN             Wait)
 /*
+ * @implemented
+ *
  * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
  * routine supplies a runtime priority boost for waiting threads. If this
  * call sets the semaphore to the Signaled state, the semaphore count is
@@ -79,29 +71,65 @@ KeReleaseSemaphore (PKSEMAPHORE     Semaphore,
  * RETURNS: If the return value is zero, the previous state of the semaphore
  *          object is Not-Signaled.
  */
+LONG 
+STDCALL
+KeReleaseSemaphore(PKSEMAPHORE Semaphore,
+                   KPRIORITY Increment,
+                   LONG Adjustment,
+                   BOOLEAN Wait)
+
 {
-   ULONG InitialState;
-  
-   DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
-         "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
-   
-   KeAcquireDispatcherDatabaseLock(Wait);
-   
-   InitialState = Semaphore->Header.SignalState;
-   if (Semaphore->Limit < InitialState + Adjustment ||
-       InitialState > InitialState + Adjustment)
-     {
-       ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
-     }
-   
-   Semaphore->Header.SignalState += Adjustment;
-   if (InitialState == 0)
-     {
-       KeDispatcherObjectWake(&Semaphore->Header);
-     }
-   
-  KeReleaseDispatcherDatabaseLock(Wait);
-  return(InitialState);
+    ULONG InitialState;
+    KIRQL OldIrql;
+    PKTHREAD CurrentThread;
+
+    DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n", 
+            Semaphore, 
+            Increment, 
+            Adjustment, 
+            Wait);
+
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
+
+    /* Save the Old State */
+    InitialState = Semaphore->Header.SignalState;
+    
+    /* Check if the Limit was exceeded */
+    if (Semaphore->Limit < (LONG) InitialState + Adjustment || 
+        InitialState > InitialState + Adjustment) {
+        
+        /* Raise an error if it was exceeded */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
+    }
+
+    /* Now set the new state */
+    Semaphore->Header.SignalState += Adjustment;
+    
+    /* Check if we should wake it */
+    if (InitialState == 0 && !IsListEmpty(&Semaphore->Header.WaitListHead)) {
+        
+        /* Wake the Semaphore */
+        KiWaitTest(&Semaphore->Header, Increment);
+    }
+
+    /* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
+    if (Wait == FALSE) {
+        
+        /* Release the Lock */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+    
+    } else {
+        
+        /* Set a wait */
+        CurrentThread = KeGetCurrentThread();
+        CurrentThread->WaitNext = TRUE;
+        CurrentThread->WaitIrql = OldIrql;
+    }
+
+    /* Return the previous state */
+    return InitialState;
 }
 
 /* EOF */