From owner-acpi-jp@jp.freebsd.org  Fri Nov  2 04:13:22 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id EAA27043;
	Fri, 2 Nov 2001 04:13:22 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from tasogare.imasy.or.jp (root@tasogare.imasy.or.jp [202.227.24.5])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id EAA27038
	for <acpi-jp@jp.freebsd.org>; Fri, 2 Nov 2001 04:13:21 +0900 (JST)
	(envelope-from iwasaki@jp.FreeBSD.org)
Received: from localhost (iwasaki.imasy.or.jp [202.227.24.92])
	(authenticated as iwa with CRAM-MD5)
	by tasogare.imasy.or.jp (8.11.6+3.4W/8.11.6/tasogare) with ESMTP/inet id fA1JDFW07476;
	Fri, 2 Nov 2001 04:13:15 +0900 (JST)
	(envelope-from iwasaki@jp.FreeBSD.org)
Date: Fri, 02 Nov 2001 04:13:12 +0900 (JST)
Message-Id: <20011102.041312.74756838.iwasaki@jp.FreeBSD.org>
To: andrew.grover@intel.com, robert.moore@intel.com
Cc: acpi-jp@jp.freebsd.org
From: Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
X-Mailer: Mew version 2.0 on Emacs 20.7 / Mule 4.0 (HANANOEN)
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Reply-To: acpi-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: acpi-jp 1418
Subject: [acpi-jp 1418] acpica-unix-20011018: Mutex patches
Errors-To: owner-acpi-jp@jp.freebsd.org
Sender: owner-acpi-jp@jp.freebsd.org
X-Originator: iwasaki@jp.freebsd.org

Hi, Intel folks.  I've just made patches for Mutex code.  Could you
review it as always?

I've updated my kernel based on acpica-unix-20011018 and noticed some
strangeness about Mutex related operations (there is no Mutex changes
on 20011018 but the problems appeared after the snapshot).

Based on our AML collection, I wrote a test ASL program on some
simplified Mutex operations, and I confirmed that all of the tests is
failed with the current ACPICA code.

----
Mutex(MUT0, 1)
Mutex(MUT1, 0)

Method(MAIN)
{
        TES1()
        TES2()
        TES3()
}

Method(TES1)
{
        Acquire(MUT0, 0x5000)
        TE12()
        Release(MUT0)           /* AE_AML_MUTEX_NOT_ACQUIRED */
}
Method(TE12)
{
        Acquire(MUT0, 0x5000)
        Release(MUT0)
}

Method(TES2)
{
        TE21()
        TE22()
}
Method(TE21)
{
        Acquire(MUT0, 0x5000)
}
Method(TE22)
{
        Release(MUT0)           /* AE_AML_MUTEX_ORDER */
}

Method(TES3)
{
        Acquire(MUT0, 0x5000)
        Acquire(MUT1, 0x5000)   /* AE_AML_MUTEX_ORDER */
        Release(MUT1)
        Release(MUT0)
}
----

TES1: simplified _SB_.BAT1._BIF -> _SB_.BAT1.UPBI -> _SB_.PCI0.ISA_.EC0_.SMRD of
      http://www.jp.freebsd.org/cgi/cvsweb.cgi/ACPI/data/fiva-MPC-206VL.dsdt?cvsroot=freebsd-jp
      The same Mutex (_SB_.PCI0.ISA_.EC0_.MUT0) is acquired by two
      different methods recursively.  Failed when we try to release
      the mutex at the method which first acquired the mutex.

TES2: simplified _SB_.PCI0.ISA_.EC__.ENFG and EXFG of
      http://www.jp.freebsd.org/cgi/cvsweb.cgi/ACPI/data/PCG-Z505SX-R0109Z0.asl?cvsroot=freebsd-jp
      Acquired mutex is released by other method.  Failed when mutex
      is released.

TES3: no actual example but possible.
      A method acquires two different sync-level mutexes.  Failed when
      second mutex is acquired.  Note that `A SyncLevel of n allows
      n+1 mutex owners' according to ACPI 2.0 Spec.

I made patches to pass the above tests for acpica-unix-20011018.
Any comments are greatly appreciated.

Thanks

Index: acobject.h
===================================================================
RCS file: /home/ncvs/src/sys/contrib/dev/acpica/acobject.h,v
retrieving revision 1.1.1.8
diff -c -r1.1.1.8 acobject.h
*** acobject.h	31 Oct 2001 02:32:27 -0000	1.1.1.8
--- acobject.h	1 Nov 2001 13:14:15 -0000
***************
*** 300,305 ****
--- 300,306 ----
  {
      ACPI_OBJECT_COMMON_HEADER
      UINT16                      SyncLevel;
+     UINT16                      CurrentSyncLevel;
      UINT16                      AcquisitionDepth;
  
      void                        *Semaphore;
Index: excreate.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/dev/acpica/excreate.c,v
retrieving revision 1.1.1.10
diff -c -r1.1.1.10 excreate.c
*** excreate.c	31 Oct 2001 02:32:27 -0000	1.1.1.10
--- excreate.c	1 Nov 2001 14:40:25 -0000
***************
*** 280,285 ****
--- 280,286 ----
      /* Init object and attach to NS node */
  
      ObjDesc->Mutex.SyncLevel = (UINT8) WalkState->Operands[1]->Integer.Value;
+     ObjDesc->Mutex.CurrentSyncLevel = 0;
  
      Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) WalkState->Operands[0],
                                  ObjDesc, (UINT8) ACPI_TYPE_MUTEX);
Index: exmutex.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/dev/acpica/exmutex.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 exmutex.c
*** exmutex.c	7 Sep 2001 01:22:24 -0000	1.1.1.2
--- exmutex.c	1 Nov 2001 15:07:47 -0000
***************
*** 152,157 ****
--- 152,159 ----
      {
          (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next;
      }
+ 
+     ObjDesc->Mutex.CurrentSyncLevel--;
  }
  
  
***************
*** 189,194 ****
--- 191,198 ----
      /* Update list head */
  
      ListHead->Mutex.Next = ObjDesc;
+ 
+     ObjDesc->Mutex.CurrentSyncLevel++;
  }
  
  
***************
*** 222,243 ****
      }
  
      /*
!      * Current Sync must be less than or equal to the sync level of the
!      * mutex.  This mechanism provides some deadlock prevention
       */
!     if (WalkState->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
      {
!         return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
      }
  
      /*
!      * If the mutex is already owned by this thread,
!      * just increment the acquisition depth
       */
!     if (ObjDesc->Mutex.Owner == WalkState)
      {
!         ObjDesc->Mutex.AcquisitionDepth++;
!         return_ACPI_STATUS (AE_OK);
      }
  
      /* Acquire the mutex, wait if necessary */
--- 226,247 ----
      }
  
      /*
!      * If the mutex is already owned by this thread,
!      * just increment the acquisition depth
       */
!     if (ObjDesc->Mutex.Owner == AcpiOsGetThreadId())
      {
!         ObjDesc->Mutex.AcquisitionDepth++;
!         return_ACPI_STATUS (AE_OK);
      }
  
      /*
!      * Current Sync must be less than or equal to the sync level of the
!      * mutex.  This mechanism provides some deadlock prevention
       */
!     if (ObjDesc->Mutex.CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
      {
!         return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
      }
  
      /* Acquire the mutex, wait if necessary */
***************
*** 252,260 ****
  
      /* Have the mutex, update mutex and walk info */
  
!     ObjDesc->Mutex.Owner = WalkState;
!     ObjDesc->Mutex.AcquisitionDepth = 1;
!     WalkState->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;
  
      /* Link the mutex to the walk state for force-unlock at method exit */
  
--- 256,266 ----
  
      /* Have the mutex, update mutex and walk info */
  
!     if (ObjDesc->Mutex.AcquisitionDepth == 0)
!     {
!         ObjDesc->Mutex.Owner = AcpiOsGetThreadId();
!     }
!     ObjDesc->Mutex.AcquisitionDepth++;
  
      /* Link the mutex to the walk state for force-unlock at method exit */
  
***************
*** 293,298 ****
--- 299,319 ----
          return_ACPI_STATUS (AE_BAD_PARAMETER);
      }
  
+     /*
+      * Match multiple Acquires with multiple Releases
+      */
+     ObjDesc->Mutex.AcquisitionDepth--;
+     if (ObjDesc->Mutex.AcquisitionDepth != 0)
+     {
+         /* Just decrement the depth and return */
+ 
+         if (ObjDesc->Mutex.Owner != AcpiOsGetThreadId())
+         {
+             AcpiExUnlinkMutex (ObjDesc);
+         }
+         return_ACPI_STATUS (AE_OK);
+     }
+ 
      /* The mutex must have been previously acquired in order to release it */
  
      if (!ObjDesc->Mutex.Owner)
***************
*** 302,332 ****
  
      /* The Mutex is owned, but this thread must be the owner */
  
!     if (ObjDesc->Mutex.Owner != WalkState)
      {
          return_ACPI_STATUS (AE_AML_NOT_OWNER);
      }
  
-     /*
-      * The sync level of the mutex must be less than or
-      * equal to the current sync level
-      */
-     if (ObjDesc->Mutex.SyncLevel > WalkState->CurrentSyncLevel)
-     {
-         return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
-     }
- 
-     /*
-      * Match multiple Acquires with multiple Releases
-      */
-     ObjDesc->Mutex.AcquisitionDepth--;
-     if (ObjDesc->Mutex.AcquisitionDepth != 0)
-     {
-         /* Just decrement the depth and return */
- 
-         return_ACPI_STATUS (AE_OK);
-     }
- 
  
      /* Release the mutex */
  
--- 323,333 ----
  
      /* The Mutex is owned, but this thread must be the owner */
  
!     if (ObjDesc->Mutex.Owner != AcpiOsGetThreadId())
      {
          return_ACPI_STATUS (AE_AML_NOT_OWNER);
      }
  
  
      /* Release the mutex */
  
***************
*** 335,341 ****
      /* Update the mutex and walk state */
  
      ObjDesc->Mutex.Owner = NULL;
-     WalkState->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;
  
      /* Unlink the mutex from the owner's list */
  
--- 336,341 ----
