/* static */ void
ES_NativeStackFrame::InitializeFrame(void *frame_start, ES_FrameStackIterator frame, void **&next_frame, BOOL include_return_address)
{
    ES_Code *code = frame.GetCode();
    ES_CodeWord *codeword = frame.GetCodeWord();

    void **ptr = reinterpret_cast<void **>(frame_start);

    if (include_return_address)
        *(ptr - GetFrameSize(code, TRUE) / sizeof(void *)) = GetReturnAddress(code, codeword);

    *next_frame = --ptr;
    next_frame = ptr;
    *--ptr = frame.GetRegisterFrame();
    *--ptr = code;
    *--ptr = frame.GetArgumentsObject();
#ifdef ARCHITECTURE_MIPS
    *--ptr = reinterpret_cast<void *>(static_cast<UINTPTR>(frame.GetArgumentsCount()));
#endif

    if (code->CanHaveVariableObject())
        *--ptr = frame.GetVariableObject();

#ifndef ARCHITECTURE_MIPS
    *--ptr = reinterpret_cast<void *>(static_cast<UINTPTR>(frame.GetArgumentsCount()));
#endif
}
Example #2
0
void
MXUser_DownSemaphore(MXUserSemaphore *sema)  // IN/OUT:
{
   int err;

   ASSERT(sema);
   MXUserValidateHeader(&sema->header, MXUSER_TYPE_SEMA);

   Atomic_Inc(&sema->activeUserCount);

   MXUserAcquisitionTracking(&sema->header, TRUE);  // rank checking

   if (vmx86_stats) {
      VmTimeType start = 0;
      Bool tryDownSuccess = FALSE;
      MXUserAcquireStats *acquireStats;

      acquireStats = Atomic_ReadPtr(&sema->acquireStatsMem);

      if (LIKELY(acquireStats != NULL)) {
         start = Hostinfo_SystemTimerNS();
      }

      err = MXUserTryDown(&sema->nativeSemaphore, &tryDownSuccess);

      if (LIKELY(err == 0)) {
         if (!tryDownSuccess) {
            err = MXUserDown(&sema->nativeSemaphore);
         }
      }

      if (LIKELY((err == 0) && (acquireStats != NULL))) {
         MXUserHisto *histo;
         VmTimeType value = Hostinfo_SystemTimerNS() - start;

         MXUserAcquisitionSample(&acquireStats->data, TRUE,
                                 !tryDownSuccess, value);

         histo = Atomic_ReadPtr(&acquireStats->histo);

         if (UNLIKELY(histo != NULL)) {
            MXUserHistoSample(histo, value, GetReturnAddress());
         }
      }
   } else {
      err = MXUserDown(&sema->nativeSemaphore);
   }

   if (UNLIKELY(err != 0)) {
      MXUserDumpAndPanic(&sema->header, "%s: Internal error (%d)\n",
                         __FUNCTION__, err);
   }

   MXUserReleaseTracking(&sema->header);

   Atomic_Dec(&sema->activeUserCount);
}
Example #3
0
MXUserRecLock *
MXUser_CreateRecLock(const char *userName,  // IN:
                     MX_Rank rank)          // IN:
{
   uint32 statsMode;
   char *properName;
   MXUserRecLock *lock = Util_SafeCalloc(1, sizeof *lock);

   if (userName == NULL) {
      properName = Str_SafeAsprintf(NULL, "R-%p", GetReturnAddress());
   } else {
      properName = Util_SafeStrdup(userName);
   }

   if (!MXRecLockInit(&lock->recursiveLock)) {
      free(properName);
      free(lock);

      return NULL;
   }

   lock->vmmLock = NULL;
   Atomic_Write(&lock->refCount, 1);

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpRecLock;

   statsMode = MXUserStatsMode();

   switch (statsMode) {
   case 0:
      MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
      lock->header.statsFunc = NULL;
      break;

   case 1:
      MXUserEnableStats(&lock->acquireStatsMem, NULL);
      lock->header.statsFunc = MXUserStatsActionRec;
      break;

   case 2:
      MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
      lock->header.statsFunc = MXUserStatsActionRec;
      break;

   default:
      Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode);
   }

   MXUserAddToList(&lock->header);

   return lock;
}
Example #4
0
Bool IsCallerMainModule(LPVOID lpAddress)
{
    DWORD dwAddress = GetReturnAddress(lpAddress);
    for (DWORD i = 0; i != dwImageSections; ++i)
    {
        if (dwAddress >= ImageSections[i].dwAddressStart && dwAddress < ImageSections[i].dwAddressEnd)
            return True;
    }
    return False;
}
Example #5
0
void
MXUser_ReleaseRecLock(MXUserRecLock *lock)  // IN/OUT:
{
   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
   ASSERT(Atomic_Read(&lock->refCount) > 0);

   if (UNLIKELY(lock->vmmLock != NULL)) {
      ASSERT(MXUserMX_UnlockRec);
      (*MXUserMX_UnlockRec)(lock->vmmLock);
   } else {
      if (vmx86_stats) {
         MXUserHeldStats *heldStats = Atomic_ReadPtr(&lock->heldStatsMem);

         if (LIKELY(heldStats != NULL)) {
            if (MXRecLockCount(&lock->recursiveLock) == 1) {
               MXUserHeldStats *heldStats;

               heldStats = Atomic_ReadPtr(&lock->heldStatsMem);

               if (UNLIKELY(heldStats != NULL)) {
                  VmTimeType value;
                  MXUserHisto *histo = Atomic_ReadPtr(&heldStats->histo);

                  value = Hostinfo_SystemTimerNS() - heldStats->holdStart;

                  MXUserBasicStatsSample(&heldStats->data, value);

                  if (UNLIKELY(histo != NULL)) {
                     MXUserHistoSample(histo, value, GetReturnAddress());
                  }
               }
            }
         }
      }

      if (vmx86_debug) {
         if (MXRecLockCount(&lock->recursiveLock) == 0) {
            MXUserDumpAndPanic(&lock->header,
                               "%s: Release of an unacquired recursive lock\n",
                                __FUNCTION__);
         }

         if (!MXRecLockIsOwner(&lock->recursiveLock)) {
            MXUserDumpAndPanic(&lock->header,
                               "%s: Non-owner release of an recursive lock\n",
                               __FUNCTION__);
         }
      }

      MXUserReleaseTracking(&lock->header);

      MXRecLockRelease(&lock->recursiveLock);
   }
}
Example #6
0
void
MXUser_AcquireRecLock(MXUserRecLock *lock)  // IN/OUT:
{
   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_REC);
   ASSERT(Atomic_Read(&lock->refCount) > 0);

   if (UNLIKELY(lock->vmmLock != NULL)) {
      ASSERT(MXUserMX_LockRec);
      (*MXUserMX_LockRec)(lock->vmmLock);
   } else {
      /* Rank checking is only done on the first acquisition */
      MXUserAcquisitionTracking(&lock->header, TRUE);

      if (vmx86_stats) {
         VmTimeType value = 0;
         MXUserAcquireStats *acquireStats;

         acquireStats = Atomic_ReadPtr(&lock->acquireStatsMem);

         MXRecLockAcquire(&lock->recursiveLock,
                          (acquireStats == NULL) ? NULL : &value);

         if (LIKELY(acquireStats != NULL)) {
            if (MXRecLockCount(&lock->recursiveLock) == 1) {
               MXUserHeldStats *heldStats;
               MXUserHisto *histo;

               MXUserAcquisitionSample(&acquireStats->data, TRUE,
                            value > acquireStats->data.contentionDurationFloor,
                                       value);

               histo = Atomic_ReadPtr(&acquireStats->histo);

               if (UNLIKELY(histo != NULL)) {
                  MXUserHistoSample(histo, value, GetReturnAddress());
               }

               heldStats = Atomic_ReadPtr(&lock->heldStatsMem);

               if (UNLIKELY(heldStats != NULL)) {
                  heldStats->holdStart = Hostinfo_SystemTimerNS();
               }
            }
         }
      } else {
         MXRecLockAcquire(&lock->recursiveLock,
                          NULL);  // non-stats
      }
   }
}
Example #7
0
MXUserExclLock *
MXUser_CreateExclLock(const char *userName,  // IN:
                      MX_Rank rank)          // IN:
{
   Bool doStats;
   char *properName;
   MXUserExclLock *lock;

   lock = Util_SafeCalloc(1, sizeof(*lock));

   if (userName == NULL) {
      properName = Str_SafeAsprintf(NULL, "X-%p", GetReturnAddress());
   } else {
      properName = Util_SafeStrdup(userName);
   }

   if (!MXRecLockInit(&lock->recursiveLock)) {
      free(properName);
      free(lock);

      return NULL;
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpExclLock;

   if (vmx86_stats) {
      doStats = MXUserStatsEnabled();
   } else {
      doStats = FALSE;
   }

   if (doStats) {
      MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS);
   } else {
      lock->header.statsFunc = NULL;
      Atomic_WritePtr(&lock->statsMem, NULL);
   }

   MXUserAddToList(&lock->header);

   return lock;
}
Example #8
0
void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
{
    LIMITED_METHOD_CONTRACT;

    pRD->IsCallerContextValid = FALSE;
    pRD->IsCallerSPValid      = FALSE;        // Don't add usage of this field.  This is only temporary.

    pRD->pCurrentContext->Rip = GetReturnAddress();
    pRD->pCurrentContext->Rsp = GetSP();

    UpdateRegDisplayFromCalleeSavedRegisters(pRD, GetCalleeSavedRegisters());
    ClearRegDisplayArgumentAndScratchRegisters(pRD);

    SyncRegDisplayToCurrentContext(pRD);

    LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK    TransitionFrame::UpdateRegDisplay(rip:%p, rsp:%p)\n", pRD->ControlPC, pRD->SP));
}
char *
Str_Strcpy(char *buf,       // OUT
           const char *src, // IN
           size_t maxSize)  // IN
{
   size_t len;

   len = strlen(src);
   if (len >= maxSize) {
#ifdef GetReturnAddress
      Panic("%s:%d Buffer too small 0x%p\n", __FILE__, __LINE__, GetReturnAddress());
#else
      Panic("%s:%d Buffer too small\n", __FILE__, __LINE__);
#endif
   }
   return memcpy(buf, src, len + 1);
}
Example #10
0
MXUserSemaphore *
MXUser_CreateSemaphore(const char *userName,  // IN:
                       MX_Rank rank)          // IN:
{
   char *properName;
   MXUserSemaphore *sema;

   sema = Util_SafeCalloc(1, sizeof(*sema));

   if (userName == NULL) {
      properName = Str_SafeAsprintf(NULL, "Sema-%p", GetReturnAddress());
   } else {
      properName = Util_SafeStrdup(userName);
   }

   if (LIKELY(MXUserInit(&sema->nativeSemaphore) == 0)) {
      sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA);
      sema->header.name = properName;
      sema->header.rank = rank;
      sema->header.serialNumber = MXUserAllocSerialNumber();
      sema->header.dumpFunc = MXUserDumpSemaphore;

      if (MXUserStatsMode() == 0) {
         sema->header.statsFunc = NULL;
         Atomic_WritePtr(&sema->acquireStatsMem, NULL);
      } else {
         MXUserAcquireStats *acquireStats;

         acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats));

         MXUserAcquisitionStatsSetUp(&acquireStats->data);

         sema->header.statsFunc = MXUserStatsActionSema;
         Atomic_WritePtr(&sema->acquireStatsMem, acquireStats);
      }

      MXUserAddToList(&sema->header);
   } else {
      free(properName);
      free(sema);
      sema = NULL;
   }

   return sema;
}
Example #11
0
void
MXUser_AcquireExclLock(MXUserExclLock *lock)  // IN/OUT:
{
   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);

   MXUserAcquisitionTracking(&lock->header, TRUE);

   if (vmx86_stats) {
      VmTimeType value = 0;
      MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem);

      MXRecLockAcquire(&lock->recursiveLock, (stats == NULL) ? NULL : &value);

      if (LIKELY(stats != NULL)) {
         MXUserHisto *histo;

         MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, value != 0,
                                 value);

         histo = Atomic_ReadPtr(&stats->acquisitionHisto);

         if (UNLIKELY(histo != NULL)) {
            MXUserHistoSample(histo, value, GetReturnAddress());
         }

         stats->holdStart = Hostinfo_SystemTimerNS();
      }
   } else {
      MXRecLockAcquire(&lock->recursiveLock,
                       NULL);  // non-stats
   }

   if (vmx86_debug && (MXRecLockCount(&lock->recursiveLock) > 1)) {
      MXUserDumpAndPanic(&lock->header,
                         "%s: Acquire on an acquired exclusive lock\n",
                         __FUNCTION__);
   }
}
Example #12
0
void
MXUser_ReleaseExclLock(MXUserExclLock *lock)  // IN/OUT:
{
   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_EXCL);

   if (vmx86_stats) {
      MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem);

      if (LIKELY(stats != NULL)) {
         MXUserHisto *histo;
         VmTimeType value = Hostinfo_SystemTimerNS() - stats->holdStart;

         MXUserBasicStatsSample(&stats->heldStats, value);

         histo = Atomic_ReadPtr(&stats->heldHisto);

         if (UNLIKELY(histo != NULL)) {
            MXUserHistoSample(histo, value, GetReturnAddress());
         }
      }
   }

   if (vmx86_debug && !MXRecLockIsOwner(&lock->recursiveLock)) {
      int lockCount = MXRecLockCount(&lock->recursiveLock);

      MXUserDumpAndPanic(&lock->header,
                         "%s: Non-owner release of an %s exclusive lock\n",
                         __FUNCTION__,
                         lockCount == 0 ? "unacquired" : "acquired");
   }

   MXUserReleaseTracking(&lock->header);

   MXRecLockRelease(&lock->recursiveLock);
}
Example #13
0
void
MXUser_ReleaseRWLock(MXUserRWLock *lock)  // IN/OUT:
{
   HolderContext *myContext;

   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_RW);

   myContext = MXUserGetHolderContext(lock);

   if (vmx86_stats) {
      MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem);

      if (LIKELY(stats != NULL)) {
         MXUserHisto *histo;
         VmTimeType duration = Hostinfo_SystemTimerNS() - myContext->holdStart;

         /*
          * The statistics are not always atomically safe so protect them
          * when necessary
          */

         if ((myContext->state == RW_LOCKED_FOR_READ) && lock->useNative) {
            MXRecLockAcquire(&lock->recursiveLock,
                             NULL);  // non-stats
         }

         MXUserBasicStatsSample(&stats->heldStats, duration);

         histo = Atomic_ReadPtr(&stats->heldHisto);

         if (UNLIKELY(histo != NULL)) {
            MXUserHistoSample(histo, duration, GetReturnAddress());
         }

         if ((myContext->state == RW_LOCKED_FOR_READ) && lock->useNative) {
            MXRecLockRelease(&lock->recursiveLock);
         }
      }
   }

   if (UNLIKELY(myContext->state == RW_UNLOCKED)) {
      uint32 lockCount = Atomic_Read(&lock->holderCount);

      MXUserDumpAndPanic(&lock->header,
                         "%s: Non-owner release of an %s read-write lock\n",
                         __FUNCTION__,
                         lockCount == 0 ? "unacquired" : "acquired");
   }

   MXUserReleaseTracking(&lock->header);

   Atomic_Dec(&lock->holderCount);

   if (LIKELY(lock->useNative)) {
      int err = MXUserNativeRWRelease(&lock->nativeLock,
                                      myContext->state == RW_LOCKED_FOR_READ);

      if (UNLIKELY(err != 0)) {
         MXUserDumpAndPanic(&lock->header, "%s: Internal error (%d)\n",
                            __FUNCTION__, err);
      }
   } else {
      ASSERT(Atomic_Read(&lock->holderCount) == 0);
      MXRecLockRelease(&lock->recursiveLock);
   }

   myContext->state = RW_UNLOCKED;
}
Example #14
0
static INLINE void
MXUserAcquisition(MXUserRWLock *lock,  // IN/OUT:
                  Bool forRead)        // IN:
{
   HolderContext *myContext;

   ASSERT(lock);
   MXUserValidateHeader(&lock->header, MXUSER_TYPE_RW);

   MXUserAcquisitionTracking(&lock->header, TRUE);

   myContext = MXUserGetHolderContext(lock);

   if (UNLIKELY(myContext->state != RW_UNLOCKED)) {
      MXUserDumpAndPanic(&lock->header,
                         "%s: AcquireFor%s after AcquireFor%s\n",
                         __FUNCTION__,
                        forRead ? "Read" : "Write",
                        (myContext->state == RW_LOCKED_FOR_READ) ? "Read" :
                                                                   "Write");
   }

   if (vmx86_stats) {
      VmTimeType value;
      MXUserStats *stats = Atomic_ReadPtr(&lock->statsMem);

      if (lock->useNative) {
         int err = 0;
         Bool contended;
         VmTimeType begin = Hostinfo_SystemTimerNS();

         contended = MXUserNativeRWAcquire(&lock->nativeLock, forRead, &err);

         value = contended ? Hostinfo_SystemTimerNS() - begin : 0;

         if (UNLIKELY(err != 0)) {
            MXUserDumpAndPanic(&lock->header, "%s: Error %d: contended %d\n",
                               __FUNCTION__, err, contended);
         }
      } else {
         value = 0;

         MXRecLockAcquire(&lock->recursiveLock,
                          (stats == NULL) ? NULL : &value);
      }

      if (LIKELY(stats != NULL)) {
         MXUserHisto *histo;

         /*
          * The statistics are not atomically safe so protect them when
          * necessary.
          */

         if (forRead && lock->useNative) {
            MXRecLockAcquire(&lock->recursiveLock,
                             NULL);  // non-stats
         }

         MXUserAcquisitionSample(&stats->acquisitionStats, TRUE, value != 0,
                                 value);

         histo = Atomic_ReadPtr(&stats->acquisitionHisto);

         if (UNLIKELY(histo != NULL)) {
            MXUserHistoSample(histo, value, GetReturnAddress());
         }

         if (forRead && lock->useNative) {
            MXRecLockRelease(&lock->recursiveLock);
         }

         myContext->holdStart = Hostinfo_SystemTimerNS();
      }
   } else {
      if (LIKELY(lock->useNative)) {
         int err = 0;

         MXUserNativeRWAcquire(&lock->nativeLock, forRead, &err);

         if (UNLIKELY(err != 0)) {
            MXUserDumpAndPanic(&lock->header, "%s: Error %d\n",
                               __FUNCTION__, err);
         }
      } else {
         MXRecLockAcquire(&lock->recursiveLock,
                          NULL);  // non-stats
      }
   }

   if (!forRead || !lock->useNative) {
      ASSERT(Atomic_Read(&lock->holderCount) == 0);
   }

   Atomic_Inc(&lock->holderCount);
   myContext->state = forRead ? RW_LOCKED_FOR_READ : RW_LOCKED_FOR_WRITE;
}
Example #15
0
MXUserRWLock *
MXUser_CreateRWLock(const char *userName,  // IN:
                    MX_Rank rank)          // IN:
{
   Bool lockInited;
   char *properName;
   MXUserRWLock *lock;
   Bool useNative = MXUserNativeRWSupported();

   lock = Util_SafeCalloc(1, sizeof(*lock));

   if (userName == NULL) {
      if (LIKELY(useNative)) {
         properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress());
      } else {
         /* emulated */
         properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress());
      }
   } else {
      properName = Util_SafeStrdup(userName);
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpRWLock;

   /*
    * Always attempt to use native locks when they are available. If, for some
    * reason, a native lock should be available but isn't, fall back to using
    * an internal recursive lock - something is better than nothing.
    */

   lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock);

   lockInited = MXRecLockInit(&lock->recursiveLock);

   if (LIKELY(lockInited)) {
      Bool doStats;

      lock->holderTable = HashTable_Alloc(256,
                                          HASH_INT_KEY | HASH_FLAG_ATOMIC,
                                          MXUserFreeHashEntry);

      if (vmx86_stats) {
         doStats = MXUserStatsEnabled();
      } else {
         doStats = FALSE;
      }

      if (doStats) {
         MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS);
      } else {
         lock->header.statsFunc = NULL;
         Atomic_WritePtr(&lock->statsMem, NULL);
      }

      MXUserAddToList(&lock->header);
   } else {
      if (lock->useNative) {
         MXUserNativeRWDestroy(&lock->nativeLock);
      }

      free(properName);
      free(lock);
      lock = NULL;
   }

   return lock;
}
Example #16
0
MXUserRWLock *
MXUser_CreateRWLock(const char *userName,  // IN:
                    MX_Rank rank)          // IN:
{
   Bool lockInited;
   char *properName;
   Bool useNative = MXUserNativeRWSupported();
   MXUserRWLock *lock = Util_SafeCalloc(1, sizeof *lock);

   if (userName == NULL) {
      if (LIKELY(useNative)) {
         properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress());
      } else {
         /* emulated */
         properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress());
      }
   } else {
      properName = Util_SafeStrdup(userName);
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpRWLock;

   /*
    * Always attempt to use native locks when they are available. If, for some
    * reason, a native lock should be available but isn't, fall back to using
    * an internal recursive lock - something is better than nothing.
    */

   lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock);

   lockInited = MXRecLockInit(&lock->recursiveLock);

   if (LIKELY(lockInited)) {
      uint32 statsMode;

      lock->holderTable = HashTable_Alloc(256,
                                          HASH_INT_KEY | HASH_FLAG_ATOMIC,
                                          MXUserFreeHashEntry);

      statsMode = MXUserStatsMode();

      switch (MXUserStatsMode()) {
      case 0:
         MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
         lock->header.statsFunc = NULL;
         break;

      case 1:
         MXUserEnableStats(&lock->acquireStatsMem, NULL);
         lock->header.statsFunc = MXUserStatsActionRW;
         break;

      case 2:
         MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
         lock->header.statsFunc = MXUserStatsActionRW;
         break;

      default:
         Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode);
      }

      MXUserAddToList(&lock->header);
   } else {
      Panic("%s: native lock initialization routine failed\n", __FUNCTION__);
   }

   return lock;
}