KD System Rewrite:
[reactos.git] / reactos / ntoskrnl / ke / sem.c
index ca4335d..2d3fe4d 100644 (file)
@@ -1,38 +1,16 @@
-/*
- *  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.14 2003/11/02 01:15:15 ekohl 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 <ddk/ntddk.h>
-#include <internal/ke.h>
-#include <internal/ps.h>
-#include <internal/id.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /*
  * @implemented
  */
-VOID STDCALL
-KeInitializeSemaphore (PKSEMAPHORE     Semaphore,
-                      LONG             Count,
-                      LONG             Limit)
+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;  
 }
 
 /*
  * @implemented
  */
-LONG STDCALL
-KeReadStateSemaphore (PKSEMAPHORE      Semaphore)
+LONG 
+STDCALL
+KeReadStateSemaphore(PKSEMAPHORE Semaphore)
 {
-   return(Semaphore->Header.SignalState);
+    /* Just return the Signal State */
+    return(Semaphore->Header.SignalState);
 }
 
 /*
  * @implemented
- */
-LONG STDCALL
-KeReleaseSemaphore (PKSEMAPHORE        Semaphore,
-                   KPRIORITY   Increment,
-                   LONG                Adjustment,
-                   BOOLEAN             Wait)
-/*
+ *
  * 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
@@ -90,40 +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;
-  KIRQL OldIrql;
+    ULONG InitialState;
+    KIRQL OldIrql;
+    PKTHREAD CurrentThread;
 
-  DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
-         "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
+    DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n", 
+            Semaphore, 
+            Increment, 
+            Adjustment, 
+            Wait);
 
-  OldIrql = KeAcquireDispatcherDatabaseLock();
+    /* Lock the Dispatcher Database */
+    OldIrql = KeAcquireDispatcherDatabaseLock();
 
-  InitialState = Semaphore->Header.SignalState;
-  if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
-      InitialState > InitialState + Adjustment)
-    {
-      ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
+    /* 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);
     }
 
-  Semaphore->Header.SignalState += Adjustment;
-  if (InitialState == 0)
-    {
-      KeDispatcherObjectWake(&Semaphore->Header);
+    /* 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 (Wait == FALSE)
-    {
-      KeReleaseDispatcherDatabaseLock(OldIrql);
-    }
-  else
-    {
-      KTHREAD *Thread = KeGetCurrentThread();
-      Thread->WaitNext = Wait;
-      Thread->WaitIrql = OldIrql;
+    /* 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(InitialState);
+    /* Return the previous state */
+    return InitialState;
 }
 
 /* EOF */