| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /************************************************************************************
- Filename : OVR_Atomic.cpp
- Content : Contains atomic operations and inline fastest locking
- functionality. Will contain #ifdefs for OS efficiency.
- Have non-thread-safe implementation if not available.
- Created : September 19, 2012
- Notes :
- Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
- Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
- you may not use the Oculus VR Rift SDK except in compliance with the License,
- which is provided at the time of installation or download, or which
- otherwise accompanies this software in either electronic or hard copy form.
- You may obtain a copy of the License at
- http://www.oculusvr.com/licenses/LICENSE-3.2
- Unless required by applicable law or agreed to in writing, the Oculus VR SDK
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ************************************************************************************/
- #include "OVR_Atomic.h"
- #include "OVR_Allocator.h"
- #ifdef OVR_ENABLE_THREADS
- // Include Windows 8-Metro compatible Synchronization API
- #if defined(OVR_OS_MS) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
- #include <synchapi.h>
- #endif
- namespace OVR {
- // ***** Windows Lock implementation
- #if defined(OVR_OS_MS)
- // ***** Standard Win32 Lock implementation
- // Constructors
- Lock::Lock(unsigned spinCount)
- {
- #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
- // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility
- InitializeCriticalSectionEx(&cs, (DWORD)spinCount,
- OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO));
- #else
- ::InitializeCriticalSectionAndSpinCount(&cs, (DWORD)spinCount); // This is available with WindowsXP+.
- #endif
- }
- Lock::~Lock()
- {
- DeleteCriticalSection(&cs);
- }
- #endif
- //-------------------------------------------------------------------------------------
- // ***** SharedLock
- // This is a general purpose globally shared Lock implementation that should probably be
- // moved to Kernel.
- // May in theory busy spin-wait if we hit contention on first lock creation,
- // but this shouldn't matter in practice since Lock* should be cached.
- enum { LockInitMarker = 0xFFFFFFFF };
- Lock* SharedLock::GetLockAddRef()
- {
- int oldUseCount;
- do {
- oldUseCount = UseCount;
- if (oldUseCount == (int)LockInitMarker)
- continue;
- if (oldUseCount == 0)
- {
- // Initialize marker
- if (UseCount.CompareAndSet_Sync(0, LockInitMarker))
- {
- Construct<Lock>(Buffer);
- do { }
- while (UseCount.CompareAndSet_Sync(LockInitMarker, 1));
- return toLock();
- }
- continue;
- }
- } while (!UseCount.CompareAndSet_NoSync(oldUseCount, oldUseCount + 1));
- return toLock();
- }
- void SharedLock::ReleaseLock(Lock* plock)
- {
- OVR_UNUSED(plock);
- OVR_ASSERT(plock == toLock());
- int oldUseCount;
- do {
- oldUseCount = UseCount;
- OVR_ASSERT(oldUseCount != (int)LockInitMarker);
- if (oldUseCount == 1)
- {
- // Initialize marker
- if (UseCount.CompareAndSet_Sync(1, LockInitMarker))
- {
- Destruct<Lock>(toLock());
- do { }
- while (!UseCount.CompareAndSet_Sync(LockInitMarker, 0));
- return;
- }
- continue;
- }
- } while (!UseCount.CompareAndSet_NoSync(oldUseCount, oldUseCount - 1));
- }
- } // OVR
- #endif // OVR_ENABLE_THREADS
|