From owner-acpi-jp@jp.freebsd.org  Tue Nov  6 07:25:58 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id HAA23833;
	Tue, 6 Nov 2001 07:25:58 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from thalia.fm.intel.com (fmfdns02.fm.intel.com [132.233.247.11])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id HAA23815;
	Tue, 6 Nov 2001 07:25:53 +0900 (JST)
	(envelope-from robert.moore@intel.com)
Received: from fmsmsxvs041.fm.intel.com (fmsmsxv041-1.fm.intel.com [132.233.48.109])
	by thalia.fm.intel.com (8.9.1a+p1/8.9.1/d: relay.m4,v 1.46 2001/10/25 21:02:55 root Exp $) with SMTP id WAA10096;
	Mon, 5 Nov 2001 22:25:48 GMT
Received: from fmsmsx26.fm.intel.com ([132.233.42.26])
 by fmsmsxvs041.fm.intel.com (NAVGW 2.5.1.6) with SMTP id M2001110514270807069
 ; Mon, 05 Nov 2001 14:27:08 -0800
Received: by fmsmsx26.fm.intel.com with Internet Mail Service (5.5.2653.19)
	id <VD69LFL4>; Mon, 5 Nov 2001 14:27:00 -0800
Message-ID: <B9ECACBD6885D5119ADC00508B68C1EA2FDFD9@orsmsx107.jf.intel.com>
From: "Moore, Robert" <robert.moore@intel.com>
To: "'Mitsuru IWASAKI'" <iwasaki@jp.FreeBSD.org>
Cc: acpi-jp@jp.FreeBSD.org, "Grover, Andrew" <andrew.grover@intel.com>,
        "Therien, Guy" <guy.therien@intel.com>,
        "Diefenbaugh, Paul S" <paul.s.diefenbaugh@intel.com>
Date: Mon, 5 Nov 2001 14:25:41 -0800 
MIME-Version: 1.0
X-Mailer: Internet Mail Service (5.5.2653.19)
Content-Type: text/plain;
	charset="iso-8859-1"
Reply-To: acpi-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: acpi-jp 1439
Subject: [acpi-jp 1439] RE: ACPI CA  Mutex patches
Errors-To: owner-acpi-jp@jp.freebsd.org
Sender: owner-acpi-jp@jp.freebsd.org
X-Originator: robert.moore@intel.com


I have verified that there are indeed some issues with the existing mutex
support when crossing method boundaries (i.e., acquiring a mutex in one
method and releasing it in another method, but all within the context of a
single thread.)

I believe that the problem stems from the fact that we are tracking the
CurrentSyncLevel on a per-method basis, and not a per-thread basis.  In
terms of the current data structures, the WalkState for each control method
should inherit the CurrentSyncLevel of the calling walk state, and at method
completion, the calling walk state should inherit the CurrentSyncLevel of
the called WalkState.

What I think this really means is that we need to maintain a small
per-thread data structure with the CurrentSyncLevel, permitting the
CurrentSyncLevel to be directly associated with the executing thread.  Each
nested WalkState would then point to the same ThreadData and
CurrentSyncLevel.

This also means that I do not agree that the CurrentSyncLevel should become
part of the Mutex object.

I'd also like to make sure that everyone agrees on the "correct" behavior of
this type of AML code, and here are some more examples along with my
understanding of what should happen:

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


    Method(TES1)
    {
            Acquire(MUT0, 0x500)
            TE12()
            Release(MUT0)           /* AE_OK */
    }
    Method(TE12)
    {
            Acquire(MUT0, 0x500)
            Release(MUT0)
    }

    Method(TES2)
    {
            TE21()
            TE22()                  /* AE_OK */
    }
    Method(TE21)
    {
            Acquire(MUT0, 0x500)
    }
    Method(TE22)
    {
            Release(MUT0)
    }

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

    Method(TES4)
    {
            Acquire(MUT1, 0x500)
            Acquire(MUT0, 0x500)
            Release(MUT1)
            Release(MUT0)           /* AE_AML_MUTEX_ORDER */
    }
    Method(TES5)
    {
            Acquire(MUT1, 0x500)  
            Acquire(MUT0, 0x500)
            Release(MUT0)
            Release(MUT1)           /* AE_OK */
    }
    Method(TES6)
    {
            Acquire(MUT1, 0x500)
            TE21()
            TE22()
            Release(MUT1)           /* AE_OK */
    }


-----Original Message-----
From: Mitsuru IWASAKI [mailto:iwasaki@jp.FreeBSD.org]
Sent: Thursday, November 01, 2001 11:13 AM
To: andrew.grover@intel.com; robert.moore@intel.com
Cc: acpi-jp@jp.FreeBSD.org
Subject: acpica-unix-20011018: Mutex patches


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?cvsro
ot=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?cv
sroot=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 ----
