hxmutexlock.h
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:18k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK *****  
  2.  * Source last modified: $Id: hxmutexlock.h,v 1.3 2003/08/03 22:00:44 dcollins Exp $ 
  3.  *   
  4.  * Portions Copyright (c) 1995-2003 RealNetworks, Inc. All Rights Reserved.  
  5.  *       
  6.  * The contents of this file, and the files included with this file, 
  7.  * are subject to the current version of the RealNetworks Public 
  8.  * Source License (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the current version of the RealNetworks Community 
  11.  * Source License (the "RCSL") available at 
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL 
  13.  * will apply. You may also obtain the license terms directly from 
  14.  * RealNetworks.  You may not use this file except in compliance with 
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable 
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for 
  17.  * the rights, obligations and limitations governing use of the 
  18.  * contents of the file. 
  19.  *   
  20.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  21.  * developer of the Original Code and owns the copyrights in the 
  22.  * portions it created. 
  23.  *   
  24.  * This file, and the files included with this file, is distributed 
  25.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY 
  26.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS 
  27.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES 
  28.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET 
  29.  * ENJOYMENT OR NON-INFRINGEMENT. 
  30.  *  
  31.  * Technology Compatibility Kit Test Suite(s) Location:  
  32.  *    http://www.helixcommunity.org/content/tck  
  33.  *  
  34.  * Contributor(s):  
  35.  *   
  36.  * ***** END LICENSE BLOCK ***** */  
  37. /*
  38.  *  Non-reentrant mutexes for various server platforms.
  39.  */
  40. /***********************************************************************
  41.  *  THIS CODE IS HIGHLY CRITICAL TO THE SERVER'S STABILITY!!!
  42.  *  DO NOT MAKE CHANGES TO THE ATOMIC OPERATORS OR TO THE
  43.  *  MUTEX CODE WITHOUT A SERVER TEAM CODE-REVIEW! (dev@helix-server)
  44.  */
  45. /***********************************************************************
  46.  *
  47.  *  Platforms supported:
  48.  *    Windows / x86
  49.  *    Solaris / sparc 
  50.  *    IRIX / MIPS
  51.  *    AIX / PowerPC
  52.  *    Tru64(OSF) / Alpha
  53.  *    HP-UX / PA-RISC
  54.  *    HP-UX / Itanium
  55.  *    Misc. Unix / x86  (Linux, FreeBSD...)
  56.  *
  57.  *  XXXDC: So far, in nearly all cases, native mutexes provided by
  58.  *  OS vendors have been buggy and/or very slow.  Well-written 
  59.  *  assembly-language mutexes are strongly preferred.
  60.  *  Be especially careful about byte-alignment issues.
  61.  *
  62.  */
  63. /***********************************************************************
  64.  *
  65.  * Externally-available routines:
  66.  *
  67.  * inline void HXMutexLock(HX_MUTEX pLock, BOOL bWait = FALSE)
  68.  *     Locks the mutex, blocking until available;  A delay
  69.  *     between attempts to grab the lock is used if bWait is TRUE.
  70.  *     Note that the default is a tight no-delay spinlock, so
  71.  *     always set bWait to TRUE unless you know you should do otherwise.
  72.  *
  73.  * inline BOOL HXMutexTryLock(HX_MUTEX pLock)
  74.  *     Locks the mutex if available, returning TRUE if the lock succeeded,
  75.  *     and returning FALSE otherwise.
  76.  *
  77.  * inline void HXMutexUnlock(HX_MUTEX pLock)
  78.  *     Unlocks the mutex.
  79.  *
  80.  * inline HX_MUTEX HXMutexCreate()
  81.  *     Creates the mutex.
  82.  *
  83.  * inline void HXMutexInit(HX_MUTEX pLock)
  84.  *     Initializes the mutex.
  85.  *
  86.  * inline void HXMutexDestroy(HX_MUTEX pLock)
  87.  *     Destroys the mutex.
  88.  *
  89.  *
  90.  *  Additionally, this file defines IHXMutex, a COM wrapper for the above.
  91.  *
  92.  *
  93.  * NOTES:
  94.  * The older HXxxxMutex variations of the above are depreciated
  95.  * and should be converted over the the above variations for consistancy.
  96.  * HXMutexUnInit() is also depreciated, it never did anything and
  97.  * the purpose of it has been lost.  It appears useless.
  98.  *
  99.  */
  100. /***********************************************************************
  101.  *
  102.  * On most platforms the above are implemented using the
  103.  * following internal routines/#defines (do NOT call these directly!):
  104.  *
  105.  * int _HXMutexSetBit(HX_MUTEX pLock)
  106.  *     Lock the lock and return the old value of the lock
  107.  *     (0 meaning it was unlocked and is now locked, non-zero otherwise)
  108.  *
  109.  * _HXMutexClearBit(pLock)    
  110.  *     Clears the mutex flag.
  111.  *
  112.  * BOOL _HXMutexYieldCPUIfNeeded()
  113.  *     On some platforms we have to explicitly yield the CPU.
  114.  *     This is not needed on most platforms.
  115.  *
  116.  * void _HXMutexInitBit(HX_MUTEX pLock)
  117.  *     Initializes the mutex, typically just calls _HXMutexClearBit().
  118.  *
  119.  * void _HXMutexDestroyBit(HX_MUTEX pLock)
  120.  *     Destroys the mutex, typically does nothing.
  121.  */
  122. #ifndef _HXMUTEXLOCK_H_
  123. #define _HXMUTEXLOCK_H_
  124. /***********************************************************************
  125.  * Common defines/includes
  126.  */
  127. //system
  128. #include  <stdio.h>
  129. //include
  130. #include "hxtypes.h"
  131. #include "hxengin.h"
  132. //hxmisc
  133. #include "microsleep.h"
  134. /***********************************************************************
  135.  * OSF(Tru64) / Alpha defines/includes
  136.  */
  137. #if defined _OSF1
  138. #include <alpha/builtins.h>
  139. typedef struct
  140. {
  141.    char          p;
  142.    unsigned long for_alignment;
  143. } _HXMutexLockType;
  144. #define HX_MUTEX volatile _HXMutexLockType* volatile
  145. #define HX_MUTEX_TYPE volatile _HXMutexLockType
  146. #define HX_MUTEX_BASE_TYPE _HXMutexLockType
  147. /***********************************************************************
  148.  * HP-UX / Itanium defines/includes
  149.  */
  150. #elif defined _HPUX && defined _IA64
  151. #define HX_MUTEX volatile int* volatile
  152. #define HX_MUTEX_TYPE volatile int
  153. #define HX_MUTEX_BASE_TYPE int
  154. /***********************************************************************
  155.  * HP-UX / PA-RISC defines/includes
  156.  */
  157. #elif defined _HPUX
  158. extern "C" {
  159.     int load_and_clear(volatile char* volatile p);
  160. };
  161. typedef struct
  162. {
  163.     char      p;
  164.     long long for_alignment;
  165. } _HXMutexLockType;
  166. #define HX_MUTEX volatile _HXMutexLockType* volatile
  167. #define HX_MUTEX_TYPE volatile _HXMutexLockType  
  168. #define HX_MUTEX_BASE_TYPE _HXMutexLockType  
  169. // for 64-bit or 32-bit
  170. #define alignedaddr(x) (volatile int *)((PTR_INT)(x) + 15 & ~0xf)
  171. #define release_spinlock(LockArea)  if (1) {  
  172.      (*alignedaddr(LockArea) = 1); }
  173. /***********************************************************************
  174.  * AIX / PowerPC defines/includes
  175.  */
  176. #elif defined _AIX
  177. #include <errno.h>
  178. // NATIVE MUTEX
  179. #include <sys/mman.h>
  180. #define HX_MUTEX msemaphore*
  181. #define HX_MUTEX_TYPE msemaphore
  182. #define HX_MUTEX_BASE_TYPE msemaphore
  183. // ASSEMBLY MUTEX
  184. //#define HX_MUTEX volatile int* volatile
  185. //#define HX_MUTEX_TYPE volatile int
  186. //#define HX_MUTEX_BASE_TYPE int
  187. /***********************************************************************
  188.  * IRIX / MIPS defines/includes
  189.  */
  190. #elif defined _IRIX
  191. #include <abi_mutex.h>
  192. #define HX_MUTEX abilock_t*
  193. #define HX_MUTEX_TYPE abilock_t
  194. #define HX_MUTEX_BASE_TYPE abilock_t
  195. /***********************************************************************
  196.  * Windows x86 defines/includes
  197.  */
  198. #elif defined _WIN32
  199. #include <winbase.h>
  200. #define HX_MUTEX volatile int* volatile
  201. #define HX_MUTEX_TYPE volatile int
  202. #define HX_MUTEX_BASE_TYPE int
  203. /***********************************************************************
  204.  * generic defines/includes
  205.  */
  206. #else
  207. #define HX_MUTEX volatile int* volatile
  208. #define HX_MUTEX_TYPE volatile int
  209. #define HX_MUTEX_BASE_TYPE int
  210. #endif
  211. /***********************************************************************
  212.  * misc globals
  213.  *
  214.  * TODO: analyze more closely what the optimal delay is.
  215.  */
  216. #ifndef HX_MUTEX_DELAY
  217. #define HX_MUTEX_DELAY 10000
  218. #endif
  219. // Backoff Configs
  220. // XXXDC - Needs to be fine-tuned on a platform-specific basis!!!
  221. // XXXDC - highly experimental!
  222. #ifdef XXXDC_USE_BACKOFF
  223. #define BACKOFF_THRESHOLD  5     // # failed locks before delay starts
  224. #define BACKOFF_START      100   // usec to initially delay
  225. #define BACKOFF_FACTOR     10    // muliply each delay by this
  226. #define BACKOFF_MAX        15000 // maximum usec to delay
  227. #endif
  228. /***********************************************************************/
  229. /***********************************************************************
  230.  * Windows x86
  231.  *
  232.  * Implementation Notes:
  233.  *   Uses assembly mutex
  234.  */
  235. #if defined _WIN32
  236. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  237. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  238. #define _HXMutexDestroyBit(pLock)  /* not needed */
  239. #define _HXMutexClearBit(pLock)    (*(pLock) = 0)
  240. inline static int
  241. _HXMutexSetBit(HX_MUTEX pLock)
  242. {
  243.     register int nOldBit;
  244.     _asm
  245.     {
  246.         mov eax, 1
  247.         mov ebx, pLock
  248.         xchg dword ptr [ebx], eax
  249.         mov nOldBit, eax
  250.     }
  251.     return nOldBit;
  252. }
  253. /***********************************************************************
  254.  * Solaris / sparc / gcc
  255.  *
  256.  * Implementation Notes:
  257.  *   Uses assembly mutex
  258.  *   GCC inline-assembly syntax
  259.  */
  260. #elif defined _SOLARIS && defined __GNUC__
  261. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  262. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  263. #define _HXMutexDestroyBit(pLock)  /* not needed */
  264. #define _HXMutexClearBit(pLock)    (*(pLock) = 0)
  265. inline static int
  266. _HXMutexSetBit(HX_MUTEX pLock)
  267. {
  268.     volatile int nOldBit;
  269.     __asm__ __volatile__("swap [%0], %1"
  270.                         : "=r" (pLock), "=&r" (nOldBit)
  271.                         : "0" (pLock), "1" (1));
  272.     return nOldBit;
  273. }
  274. /***********************************************************************
  275.  * Solaris / sparc / native compiler
  276.  *
  277.  * Implementation Notes:
  278.  *   Uses assembly mutex
  279.  *   native-compiler syntax
  280.  */
  281. #elif defined _SOLARIS /* native compiler */
  282. extern "C" int _HXMutexSetBitCAS(HX_MUTEX pLock);
  283. extern "C" int _HXMutexSetBitSWAP(HX_MUTEX pLock);
  284. extern "C" int _HXMutexClearBit(HX_MUTEX pLock);
  285. #define _HXMutexSetBit(pLock)      _HXMutexSetBitCAS(pLock)
  286. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  287. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  288. #define _HXMutexDestroyBit(pLock)  /* not needed */
  289. /***********************************************************************
  290.  * IRIX / MIPS
  291.  *
  292.  * Implementation Notes:
  293.  *   Uses native mutex calls acquire_lock/etc.
  294.  *   On this platform we explicitly yield the processor
  295.  */
  296. #elif defined _IRIX
  297. #define _HXMutexYieldCPUIfNeeded() sginap(0)
  298. #define _HXMutexSetBit(pLock)      acquire_lock(pLock)
  299. #define _HXMutexClearBit(pLock)    release_lock(pLock)
  300. #define _HXMutexInitBit(pLock)     init_lock(pLock)
  301. #define _HXMutexDestroyBit(pLock)  /* not needed */
  302. /***********************************************************************
  303.  * AIX / PowerPC
  304.  *
  305.  * Implementation Notes:
  306.  *   Uses native mutex calls msem_lock/etc.
  307.  */
  308. #elif defined _AIX
  309. // NATIVE MUTEX
  310. //this doesn't work cleanly, we had to customize HXMutexLock() for AIX
  311. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  312. #define _HXMutexSetBit(pLock)      msem_lock(pLock, MSEM_IF_NOWAIT)
  313. #define _HXMutexClearBit(pLock)    msem_unlock(pLock, 0)
  314. #define _HXMutexInitBit(pLock)     msem_init(pLock, MSEM_UNLOCKED)
  315. #define _HXMutexDestroyBit(pLock)  msem_remove(pLock)
  316. // ASSEMBLY MUTEX
  317. //#include <sched.h>
  318. //#define _HXMutexYieldCPUIfNeeded() sched_yield()
  319. //extern "C" int _HXMutexSetBit(HX_MUTEX pLock);
  320. //extern "C" int _HXMutexClearBit(HX_MUTEX pLock);
  321. //#define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  322. //#define _HXMutexDestroyBit(pLock)  /* not needed */
  323. /***********************************************************************
  324.  * HP-UX / Itanium
  325.  *
  326.  * Implementation Notes:
  327.  *   Uses non-inline assembly mutex call _HXMutexSetBit(), defined
  328.  *   in common/util/platform/hpux/spinlock-ia64.s.   XXX: make this inline.
  329.  */
  330. #elif defined _HPUX && defined _IA64
  331. extern "C" int _HXMutexSetBit(HX_MUTEX pLock);
  332. extern "C" int _HXMutexClearBit(HX_MUTEX pLock);
  333. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  334. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  335. #define _HXMutexDestroyBit(pLock)  /* not needed */
  336. /***********************************************************************
  337.  * HP-UX / PA-RISC
  338.  *
  339.  * Implementation Notes:
  340.  *   Uses non-inline assembly mutex call load_and_clear(), defined
  341.  *   in common/util/platform/hpux/spin.s.   XXX: make this inline.
  342.  *   The logic of this mutex is backwards from most of our others,
  343.  *   1 means clear, 0 means set.
  344.  */
  345. #elif defined _HPUX
  346. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  347. #define _HXMutexSetBit(pLock)      (load_and_clear((char* volatile)pLock) == 0)
  348. #define _HXMutexClearBit(pLock)   release_spinlock(pLock)
  349. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  350. #define _HXMutexDestroyBit(pLock)  /* not needed */
  351. /***********************************************************************
  352.  * Tru64 (OSF/1) / Alpha
  353.  *
  354.  * Implementation Notes:
  355.  *   Uses native mutex calls __LOCK_LONG_RETRY/etc.
  356.  *
  357.  * TODO:
  358.  *   This native mutex is much slower than on other platforms.
  359.  *   Change this to use assembly.
  360.  */
  361. #elif defined _OSF1
  362. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  363. #define _HXMutexSetBit(pLock)      (__LOCK_LONG_RETRY(pLock, 1) == 0)
  364. #define _HXMutexClearBit(pLock)    __UNLOCK_LONG(pLock)
  365. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  366. #define _HXMutexDestroyBit(pLock)  /* not needed */
  367. /***********************************************************************
  368.  * Misc. Unix / x86  (Linux, FreeBSD...)
  369.  *
  370.  * Implementation Notes:
  371.  *   Uses assembly mutex
  372.  *   GCC inline-assembly syntax
  373.  *
  374.  * TODO: add non-x86 support for Linux/FreeBSD/etc.
  375.  */
  376. #else
  377. #define _HXMutexYieldCPUIfNeeded() /* not needed */
  378. #define _HXMutexInitBit(pLock)     _HXMutexClearBit(pLock)
  379. #define _HXMutexDestroyBit(pLock)  /* not needed */
  380. #define _HXMutexClearBit(pLock)    (*(pLock) = 0)
  381. /*
  382.  * GCC gets really mad if we use eax / ebx in the assembly below.
  383.  * We use ecx / edx instead (cross your fingers =)
  384.  */
  385. inline static int
  386. _HXMutexSetBit(HX_MUTEX pLock)
  387. {
  388.     volatile int nOldBit;
  389.     __asm__ __volatile__("xchg %%ecx, (%%edx)"
  390. : "=c" (nOldBit)
  391. : "c" (1), "d" (pLock));
  392.     return nOldBit;
  393. }
  394. #endif
  395. /***********************************************************************
  396.  * Common code, shared by multiple platforms
  397.  *
  398.  */
  399. #if !defined(HELIX_FEATURE_SERVER) && !defined(HX_MUTEX_PRIVATE_COLLISION_COUNTERS) && !defined(HX_MUTEX_PRIVATE_COLLISION_COUNTERS)
  400. //default for non-server products is to not use the collision counters
  401. #define HX_MUTEX_NO_COLLISION_COUNTERS
  402. #endif
  403. #if defined HX_MUTEX_NO_COLLISION_COUNTERS
  404. #define HXMutexCollision(p)    /* nothing */
  405. #elif defined HX_MUTEX_PRIVATE_COLLISION_COUNTERS
  406. /* User must define their own HXMutexCollision(p) */
  407. #else
  408. extern HX_MUTEX g_pServerMainLock;
  409. extern UINT32* g_pConcurrentOps;
  410. extern UINT32* g_pConcurrentMemOps;
  411. inline void
  412. HXMutexCollision(HX_MUTEX pLock)
  413. {
  414.     ++(*g_pConcurrentOps);
  415.     if (pLock != g_pServerMainLock)
  416.         ++(*g_pConcurrentMemOps);
  417. }
  418. #endif
  419. #ifndef HX_MUTEX_CUSTOM_COLLISION_DELAY
  420. #define HXMutexCollisionDelay(n) microsleep(n)
  421. #else
  422. /* User must define their own HXMutexCollisionDelay() */
  423. #endif
  424. //will obsolete these old names shortly...
  425. #define HXCreateMutex()   HXMutexCreate()
  426. #define HXInitMutex(p)    HXMutexInit(p)
  427. #define HXUnInitMutex(p)  HXMutexUnInit(p)
  428. #define HXDestroyMutex(p) HXMutexDestroy(p)
  429. #ifdef HX_MUTEX_USE_MANAGED_LOCKS
  430. HX_RESULT AddManagedMutex(HX_MUTEX pMutex);
  431. HX_RESULT RemoveManagedMutex(HX_MUTEX pMutex);
  432. #endif
  433. inline void
  434. HXMutexLock(HX_MUTEX pLock, BOOL bWait = FALSE)
  435. {
  436. #ifdef XXXDC_USE_BACKOFF
  437.     if (_HXMutexSetBit(pLock))
  438.     {
  439.         register int nInitialTries = 1;
  440.   register int nDelay = BACKOFF_START;
  441.    
  442.         //spin on reads for a bit (not writes)
  443.         while (*pLock && nInitialTries < BACKOFF_THRESHOLD)
  444.         {
  445.             HXMutexCollision(pLock);
  446.             ++nInitialTries;
  447.         }
  448.         while(_HXMutexSetBit(pLock))
  449.         {
  450.             _HXMutexYieldCPUIfNeeded();
  451.             if (bWait)
  452.             {
  453. HXMutexCollisionDelay(nDelay);
  454. nDelay = nDelay * BACKOFF_FACTOR;
  455. if (nDelay > BACKOFF_MAX)
  456.     nDelay = BACKOFF_MAX;
  457.             }
  458.             HXMutexCollision(pLock);
  459.         }
  460.     }
  461. #elif defined _AIX
  462.     do
  463.     {
  464.         if (msem_lock(pLock, 0) == 0) break;
  465.     } while (errno == EINTR);
  466. #else
  467.     while(_HXMutexSetBit(pLock))
  468.     {
  469.         _HXMutexYieldCPUIfNeeded();
  470.         if (bWait)
  471.         {
  472.             HXMutexCollisionDelay(HX_MUTEX_DELAY);
  473.         }
  474.         HXMutexCollision(pLock);
  475.     }
  476. #endif
  477. #ifdef HX_MUTEX_USE_MANAGED_LOCKS
  478.     AddManagedMutex(pLock);
  479. #endif
  480. }
  481. inline BOOL
  482. HXMutexTryLock(HX_MUTEX pLock)
  483. {
  484. #ifdef _AIX
  485.     BOOL bRet = (msem_lock(pLock, 0) == 0);
  486. #ifdef HX_MUTEX_USE_MANAGED_LOCKS
  487.     if (bRet)
  488.         AddManagedMutex(pLock);
  489. #endif
  490.     return bRet;
  491. #else
  492.     if (_HXMutexSetBit(pLock))
  493.     {
  494.         HXMutexCollision(pLock);
  495.         return FALSE;
  496.     }
  497. #ifdef HX_MUTEX_USE_MANAGED_LOCKS
  498.     AddManagedMutex(pLock);
  499. #endif
  500.     return TRUE;
  501. #endif
  502. }
  503. inline void
  504. HXMutexUnlock(HX_MUTEX pLock)
  505. {
  506. #ifdef HX_MUTEX_USE_MANAGED_LOCKS
  507.     RemoveManagedMutex(pLock);
  508. #endif
  509.     _HXMutexClearBit(pLock);
  510. }
  511. inline HX_MUTEX
  512. HXMutexCreate()
  513. {
  514.     HX_MUTEX pLock = (HX_MUTEX) new HX_MUTEX_BASE_TYPE;
  515.     _HXMutexInitBit(pLock);
  516.     return pLock;
  517. }
  518. inline void
  519. HXMutexInit(HX_MUTEX pLock)
  520. {
  521.     _HXMutexClearBit(pLock);
  522. }
  523. inline void
  524. HXMutexUnInit(HX_MUTEX pLock)
  525. {
  526.    /* no-op */
  527. }
  528. inline void
  529. HXMutexDestroy(HX_MUTEX pLock)
  530. {
  531.     _HXMutexDestroyBit(pLock);
  532. #if defined _WINDOWS
  533.     delete (void*)pLock;
  534. #else
  535.     delete pLock;
  536. #endif
  537. }
  538. #endif /* _HXMUTEXLOCK_H_ */