ncbiatomic.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbiatomic.hpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:07:53  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef NCBIATOMIC__HPP
  10. #define NCBIATOMIC__HPP
  11. /*  $Id: ncbiatomic.hpp,v 1000.3 2004/06/01 19:07:53 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Aaron Ucko
  37.  *
  38.  *
  39.  */
  40. /// @file ncbiatomic.hpp
  41. /// Multi-threading -- atomic pointer exchange function
  42. ///
  43. /// MISC:
  44. /// - SwapPointers     -- atomic pointer swap operation
  45. ///
  46. #include <corelib/ncbicntr.hpp>
  47. #if defined(NCBI_OS_DARWIN)  &&  !defined(NCBI_NO_THREADS)
  48. // Needed for SwapPointers, even if not for CAtomicCounter
  49. #  include <CoreServices/CoreServices.h>
  50. // Darwin's <AssertMacros.h> defines check as a variant of assert....
  51. #  ifdef check
  52. #    undef check
  53. #  endif
  54. #endif
  55. BEGIN_NCBI_SCOPE
  56. /** @addtogroup Threads
  57.  *
  58.  * @{
  59.  */
  60. /// Out-of-line implementation; defined and used ifdef NCBI_SLOW_ATOMIC_SWAP.
  61. void* x_SwapPointers(void * volatile * location, void* new_value);
  62. /////////////////////////////////////////////////////////////////////////////
  63. /////////////////////////////////////////////////////////////////////////////
  64. //  IMPLEMENTATION of INLINE functions
  65. /////////////////////////////////////////////////////////////////////////////
  66. // Sigh... this is a big mess because WorkShop's handling of inline
  67. // asm is awkward and a lot of platforms supply compare-and-swap but
  68. // no suitable unconditional swap.  It also doesn't help that standard
  69. // interfaces are typically for integral types.
  70. #if defined(NCBI_COMPILER_WORKSHOP)  &&  !defined(NCBI_NO_THREADS)  &&  !defined(NCBI_COUNTER_IMPLEMENTATION)
  71. /// Set *location to new_value, and return its immediately previous contents.
  72. void* SwapPointers(void * volatile * location, void* new_value);
  73. #else
  74. #  if defined(NCBI_COMPILER_WORKSHOP)  &&  !defined(NCBI_NO_THREADS)
  75. #    ifdef __sparcv9
  76. extern "C"
  77. void* NCBICORE_asm_casx(void* new_value, void** location, void* old_value);
  78. #    elif defined(__i386)
  79. extern "C"
  80. void* NCBICORE_asm_xchg(void* new_value, void** location);
  81. #    endif
  82. #  else
  83. inline
  84. #  endif
  85. void* SwapPointers(void * volatile * location, void* new_value)
  86. {
  87.     void** nv_loc = const_cast<void**>(location);
  88. #  ifdef NCBI_NO_THREADS
  89.     void* old_value = *nv_loc;
  90.     *nv_loc = new_value;
  91.     return old_value;
  92. #  elif defined(NCBI_COMPILER_COMPAQ)
  93.     return reinterpret_cast<void*>
  94.         (__ATOMIC_EXCH_QUAD(nv_loc, reinterpret_cast<long>(new_value)));
  95. #  elif defined(NCBI_OS_IRIX)
  96.     return reinterpret_cast<void*>
  97.         (test_and_set(reinterpret_cast<unsigned long*>(nv_loc),
  98.                       reinterpret_cast<unsigned long>(new_value)));
  99. #  elif defined(NCBI_OS_AIX)
  100.     boolean_t swapped   = FALSE;
  101.     void*     old_value;
  102.     NCBI_SCHED_INIT();
  103.     while (swapped == FALSE) {
  104.         old_value = *location;
  105.         swapped = compare_and_swap(reinterpret_cast<atomic_p>(nv_loc),
  106.                                    reinterpret_cast<int*>(&old_value),
  107.                                    reinterpret_cast<int>(new_value));
  108.         NCBI_SCHED_YIELD();
  109.     }
  110.     return old_value;
  111. #  elif defined(NCBI_OS_DARWIN)
  112.     bool  swapped = false;
  113.     void* old_value;
  114.     NCBI_SCHED_INIT();
  115.     while (swapped == false) {
  116.         old_value = *location;
  117.         swapped = CompareAndSwap(reinterpret_cast<UInt32>(old_value),
  118.                                  reinterpret_cast<UInt32>(new_value),
  119.                                  reinterpret_cast<UInt32*>(nv_loc));
  120.         NCBI_SCHED_YIELD();
  121.     }
  122.     return old_value;
  123. #  elif defined(NCBI_OS_MAC)
  124.     Boolean swapped = FALSE;
  125.     void*   old_value;
  126.     NCBI_SCHED_INIT();
  127.     while (swapped == FALSE) {
  128.         old_value = *location;
  129.         swapped = OTCompareAndSwapPtr(*location, new_value, nv_loc);
  130.         NCBI_SCHED_YIELD();
  131.     }
  132.     return old_value;
  133. #  elif defined(NCBI_OS_MSWIN)
  134.     // InterlockedExchangePointer would be better, but older SDK versions
  135.     // don't declare it. :-/
  136.     return reinterpret_cast<void*>
  137.         (InterlockedExchange(reinterpret_cast<LPLONG>(nv_loc),
  138.                              reinterpret_cast<LONG>(new_value)));
  139. #  elif defined(NCBI_COUNTER_ASM_OK)
  140. #    if defined(__i386) || defined(__x86_64) // same (overloaded) opcode...
  141.     void* old_value;
  142. #      ifdef NCBI_COMPILER_WORKSHOP
  143.     old_value = NCBICORE_asm_xchg(new_value, nv_loc);
  144. #      else
  145.     asm volatile("xchg %0, %1" : "=m" (*nv_loc), "=r" (old_value)
  146.                  : "1" (new_value), "m" (*nv_loc));
  147. #      endif
  148.     return old_value;
  149. #    elif defined(__sparcv9)
  150.     void* old_value;
  151.     NCBI_SCHED_INIT();
  152.     for ( ;; ) {
  153.         // repeatedly try to swap values
  154.         old_value = *location;
  155.         if ( old_value == new_value ) {
  156.             // The new & old values are the same - we can assume them swapped.
  157.             // Anyway, the following logic will not work in this case.
  158.             break;
  159.         }
  160.         void* tmp = new_value;
  161. #      ifdef NCBI_COMPILER_WORKSHOP
  162.         tmp = NCBICORE_asm_casx(tmp, nv_loc, old_value);
  163. #      else
  164.         asm volatile("casx [%3], %2, %1" : "=m" (*nv_loc), "+r" (tmp)
  165.                      : "r" (old_value), "r" (nv_loc), m (*nv_loc));
  166. #      endif
  167.         if (tmp == old_value) {
  168.             // swap was successful
  169.             break;
  170.         }
  171.         NCBI_SCHED_YIELD();
  172.     }
  173.     return old_value;
  174. #    elif defined(__sparc)
  175.     void* old_value;
  176. #      ifdef NCBI_COMPILER_WORKSHOP
  177.     old_value = reinterpret_cast<void*>
  178.         (NCBICORE_asm_swap(reinterpret_cast<TNCBIAtomicValue>(new_value),
  179.                            reinterpret_cast<TNCBIAtomicValue*>(nv_loc)));
  180. #      else
  181.     asm volatile("swap [%2], %1" : "=m" (*nv_loc), "=r" (old_value)
  182.                  : "r" (nv_loc), "1" (new_value), "m" (*nv_loc));
  183. #      endif
  184.     return old_value;
  185. #    else
  186. #      define NCBI_SLOW_ATOMIC_SWAP
  187.     return x_SwapPointers(location, new_value);
  188. #    endif
  189. #  else
  190. #    define NCBI_SLOW_ATOMIC_SWAP
  191.     return x_SwapPointers(location, new_value);
  192. #  endif
  193. }
  194. #endif
  195. /* @} */
  196. END_NCBI_SCOPE
  197. /*
  198.  * ===========================================================================
  199.  * $Log: ncbiatomic.hpp,v $
  200.  * Revision 1000.3  2004/06/01 19:07:53  gouriano
  201.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  202.  *
  203.  * Revision 1.10  2004/04/26 14:31:11  ucko
  204.  * Split up "+m" constraints for GCC assembly, as versions 3.4 and up
  205.  * complain about them.
  206.  *
  207.  * Revision 1.9  2004/02/19 16:50:57  vasilche
  208.  * Use spin counter before sched_yield().
  209.  * Check if new_value == old_value before cacx - logic doesn't work in this case.
  210.  *
  211.  * Revision 1.8  2004/02/18 23:27:56  ucko
  212.  * Fix logic errors, and call sched_yield() between tries rather than spinning.
  213.  *
  214.  * Revision 1.7  2004/02/04 00:38:02  ucko
  215.  * Centralize undefinition of Darwin's check macro.
  216.  *
  217.  * Revision 1.6  2004/02/03 19:28:18  ucko
  218.  * Darwin: include the master CoreServices header because
  219.  * DriverSynchronization.h is officially internal, but limit its use to
  220.  * threaded builds.
  221.  *
  222.  * Revision 1.5  2004/01/21 22:07:37  ucko
  223.  * SwapPointers: use XCHG opcode on x86-64 in addition to vanilla x86.
  224.  *
  225.  * Revision 1.4  2003/10/09 21:02:48  ucko
  226.  * Only predeclare SwapPointers when not inlining it, to avoid a warning.
  227.  *
  228.  * Revision 1.3  2003/10/02 12:35:08  ucko
  229.  * Always define SwapPointers (as inline) for ST WorkShop builds.
  230.  *
  231.  * Revision 1.2  2003/09/23 19:46:41  rsmith
  232.  * Get rid of old Boolean macros and use built in bool on Mac OSX
  233.  *
  234.  * Revision 1.1  2003/09/17 15:20:45  vasilche
  235.  * Moved atomic counter swap functions to separate file.
  236.  * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods.
  237.  *
  238.  * Revision 1.20  2003/07/31 19:29:03  ucko
  239.  * SwapPointers: fix for Mac OS (classic and X) and AIX.
  240.  *
  241.  * Revision 1.19  2003/06/27 17:27:44  ucko
  242.  * +SwapPointers
  243.  * ===========================================================================
  244.  */
  245. #endif//NCBIATOMIC__HPP