Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Atomic.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : OVR_Atomic.cpp
4 Content : Contains atomic operations and inline fastest locking
5  functionality. Will contain #ifdefs for OS efficiency.
6  Have non-thread-safe implementation if not available.
7 Created : September 19, 2012
8 Notes :
9 
10 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
11 
12 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
13 you may not use the Oculus VR Rift SDK except in compliance with the License,
14 which is provided at the time of installation or download, or which
15 otherwise accompanies this software in either electronic or hard copy form.
16 
17 You may obtain a copy of the License at
18 
19 http://www.oculusvr.com/licenses/LICENSE-3.1
20 
21 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
22 distributed under the License is distributed on an "AS IS" BASIS,
23 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 See the License for the specific language governing permissions and
25 limitations under the License.
26 
27 ************************************************************************************/
28 
29 #include "OVR_Atomic.h"
30 #include "OVR_Allocator.h"
31 
32 #ifdef OVR_ENABLE_THREADS
33 
34 // Include Windows 8-Metro compatible Synchronization API
35 #if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
36 #include <synchapi.h>
37 #endif
38 
39 
40 namespace OVR {
41 
42 // ***** Windows Lock implementation
43 
44 #if defined(OVR_OS_WIN32)
45 
46 // ***** Standard Win32 Lock implementation
47 
48 // Constructors
49 Lock::Lock(unsigned spinCount)
50 {
51 #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
52  // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility
53  InitializeCriticalSectionEx(&cs, spinCount,
54  OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO));
55 #else
56  // Spin count init critical section function prototype for Window NT
57  typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount)
58  (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
59 
60 
61  // Try to load function dynamically so that we don't require NT
62  // On Windows NT we will use InitializeCriticalSectionAndSpinCount
63  static bool initTried = 0;
64  static Function_InitializeCriticalSectionAndSpinCount pInitFn = 0;
65 
66  if (!initTried)
67  {
68  HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll"));
69  pInitFn = (Function_InitializeCriticalSectionAndSpinCount)
70  ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount");
71  initTried = true;
72  }
73 
74  // Initialize the critical section
75  if (pInitFn)
76  pInitFn(&cs, spinCount);
77  else
78  ::InitializeCriticalSection(&cs);
79 #endif
80 
81 }
82 
83 
85 {
86  DeleteCriticalSection(&cs);
87 }
88 
89 
90 #endif
91 
92 
93 //-------------------------------------------------------------------------------------
94 // ***** SharedLock
95 
96 // This is a general purpose globally shared Lock implementation that should probably be
97 // moved to Kernel.
98 // May in theory busy spin-wait if we hit contention on first lock creation,
99 // but this shouldn't matter in practice since Lock* should be cached.
100 
101 
102 enum { LockInitMarker = 0xFFFFFFFF };
103 
105 {
106  int oldUseCount;
107 
108  do {
109  oldUseCount = UseCount;
110  if (oldUseCount == LockInitMarker)
111  continue;
112 
113  if (oldUseCount == 0)
114  {
115  // Initialize marker
117  {
118  Construct<Lock>(Buffer);
119  do { }
121  return toLock();
122  }
123  continue;
124  }
125 
126  } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
127 
128  return toLock();
129 }
130 
132 {
133  OVR_UNUSED(plock);
134  OVR_ASSERT(plock == toLock());
135 
136  int oldUseCount;
137 
138  do {
139  oldUseCount = UseCount;
140  OVR_ASSERT(oldUseCount != LockInitMarker);
141 
142  if (oldUseCount == 1)
143  {
144  // Initialize marker
146  {
147  Destruct<Lock>(toLock());
148 
149  do { }
151 
152  return;
153  }
154  continue;
155  }
156 
157  } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
158 }
159 
160 } // OVR
161 
162 #endif // OVR_ENABLE_THREADS
void ReleaseLock(Lock *plock)
Definition: OVR_Atomic.cpp:131
#define OVR_DEBUG_SELECT(d, nd)
#define NULL
#define OVR_UNUSED(a)
#define OVR_ASSERT(p)
Lock * GetLockAddRef()
Definition: OVR_Atomic.cpp:104
UInt64 Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)]
Definition: OVR_Atomic.h:884
volatile int UseCount
Definition: OVR_Atomic.h:883
Lock(unsigned dummy=0)
Definition: OVR_Atomic.h:836
Lock * toLock()
Definition: OVR_Atomic.h:880