📄 ncbiatomic.hpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbiatomic.hpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:07:53 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10 * PRODUCTION * =========================================================================== */#ifndef NCBIATOMIC__HPP#define NCBIATOMIC__HPP/* $Id: ncbiatomic.hpp,v 1000.3 2004/06/01 19:07:53 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Aaron Ucko * * *//// @file ncbiatomic.hpp/// Multi-threading -- atomic pointer exchange function////// MISC:/// - SwapPointers -- atomic pointer swap operation///#include <corelib/ncbicntr.hpp>#if defined(NCBI_OS_DARWIN) && !defined(NCBI_NO_THREADS)// Needed for SwapPointers, even if not for CAtomicCounter# include <CoreServices/CoreServices.h>// Darwin's <AssertMacros.h> defines check as a variant of assert....# ifdef check# undef check# endif#endifBEGIN_NCBI_SCOPE/** @addtogroup Threads * * @{ *//// Out-of-line implementation; defined and used ifdef NCBI_SLOW_ATOMIC_SWAP.void* x_SwapPointers(void * volatile * location, void* new_value);//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IMPLEMENTATION of INLINE functions/////////////////////////////////////////////////////////////////////////////// Sigh... this is a big mess because WorkShop's handling of inline// asm is awkward and a lot of platforms supply compare-and-swap but// no suitable unconditional swap. It also doesn't help that standard// interfaces are typically for integral types.#if defined(NCBI_COMPILER_WORKSHOP) && !defined(NCBI_NO_THREADS) && !defined(NCBI_COUNTER_IMPLEMENTATION)/// Set *location to new_value, and return its immediately previous contents.void* SwapPointers(void * volatile * location, void* new_value);#else# if defined(NCBI_COMPILER_WORKSHOP) && !defined(NCBI_NO_THREADS)# ifdef __sparcv9extern "C"void* NCBICORE_asm_casx(void* new_value, void** location, void* old_value);# elif defined(__i386)extern "C"void* NCBICORE_asm_xchg(void* new_value, void** location);# endif# elseinline# endifvoid* SwapPointers(void * volatile * location, void* new_value){ void** nv_loc = const_cast<void**>(location);# ifdef NCBI_NO_THREADS void* old_value = *nv_loc; *nv_loc = new_value; return old_value;# elif defined(NCBI_COMPILER_COMPAQ) return reinterpret_cast<void*> (__ATOMIC_EXCH_QUAD(nv_loc, reinterpret_cast<long>(new_value)));# elif defined(NCBI_OS_IRIX) return reinterpret_cast<void*> (test_and_set(reinterpret_cast<unsigned long*>(nv_loc), reinterpret_cast<unsigned long>(new_value)));# elif defined(NCBI_OS_AIX) boolean_t swapped = FALSE; void* old_value; NCBI_SCHED_INIT(); while (swapped == FALSE) { old_value = *location; swapped = compare_and_swap(reinterpret_cast<atomic_p>(nv_loc), reinterpret_cast<int*>(&old_value), reinterpret_cast<int>(new_value)); NCBI_SCHED_YIELD(); } return old_value;# elif defined(NCBI_OS_DARWIN) bool swapped = false; void* old_value; NCBI_SCHED_INIT(); while (swapped == false) { old_value = *location; swapped = CompareAndSwap(reinterpret_cast<UInt32>(old_value), reinterpret_cast<UInt32>(new_value), reinterpret_cast<UInt32*>(nv_loc)); NCBI_SCHED_YIELD(); } return old_value;# elif defined(NCBI_OS_MAC) Boolean swapped = FALSE; void* old_value; NCBI_SCHED_INIT(); while (swapped == FALSE) { old_value = *location; swapped = OTCompareAndSwapPtr(*location, new_value, nv_loc); NCBI_SCHED_YIELD(); } return old_value;# elif defined(NCBI_OS_MSWIN) // InterlockedExchangePointer would be better, but older SDK versions // don't declare it. :-/ return reinterpret_cast<void*> (InterlockedExchange(reinterpret_cast<LPLONG>(nv_loc), reinterpret_cast<LONG>(new_value)));# elif defined(NCBI_COUNTER_ASM_OK)# if defined(__i386) || defined(__x86_64) // same (overloaded) opcode... void* old_value;# ifdef NCBI_COMPILER_WORKSHOP old_value = NCBICORE_asm_xchg(new_value, nv_loc);# else asm volatile("xchg %0, %1" : "=m" (*nv_loc), "=r" (old_value) : "1" (new_value), "m" (*nv_loc));# endif return old_value;# elif defined(__sparcv9) void* old_value; NCBI_SCHED_INIT(); for ( ;; ) { // repeatedly try to swap values old_value = *location; if ( old_value == new_value ) { // The new & old values are the same - we can assume them swapped. // Anyway, the following logic will not work in this case. break; } void* tmp = new_value;# ifdef NCBI_COMPILER_WORKSHOP tmp = NCBICORE_asm_casx(tmp, nv_loc, old_value);# else asm volatile("casx [%3], %2, %1" : "=m" (*nv_loc), "+r" (tmp) : "r" (old_value), "r" (nv_loc), m (*nv_loc));# endif if (tmp == old_value) { // swap was successful break; } NCBI_SCHED_YIELD(); } return old_value;# elif defined(__sparc) void* old_value;# ifdef NCBI_COMPILER_WORKSHOP old_value = reinterpret_cast<void*> (NCBICORE_asm_swap(reinterpret_cast<TNCBIAtomicValue>(new_value), reinterpret_cast<TNCBIAtomicValue*>(nv_loc)));# else asm volatile("swap [%2], %1" : "=m" (*nv_loc), "=r" (old_value) : "r" (nv_loc), "1" (new_value), "m" (*nv_loc));# endif return old_value;# else# define NCBI_SLOW_ATOMIC_SWAP return x_SwapPointers(location, new_value);# endif# else# define NCBI_SLOW_ATOMIC_SWAP return x_SwapPointers(location, new_value);# endif}#endif/* @} */END_NCBI_SCOPE/* * =========================================================================== * $Log: ncbiatomic.hpp,v $ * Revision 1000.3 2004/06/01 19:07:53 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10 * * Revision 1.10 2004/04/26 14:31:11 ucko * Split up "+m" constraints for GCC assembly, as versions 3.4 and up * complain about them. * * Revision 1.9 2004/02/19 16:50:57 vasilche * Use spin counter before sched_yield(). * Check if new_value == old_value before cacx - logic doesn't work in this case. * * Revision 1.8 2004/02/18 23:27:56 ucko * Fix logic errors, and call sched_yield() between tries rather than spinning. * * Revision 1.7 2004/02/04 00:38:02 ucko * Centralize undefinition of Darwin's check macro. * * Revision 1.6 2004/02/03 19:28:18 ucko * Darwin: include the master CoreServices header because * DriverSynchronization.h is officially internal, but limit its use to * threaded builds. * * Revision 1.5 2004/01/21 22:07:37 ucko * SwapPointers: use XCHG opcode on x86-64 in addition to vanilla x86. * * Revision 1.4 2003/10/09 21:02:48 ucko * Only predeclare SwapPointers when not inlining it, to avoid a warning. * * Revision 1.3 2003/10/02 12:35:08 ucko * Always define SwapPointers (as inline) for ST WorkShop builds. * * Revision 1.2 2003/09/23 19:46:41 rsmith * Get rid of old Boolean macros and use built in bool on Mac OSX * * Revision 1.1 2003/09/17 15:20:45 vasilche * Moved atomic counter swap functions to separate file. * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods. * * Revision 1.20 2003/07/31 19:29:03 ucko * SwapPointers: fix for Mac OS (classic and X) and AIX. * * Revision 1.19 2003/06/27 17:27:44 ucko * +SwapPointers * =========================================================================== */#endif//NCBIATOMIC__HPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -