diff options
Diffstat (limited to 'LibOVR/Src/Kernel')
57 files changed, 16045 insertions, 1886 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Alg.cpp b/LibOVR/Src/Kernel/OVR_Alg.cpp index 2e52bc3..c087777 100644 --- a/LibOVR/Src/Kernel/OVR_Alg.cpp +++ b/LibOVR/Src/Kernel/OVR_Alg.cpp @@ -5,16 +5,16 @@ Content : Static lookup tables for Alg functions Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -29,7 +29,7 @@ limitations under the License. namespace OVR { namespace Alg { //------------------------------------------------------------------------ -extern const UByte UpperBitTable[256] = +extern const uint8_t UpperBitTable[256] = { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -41,7 +41,7 @@ extern const UByte UpperBitTable[256] = 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; -extern const UByte LowerBitTable[256] = +extern const uint8_t LowerBitTable[256] = { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, diff --git a/LibOVR/Src/Kernel/OVR_Alg.h b/LibOVR/Src/Kernel/OVR_Alg.h index e03cea0..f7f461f 100644 --- a/LibOVR/Src/Kernel/OVR_Alg.h +++ b/LibOVR/Src/Kernel/OVR_Alg.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Alg.h Content : Simple general purpose algorithms: Sort, Binary Search, etc. Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -66,12 +66,12 @@ template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f) // absolutelly the same as regular gmin/gmax. template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b) { - OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t)); return (a < b) ? a : b; } template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b) { - OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t)); return (b < a) ? a : b; } @@ -99,7 +99,7 @@ template<class T> struct OperatorLess // The range is specified with start, end, where "end" is exclusive! // The comparison predicate must be specified. template<class Array, class Less> -void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) +void QuickSortSliced(Array& arr, size_t start, size_t end, Less less) { enum { @@ -108,15 +108,15 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) if(end - start < 2) return; - SPInt stack[80]; - SPInt* top = stack; - SPInt base = (SPInt)start; - SPInt limit = (SPInt)end; + intptr_t stack[80]; + intptr_t* top = stack; + intptr_t base = (intptr_t)start; + intptr_t limit = (intptr_t)end; for(;;) { - SPInt len = limit - base; - SPInt i, j, pivot; + intptr_t len = limit - base; + intptr_t i, j, pivot; if(len > Threshold) { @@ -201,7 +201,7 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> -void QuickSortSliced(Array& arr, UPInt start, UPInt end) +void QuickSortSliced(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); @@ -210,7 +210,7 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end) // Same as corresponding G_QuickSortSliced but with checking array limits to avoid // crash in the case of wrong comparator functor. template<class Array, class Less> -bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end, Less less) { enum { @@ -219,15 +219,15 @@ bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) if(end - start < 2) return true; - SPInt stack[80]; - SPInt* top = stack; - SPInt base = (SPInt)start; - SPInt limit = (SPInt)end; + intptr_t stack[80]; + intptr_t* top = stack; + intptr_t base = (intptr_t)start; + intptr_t limit = (intptr_t)end; for(;;) { - SPInt len = limit - base; - SPInt i, j, pivot; + intptr_t len = limit - base; + intptr_t i, j, pivot; if(len > Threshold) { @@ -316,7 +316,7 @@ bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) } template<class Array> -bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end) +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare); @@ -374,11 +374,11 @@ bool QuickSortSafe(Array& arr) // an array with all equal elements will remain "untouched", while // Quick Sort will considerably shuffle the elements in this case. template<class Array, class Less> -void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) +void InsertionSortSliced(Array& arr, size_t start, size_t end, Less less) { - UPInt j = start; - UPInt i = j + 1; - UPInt limit = end; + size_t j = start; + size_t i = j + 1; + size_t limit = end; for(; i < limit; j = i, i++) { @@ -401,7 +401,7 @@ void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> -void InsertionSortSliced(Array& arr, UPInt start, UPInt end) +void InsertionSortSliced(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); @@ -442,14 +442,14 @@ void InsertionSort(Array& arr) template<class Array> typename Array::ValueType& Median(Array& arr) { - UPInt count = arr.GetSize(); - UPInt mid = (count - 1) / 2; + size_t count = arr.GetSize(); + size_t mid = (count - 1) / 2; OVR_ASSERT(count > 0); - for (UPInt j = 0; j <= mid; j++) + for (size_t j = 0; j <= mid; j++) { - UPInt min = j; - for (UPInt k = j + 1; k < count; k++) + size_t min = j; + for (size_t k = j + 1; k < count; k++) if (arr[k] < arr[min]) min = k; Swap(arr[j], arr[min]); @@ -461,12 +461,12 @@ typename Array::ValueType& Median(Array& arr) // ***** LowerBoundSliced // template<class Array, class Value, class Less> -UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less) { - SPInt first = (SPInt)start; - SPInt len = (SPInt)(end - start); - SPInt half; - SPInt middle; + intptr_t first = (intptr_t)start; + intptr_t len = (intptr_t)(end - start); + intptr_t half; + intptr_t middle; while(len > 0) { @@ -482,7 +482,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va len = half; } } - return (UPInt)first; + return (size_t)first; } @@ -490,7 +490,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** LowerBoundSliced // template<class Array, class Value> -UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val) { return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } @@ -499,7 +499,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** LowerBoundSized // template<class Array, class Value> -UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) +size_t LowerBoundSized(const Array& arr, size_t size, const Value& val) { return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } @@ -508,7 +508,7 @@ UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) // ***** LowerBound // template<class Array, class Value, class Less> -UPInt LowerBound(const Array& arr, const Value& val, Less less) +size_t LowerBound(const Array& arr, const Value& val, Less less) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, less); } @@ -518,7 +518,7 @@ UPInt LowerBound(const Array& arr, const Value& val, Less less) // ***** LowerBound // template<class Array, class Value> -UPInt LowerBound(const Array& arr, const Value& val) +size_t LowerBound(const Array& arr, const Value& val) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } @@ -529,12 +529,12 @@ UPInt LowerBound(const Array& arr, const Value& val) // ***** UpperBoundSliced // template<class Array, class Value, class Less> -UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less) { - SPInt first = (SPInt)start; - SPInt len = (SPInt)(end - start); - SPInt half; - SPInt middle; + intptr_t first = (intptr_t)start; + intptr_t len = (intptr_t)(end - start); + intptr_t half; + intptr_t middle; while(len > 0) { @@ -550,7 +550,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va len = len - half - 1; } } - return (UPInt)first; + return (size_t)first; } @@ -558,7 +558,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** UpperBoundSliced // template<class Array, class Value> -UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val) { return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } @@ -568,7 +568,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** UpperBoundSized // template<class Array, class Value> -UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) +size_t UpperBoundSized(const Array& arr, size_t size, const Value& val) { return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } @@ -578,7 +578,7 @@ UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) // ***** UpperBound // template<class Array, class Value, class Less> -UPInt UpperBound(const Array& arr, const Value& val, Less less) +size_t UpperBound(const Array& arr, const Value& val, Less less) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, less); } @@ -588,7 +588,7 @@ UPInt UpperBound(const Array& arr, const Value& val, Less less) // ***** UpperBound // template<class Array, class Value> -UPInt UpperBound(const Array& arr, const Value& val) +size_t UpperBound(const Array& arr, const Value& val) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } @@ -599,8 +599,8 @@ UPInt UpperBound(const Array& arr, const Value& val) // template<class Array> void ReverseArray(Array& arr) { - SPInt from = 0; - SPInt to = arr.GetSize() - 1; + intptr_t from = 0; + intptr_t to = arr.GetSize() - 1; while(from < to) { Swap(arr[from], arr[to]); @@ -615,7 +615,7 @@ template<class Array> void ReverseArray(Array& arr) template<class CDst, class CSrc> void AppendArray(CDst& dst, const CSrc& src) { - UPInt i; + size_t i; for(i = 0; i < src.GetSize(); i++) dst.PushBack(src[i]); } @@ -630,13 +630,14 @@ template<class T> class ArrayAdaptor public: typedef T ValueType; ArrayAdaptor() : Data(0), Size(0) {} - ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {} - UPInt GetSize() const { return Size; } - const T& operator [] (UPInt i) const { return Data[i]; } - T& operator [] (UPInt i) { return Data[i]; } + ArrayAdaptor(T* ptr, size_t size) : Data(ptr), Size(size) {} + size_t GetSize() const { return Size; } + int GetSizeI() const { return (int)GetSize(); } + const T& operator [] (size_t i) const { return Data[i]; } + T& operator [] (size_t i) { return Data[i]; } private: T* Data; - UPInt Size; + size_t Size; }; @@ -650,24 +651,25 @@ template<class T> class ConstArrayAdaptor public: typedef T ValueType; ConstArrayAdaptor() : Data(0), Size(0) {} - ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {} - UPInt GetSize() const { return Size; } - const T& operator [] (UPInt i) const { return Data[i]; } + ConstArrayAdaptor(const T* ptr, size_t size) : Data(ptr), Size(size) {} + size_t GetSize() const { return Size; } + int GetSizeI() const { return (int)GetSize(); } + const T& operator [] (size_t i) const { return Data[i]; } private: const T* Data; - UPInt Size; + size_t Size; }; //----------------------------------------------------------------------------------- -extern const UByte UpperBitTable[256]; -extern const UByte LowerBitTable[256]; +extern const uint8_t UpperBitTable[256]; +extern const uint8_t LowerBitTable[256]; //----------------------------------------------------------------------------------- -inline UByte UpperBit(UPInt val) +inline uint8_t UpperBit(size_t val) { #ifndef OVR_64BIT_POINTERS @@ -712,7 +714,7 @@ inline UByte UpperBit(UPInt val) } //----------------------------------------------------------------------------------- -inline UByte LowerBit(UPInt val) +inline uint8_t LowerBit(size_t val) { #ifndef OVR_64BIT_POINTERS @@ -765,18 +767,18 @@ class MemUtil public: // Memory compare - static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } - static int Cmp16(const void* p1, const void* p2, UPInt int16Count); - static int Cmp32(const void* p1, const void* p2, UPInt int32Count); - static int Cmp64(const void* p1, const void* p2, UPInt int64Count); + static int Cmp (const void* p1, const void* p2, size_t byteCount) { return memcmp(p1, p2, byteCount); } + static int Cmp16(const void* p1, const void* p2, size_t int16Count); + static int Cmp32(const void* p1, const void* p2, size_t int32Count); + static int Cmp64(const void* p1, const void* p2, size_t int64Count); }; // ** Inline Implementation -inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) +inline int MemUtil::Cmp16(const void* p1, const void* p2, size_t int16Count) { - SInt16* pa = (SInt16*)p1; - SInt16* pb = (SInt16*)p2; + int16_t* pa = (int16_t*)p1; + int16_t* pb = (int16_t*)p2; unsigned ic = 0; if (int16Count == 0) return 0; @@ -785,10 +787,10 @@ inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } -inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) +inline int MemUtil::Cmp32(const void* p1, const void* p2, size_t int32Count) { - SInt32* pa = (SInt32*)p1; - SInt32* pb = (SInt32*)p2; + int32_t* pa = (int32_t*)p1; + int32_t* pb = (int32_t*)p2; unsigned ic = 0; if (int32Count == 0) return 0; @@ -797,10 +799,10 @@ inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } -inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) +inline int MemUtil::Cmp64(const void* p1, const void* p2, size_t int64Count) { - SInt64* pa = (SInt64*)p1; - SInt64* pb = (SInt64*)p2; + int64_t* pa = (int64_t*)p1; + int64_t* pb = (int64_t*)p2; unsigned ic = 0; if (int64Count == 0) return 0; @@ -822,8 +824,8 @@ namespace ByteUtil { // Swap the byte order of a byte array inline void SwapOrder(void* pv, int size) { - UByte* pb = (UByte*)pv; - UByte temp; + uint8_t* pb = (uint8_t*)pv; + uint8_t temp; for (int i = 0; i < size>>1; i++) { temp = pb[size-1-i]; @@ -833,29 +835,29 @@ namespace ByteUtil { } // Swap the byte order of primitive types - inline UByte SwapOrder(UByte v) { return v; } - inline SByte SwapOrder(SByte v) { return v; } - inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } - inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } - inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } - inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } - inline UInt64 SwapOrder(UInt64 v) + inline uint8_t SwapOrder(uint8_t v) { return v; } + inline int8_t SwapOrder(int8_t v) { return v; } + inline uint16_t SwapOrder(uint16_t v) { return uint16_t(v>>8)|uint16_t(v<<8); } + inline int16_t SwapOrder(int16_t v) { return int16_t((uint16_t(v)>>8)|(v<<8)); } + inline uint32_t SwapOrder(uint32_t v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } + inline int32_t SwapOrder(int32_t p) { return (int32_t)SwapOrder(uint32_t(p)); } + inline uint64_t SwapOrder(uint64_t v) { return (v>>56) | - ((v&UInt64(0x00FF000000000000ULL))>>40) | - ((v&UInt64(0x0000FF0000000000ULL))>>24) | - ((v&UInt64(0x000000FF00000000ULL))>>8) | - ((v&UInt64(0x00000000FF000000ULL))<<8) | - ((v&UInt64(0x0000000000FF0000ULL))<<24) | - ((v&UInt64(0x000000000000FF00ULL))<<40) | + ((v&uint64_t(0x00FF000000000000ULL))>>40) | + ((v&uint64_t(0x0000FF0000000000ULL))>>24) | + ((v&uint64_t(0x000000FF00000000ULL))>>8) | + ((v&uint64_t(0x00000000FF000000ULL))<<8) | + ((v&uint64_t(0x0000000000FF0000ULL))<<24) | + ((v&uint64_t(0x000000000000FF00ULL))<<40) | (v<<56); } - inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } + inline int64_t SwapOrder(int64_t v) { return (int64_t)SwapOrder(uint64_t(v)); } inline float SwapOrder(float p) { union { float p; - UInt32 v; + uint32_t v; } u; u.p = p; u.v = SwapOrder(u.v); @@ -866,7 +868,7 @@ namespace ByteUtil { { union { double p; - UInt64 v; + uint64_t v; } u; u.p = p; u.v = SwapOrder(u.v); @@ -877,99 +879,99 @@ namespace ByteUtil { #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN) // Little Endian to System (LE) - inline UByte LEToSystem(UByte v) { return v; } - inline SByte LEToSystem(SByte v) { return v; } - inline UInt16 LEToSystem(UInt16 v) { return v; } - inline SInt16 LEToSystem(SInt16 v) { return v; } - inline UInt32 LEToSystem(UInt32 v) { return v; } - inline SInt32 LEToSystem(SInt32 v) { return v; } - inline UInt64 LEToSystem(UInt64 v) { return v; } - inline SInt64 LEToSystem(SInt64 v) { return v; } + inline uint8_t LEToSystem(uint8_t v) { return v; } + inline int8_t LEToSystem(int8_t v) { return v; } + inline uint16_t LEToSystem(uint16_t v) { return v; } + inline int16_t LEToSystem(int16_t v) { return v; } + inline uint32_t LEToSystem(uint32_t v) { return v; } + inline int32_t LEToSystem(int32_t v) { return v; } + inline uint64_t LEToSystem(uint64_t v) { return v; } + inline int64_t LEToSystem(int64_t v) { return v; } inline float LEToSystem(float v) { return v; } inline double LEToSystem(double v) { return v; } // Big Endian to System (LE) - inline UByte BEToSystem(UByte v) { return SwapOrder(v); } - inline SByte BEToSystem(SByte v) { return SwapOrder(v); } - inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } - inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } - inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } - inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } - inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } - inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } + inline uint8_t BEToSystem(uint8_t v) { return SwapOrder(v); } + inline int8_t BEToSystem(int8_t v) { return SwapOrder(v); } + inline uint16_t BEToSystem(uint16_t v) { return SwapOrder(v); } + inline int16_t BEToSystem(int16_t v) { return SwapOrder(v); } + inline uint32_t BEToSystem(uint32_t v) { return SwapOrder(v); } + inline int32_t BEToSystem(int32_t v) { return SwapOrder(v); } + inline uint64_t BEToSystem(uint64_t v) { return SwapOrder(v); } + inline int64_t BEToSystem(int64_t v) { return SwapOrder(v); } inline float BEToSystem(float v) { return SwapOrder(v); } inline double BEToSystem(double v) { return SwapOrder(v); } // System (LE) to Little Endian - inline UByte SystemToLE(UByte v) { return v; } - inline SByte SystemToLE(SByte v) { return v; } - inline UInt16 SystemToLE(UInt16 v) { return v; } - inline SInt16 SystemToLE(SInt16 v) { return v; } - inline UInt32 SystemToLE(UInt32 v) { return v; } - inline SInt32 SystemToLE(SInt32 v) { return v; } - inline UInt64 SystemToLE(UInt64 v) { return v; } - inline SInt64 SystemToLE(SInt64 v) { return v; } + inline uint8_t SystemToLE(uint8_t v) { return v; } + inline int8_t SystemToLE(int8_t v) { return v; } + inline uint16_t SystemToLE(uint16_t v) { return v; } + inline int16_t SystemToLE(int16_t v) { return v; } + inline uint32_t SystemToLE(uint32_t v) { return v; } + inline int32_t SystemToLE(int32_t v) { return v; } + inline uint64_t SystemToLE(uint64_t v) { return v; } + inline int64_t SystemToLE(int64_t v) { return v; } inline float SystemToLE(float v) { return v; } inline double SystemToLE(double v) { return v; } // System (LE) to Big Endian - inline UByte SystemToBE(UByte v) { return SwapOrder(v); } - inline SByte SystemToBE(SByte v) { return SwapOrder(v); } - inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } - inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } - inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } - inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } - inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } - inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } + inline uint8_t SystemToBE(uint8_t v) { return SwapOrder(v); } + inline int8_t SystemToBE(int8_t v) { return SwapOrder(v); } + inline uint16_t SystemToBE(uint16_t v) { return SwapOrder(v); } + inline int16_t SystemToBE(int16_t v) { return SwapOrder(v); } + inline uint32_t SystemToBE(uint32_t v) { return SwapOrder(v); } + inline int32_t SystemToBE(int32_t v) { return SwapOrder(v); } + inline uint64_t SystemToBE(uint64_t v) { return SwapOrder(v); } + inline int64_t SystemToBE(int64_t v) { return SwapOrder(v); } inline float SystemToBE(float v) { return SwapOrder(v); } inline double SystemToBE(double v) { return SwapOrder(v); } #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN) // Little Endian to System (BE) - inline UByte LEToSystem(UByte v) { return SwapOrder(v); } - inline SByte LEToSystem(SByte v) { return SwapOrder(v); } - inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } - inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } - inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } - inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } - inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } - inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } + inline uint8_t LEToSystem(uint8_t v) { return SwapOrder(v); } + inline int8_t LEToSystem(int8_t v) { return SwapOrder(v); } + inline uint16_t LEToSystem(uint16_t v) { return SwapOrder(v); } + inline int16_t LEToSystem(int16_t v) { return SwapOrder(v); } + inline uint32_t LEToSystem(uint32_t v) { return SwapOrder(v); } + inline int32_t LEToSystem(int32_t v) { return SwapOrder(v); } + inline uint64_t LEToSystem(uint64_t v) { return SwapOrder(v); } + inline int64_t LEToSystem(int64_t v) { return SwapOrder(v); } inline float LEToSystem(float v) { return SwapOrder(v); } inline double LEToSystem(double v) { return SwapOrder(v); } // Big Endian to System (BE) - inline UByte BEToSystem(UByte v) { return v; } - inline SByte BEToSystem(SByte v) { return v; } - inline UInt16 BEToSystem(UInt16 v) { return v; } - inline SInt16 BEToSystem(SInt16 v) { return v; } - inline UInt32 BEToSystem(UInt32 v) { return v; } - inline SInt32 BEToSystem(SInt32 v) { return v; } - inline UInt64 BEToSystem(UInt64 v) { return v; } - inline SInt64 BEToSystem(SInt64 v) { return v; } + inline uint8_t BEToSystem(uint8_t v) { return v; } + inline int8_t BEToSystem(int8_t v) { return v; } + inline uint16_t BEToSystem(uint16_t v) { return v; } + inline int16_t BEToSystem(int16_t v) { return v; } + inline uint32_t BEToSystem(uint32_t v) { return v; } + inline int32_t BEToSystem(int32_t v) { return v; } + inline uint64_t BEToSystem(uint64_t v) { return v; } + inline int64_t BEToSystem(int64_t v) { return v; } inline float BEToSystem(float v) { return v; } inline double BEToSystem(double v) { return v; } // System (BE) to Little Endian - inline UByte SystemToLE(UByte v) { return SwapOrder(v); } - inline SByte SystemToLE(SByte v) { return SwapOrder(v); } - inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } - inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } - inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } - inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } - inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } - inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } + inline uint8_t SystemToLE(uint8_t v) { return SwapOrder(v); } + inline int8_t SystemToLE(int8_t v) { return SwapOrder(v); } + inline uint16_t SystemToLE(uint16_t v) { return SwapOrder(v); } + inline int16_t SystemToLE(int16_t v) { return SwapOrder(v); } + inline uint32_t SystemToLE(uint32_t v) { return SwapOrder(v); } + inline int32_t SystemToLE(int32_t v) { return SwapOrder(v); } + inline uint64_t SystemToLE(uint64_t v) { return SwapOrder(v); } + inline int64_t SystemToLE(int64_t v) { return SwapOrder(v); } inline float SystemToLE(float v) { return SwapOrder(v); } inline double SystemToLE(double v) { return SwapOrder(v); } // System (BE) to Big Endian - inline UByte SystemToBE(UByte v) { return v; } - inline SByte SystemToBE(SByte v) { return v; } - inline UInt16 SystemToBE(UInt16 v) { return v; } - inline SInt16 SystemToBE(SInt16 v) { return v; } - inline UInt32 SystemToBE(UInt32 v) { return v; } - inline SInt32 SystemToBE(SInt32 v) { return v; } - inline UInt64 SystemToBE(UInt64 v) { return v; } - inline SInt64 SystemToBE(SInt64 v) { return v; } + inline uint8_t SystemToBE(uint8_t v) { return v; } + inline int8_t SystemToBE(int8_t v) { return v; } + inline uint16_t SystemToBE(uint16_t v) { return v; } + inline int16_t SystemToBE(int16_t v) { return v; } + inline uint32_t SystemToBE(uint32_t v) { return v; } + inline int32_t SystemToBE(int32_t v) { return v; } + inline uint64_t SystemToBE(uint64_t v) { return v; } + inline int64_t SystemToBE(int64_t v) { return v; } inline float SystemToBE(float v) { return v; } inline double SystemToBE(double v) { return v; } @@ -983,30 +985,30 @@ namespace ByteUtil { // Used primarily for hardware interfacing such as sensor reports, firmware, etc. // Reported data is all little-endian. -inline UInt16 DecodeUInt16(const UByte* buffer) +inline uint16_t DecodeUInt16(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const UInt16*)buffer ); + return ByteUtil::LEToSystem ( *(const uint16_t*)buffer ); } -inline SInt16 DecodeSInt16(const UByte* buffer) +inline int16_t DecodeSInt16(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const SInt16*)buffer ); + return ByteUtil::LEToSystem ( *(const int16_t*)buffer ); } -inline UInt32 DecodeUInt32(const UByte* buffer) +inline uint32_t DecodeUInt32(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const UInt32*)buffer ); + return ByteUtil::LEToSystem ( *(const uint32_t*)buffer ); } -inline SInt32 DecodeSInt32(const UByte* buffer) +inline int32_t DecodeSInt32(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const SInt32*)buffer ); + return ByteUtil::LEToSystem ( *(const int32_t*)buffer ); } -inline float DecodeFloat(const UByte* buffer) +inline float DecodeFloat(const uint8_t* buffer) { union { - UInt32 U; + uint32_t U; float F; }; @@ -1014,30 +1016,30 @@ inline float DecodeFloat(const UByte* buffer) return F; } -inline void EncodeUInt16(UByte* buffer, UInt16 val) +inline void EncodeUInt16(uint8_t* buffer, uint16_t val) { - *(UInt16*)buffer = ByteUtil::SystemToLE ( val ); + *(uint16_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeSInt16(UByte* buffer, SInt16 val) +inline void EncodeSInt16(uint8_t* buffer, int16_t val) { - *(SInt16*)buffer = ByteUtil::SystemToLE ( val ); + *(int16_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeUInt32(UByte* buffer, UInt32 val) +inline void EncodeUInt32(uint8_t* buffer, uint32_t val) { - *(UInt32*)buffer = ByteUtil::SystemToLE ( val ); + *(uint32_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeSInt32(UByte* buffer, SInt32 val) +inline void EncodeSInt32(uint8_t* buffer, int32_t val) { - *(SInt32*)buffer = ByteUtil::SystemToLE ( val ); + *(int32_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeFloat(UByte* buffer, float val) +inline void EncodeFloat(uint8_t* buffer, float val) { union { - UInt32 U; + uint32_t U; float F; }; @@ -1046,12 +1048,12 @@ inline void EncodeFloat(UByte* buffer, float val) } // Converts an 8-bit binary-coded decimal -inline SByte DecodeBCD(UByte byte) +inline int8_t DecodeBCD(uint8_t byte) { - UByte digit1 = (byte >> 4) & 0x0f; - UByte digit2 = byte & 0x0f; + uint8_t digit1 = (byte >> 4) & 0x0f; + uint8_t digit2 = byte & 0x0f; int decimal = digit1 * 10 + digit2; // maximum value = 99 - return (SByte)decimal; + return (int8_t)decimal; } diff --git a/LibOVR/Src/Kernel/OVR_Allocator.cpp b/LibOVR/Src/Kernel/OVR_Allocator.cpp index 0f82561..f963d08 100644 --- a/LibOVR/Src/Kernel/OVR_Allocator.cpp +++ b/LibOVR/Src/Kernel/OVR_Allocator.cpp @@ -5,16 +5,16 @@ Content : Installable memory allocator implementation Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -31,6 +31,14 @@ limitations under the License. #include <malloc.h> #endif +#if defined(OVR_OS_MS) + #include <Windows.h> +#elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + #include <unistd.h> + #include <sys/mman.h> +#endif + + namespace OVR { //----------------------------------------------------------------------------------- @@ -39,25 +47,25 @@ namespace OVR { Allocator* Allocator::pInstance = 0; // Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding. -void* Allocator::AllocAligned(UPInt size, UPInt align) +void* Allocator::AllocAligned(size_t size, size_t align) { OVR_ASSERT((align & (align-1)) == 0); - align = (align > sizeof(UPInt)) ? align : sizeof(UPInt); - UPInt p = (UPInt)Alloc(size+align); - UPInt aligned = 0; + align = (align > sizeof(size_t)) ? align : sizeof(size_t); + size_t p = (size_t)Alloc(size+align); + size_t aligned = 0; if (p) { - aligned = (UPInt(p) + align-1) & ~(align-1); + aligned = (size_t(p) + align-1) & ~(align-1); if (aligned == p) aligned += align; - *(((UPInt*)aligned)-1) = aligned-p; + *(((size_t*)aligned)-1) = aligned-p; } return (void*)aligned; } void Allocator::FreeAligned(void* p) { - UPInt src = UPInt(p) - *(((UPInt*)p)-1); + size_t src = size_t(p) - *(((size_t*)p)-1); Free((void*)src); } @@ -68,21 +76,21 @@ void Allocator::FreeAligned(void* p) // This allocator is created and used if no other allocator is installed. // Default allocator delegates to system malloc. -void* DefaultAllocator::Alloc(UPInt size) +void* DefaultAllocator::Alloc(size_t size) { return malloc(size); } -void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line) +void* DefaultAllocator::AllocDebug(size_t size, const char* file, unsigned line) { + OVR_UNUSED2(file, line); // should be here for debugopt config #if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC) return _malloc_dbg(size, _NORMAL_BLOCK, file, line); #else - OVR_UNUSED2(file, line); return malloc(size); #endif } -void* DefaultAllocator::Realloc(void* p, UPInt newSize) +void* DefaultAllocator::Realloc(void* p, size_t newSize) { return realloc(p, newSize); } @@ -92,4 +100,42 @@ void DefaultAllocator::Free(void *p) } + + +void* MMapAlloc(size_t size) +{ + #if defined(OVR_OS_MS) + return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // size is rounded up to a page. // Returned memory is 0-filled. + + #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + #if !defined(MAP_FAILED) + #define MAP_FAILED ((void*)-1) + #endif + + void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // Returned memory is 0-filled. + if(result == MAP_FAILED) // mmap returns MAP_FAILED (-1) upon failure. + result = NULL; + return result; + #endif +} + + + + +void MMapFree(void* memory, size_t size) +{ + #if defined(OVR_OS_MS) + OVR_UNUSED(size); + VirtualFree(memory, 0, MEM_RELEASE); + + #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + size_t pageSize = getpagesize(); + size = (((size + (pageSize - 1)) / pageSize) * pageSize); + munmap(memory, size); // Must supply the size to munmap. + #endif +} + + + + } // OVR diff --git a/LibOVR/Src/Kernel/OVR_Allocator.h b/LibOVR/Src/Kernel/OVR_Allocator.h index b862557..dcf097d 100644 --- a/LibOVR/Src/Kernel/OVR_Allocator.h +++ b/LibOVR/Src/Kernel/OVR_Allocator.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Allocator.h Content : Installable memory allocator Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -56,7 +56,7 @@ limitations under the License. # include <new> # else // Useful on MSVC - OVR_FORCE_INLINE void* operator new (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } + OVR_FORCE_INLINE void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } OVR_FORCE_INLINE void operator delete (void *, void *) { } # endif @@ -71,9 +71,9 @@ limitations under the License. // class member operator new. #define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \ - void* operator new(UPInt sz) \ + void* operator new(size_t sz) \ { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \ - void* operator new(UPInt sz, const char* file, int line) \ + void* operator new(size_t sz, const char* file, int line) \ { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \ void operator delete(void *p) \ { check_delete(class_name, p); OVR_FREE(p); } \ @@ -81,7 +81,7 @@ limitations under the License. { check_delete(class_name, p); OVR_FREE(p); } #define OVR_MEMORY_DEFINE_PLACEMENT_NEW \ - void* operator new (UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } \ + void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } \ void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); } @@ -127,20 +127,20 @@ OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2) } template <class T> -OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count) +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) { Construct<T>(pdata); } } template <class T> -OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source) +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count, const T& source) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) { Construct<T>(pdata, source); } @@ -154,9 +154,9 @@ OVR_FORCE_INLINE void Destruct(T *pobj) } template <class T> -OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count) +OVR_FORCE_INLINE void DestructArray(T *pobj, size_t count) { - for (UPInt i=0; i<count; ++i, ++pobj) + for (size_t i=0; i<count; ++i, ++pobj) pobj->~T(); } @@ -178,15 +178,16 @@ class Allocator { friend class System; public: + virtual ~Allocator(){} // *** Standard Alignment Alloc/Free // Allocate memory of specified size with default alignment. // Alloc of size==0 will allocate a tiny block & return a valid pointer; // this makes it suitable for new operator. - virtual void* Alloc(UPInt size) = 0; + virtual void* Alloc(size_t size) = 0; // Same as Alloc, but provides an option of passing debug data. - virtual void* AllocDebug(UPInt size, const char* file, unsigned line) + virtual void* AllocDebug(size_t size, const char* file, unsigned line) { OVR_UNUSED2(file, line); return Alloc(size); } // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to @@ -195,7 +196,7 @@ public: // Realloc to decrease size will never fail. // Realloc of pointer == 0 is equivalent to Alloc // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free(). - virtual void* Realloc(void* p, UPInt newSize) = 0; + virtual void* Realloc(void* p, size_t newSize) = 0; // Frees memory allocated by Alloc/Realloc. // Free of null pointer is valid and will do nothing. @@ -207,7 +208,7 @@ public: // Allocate memory of specified alignment. // Memory allocated with AllocAligned MUST be freed with FreeAligned. // Default implementation will delegate to Alloc/Free after doing rounding. - virtual void* AllocAligned(UPInt size, UPInt align); + virtual void* AllocAligned(size_t size, size_t align); // Frees memory allocated with AllocAligned. virtual void FreeAligned(void* p); @@ -250,7 +251,7 @@ class Allocator_SingletonSupport : public Allocator { struct AllocContainer { - UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)]; + size_t Data[(sizeof(D) + sizeof(size_t)-1) / sizeof(size_t)]; bool Initialized; AllocContainer() : Initialized(0) { } }; @@ -295,9 +296,9 @@ protected: class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator> { public: - virtual void* Alloc(UPInt size); - virtual void* AllocDebug(UPInt size, const char* file, unsigned line); - virtual void* Realloc(void* p, UPInt newSize); + virtual void* Alloc(size_t size); + virtual void* AllocDebug(size_t size, const char* file, unsigned line); + virtual void* Realloc(void* p, size_t newSize); virtual void Free(void *p); }; @@ -335,6 +336,18 @@ public: }; +//------------------------------------------------------------------------ +// ***** Mapped memory allocation +// +// Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix. +// These are useful for when you need system-supplied memory pages. +// These are also useful for when you need to allocate memory in a way +// that doesn't affect the application heap. + +void* MMapAlloc(size_t size); +void MMapFree(void* memory, size_t size); + + } // OVR diff --git a/LibOVR/Src/Kernel/OVR_Array.h b/LibOVR/Src/Kernel/OVR_Array.h index 7a715ba..7855a5b 100644 --- a/LibOVR/Src/Kernel/OVR_Array.h +++ b/LibOVR/Src/Kernel/OVR_Array.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Array.h Content : Template implementation for Array Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -44,14 +44,14 @@ struct ArrayDefaultPolicy ArrayDefaultPolicy() : Capacity(0) {} ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {} - UPInt GetMinCapacity() const { return 0; } - UPInt GetGranularity() const { return 4; } + size_t GetMinCapacity() const { return 0; } + size_t GetGranularity() const { return 4; } bool NeverShrinking() const { return 0; } - UPInt GetCapacity() const { return Capacity; } - void SetCapacity(UPInt capacity) { Capacity = capacity; } + size_t GetCapacity() const { return Capacity; } + void SetCapacity(size_t capacity) { Capacity = capacity; } private: - UPInt Capacity; + size_t Capacity; }; @@ -68,14 +68,14 @@ struct ArrayConstPolicy ArrayConstPolicy() : Capacity(0) {} ArrayConstPolicy(const SelfType&) : Capacity(0) {} - UPInt GetMinCapacity() const { return MinCapacity; } - UPInt GetGranularity() const { return Granularity; } + size_t GetMinCapacity() const { return MinCapacity; } + size_t GetGranularity() const { return Granularity; } bool NeverShrinking() const { return NeverShrink; } - UPInt GetCapacity() const { return Capacity; } - void SetCapacity(UPInt capacity) { Capacity = capacity; } + size_t GetCapacity() const { return Capacity; } + void SetCapacity(size_t capacity) { Capacity = capacity; } private: - UPInt Capacity; + size_t Capacity; }; //----------------------------------------------------------------------------------- @@ -103,7 +103,7 @@ struct ArrayDataBase Allocator::Free(Data); } - UPInt GetCapacity() const + size_t GetCapacity() const { return Policy.GetCapacity(); } @@ -117,7 +117,7 @@ struct ArrayDataBase Policy.SetCapacity(0); } - void Reserve(UPInt newCapacity) + void Reserve(size_t newCapacity) { if (Policy.NeverShrinking() && newCapacity < GetCapacity()) return; @@ -137,7 +137,7 @@ struct ArrayDataBase } else { - UPInt gran = Policy.GetGranularity(); + size_t gran = Policy.GetGranularity(); newCapacity = (newCapacity + gran - 1) / gran * gran; if (Data) { @@ -148,7 +148,7 @@ struct ArrayDataBase else { T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity); - UPInt i, s; + size_t i, s; s = (Size < newCapacity) ? Size : newCapacity; for (i = 0; i < s; ++i) { @@ -176,9 +176,9 @@ struct ArrayDataBase // This version of Resize DOES NOT construct the elements. // It's done to optimize PushBack, which uses a copy constructor // instead of the default constructor and assignment - void ResizeNoConstruct(UPInt newSize) + void ResizeNoConstruct(size_t newSize) { - UPInt oldSize = Size; + size_t oldSize = Size; if (newSize < oldSize) { @@ -199,7 +199,7 @@ struct ArrayDataBase } ValueType* Data; - UPInt Size; + size_t Size; SizePolicy Policy; }; @@ -222,16 +222,16 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> ArrayData() : BaseType() { } - ArrayData(UPInt size) + ArrayData(size_t size) : BaseType() { Resize(size); } ArrayData(const SelfType& a) : BaseType(a.Policy) { Append(a.Data, a.Size); } - void Resize(UPInt newSize) + void Resize(size_t newSize) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(newSize); if(newSize > oldSize) Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize); @@ -240,6 +240,7 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> void PushBack(const ValueType& val) { BaseType::ResizeNoConstruct(this->Size + 1); + OVR_ASSERT(this->Data != NULL); Allocator::Construct(this->Data + this->Size - 1, val); } @@ -251,11 +252,11 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { if (count) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(this->Size + count); Allocator::ConstructArray(this->Data + oldSize, count, other); } @@ -281,16 +282,16 @@ struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> ArrayDataCC(const ValueType& defval) : BaseType(), DefaultValue(defval) { } - ArrayDataCC(const ValueType& defval, UPInt size) + ArrayDataCC(const ValueType& defval, size_t size) : BaseType(), DefaultValue(defval) { Resize(size); } ArrayDataCC(const SelfType& a) : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); } - void Resize(UPInt newSize) + void Resize(size_t newSize) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(newSize); if(newSize > oldSize) Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue); @@ -310,11 +311,11 @@ struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { if (count) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(this->Size + count); Allocator::ConstructArray(this->Data + oldSize, count, other); } @@ -359,64 +360,65 @@ public: ArrayBase() : Data() {} - ArrayBase(UPInt size) + ArrayBase(size_t size) : Data(size) {} ArrayBase(const SelfType& a) : Data(a.Data) {} ArrayBase(const ValueType& defval) : Data(defval) {} - ArrayBase(const ValueType& defval, UPInt size) + ArrayBase(const ValueType& defval, size_t size) : Data(defval, size) {} SizePolicyType* GetSizePolicy() const { return Data.Policy; } void SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; } bool NeverShrinking()const { return Data.Policy.NeverShrinking(); } - UPInt GetSize() const { return Data.Size; } - bool IsEmpty() const { return Data.Size == 0; } - UPInt GetCapacity() const { return Data.GetCapacity(); } - UPInt GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } + size_t GetSize() const { return Data.Size; } + int GetSizeI() const { return (int)Data.Size; } + bool IsEmpty() const { return Data.Size == 0; } + size_t GetCapacity() const { return Data.GetCapacity(); } + size_t GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } void ClearAndRelease() { Data.ClearAndRelease(); } void Clear() { Data.Resize(0); } - void Resize(UPInt newSize) { Data.Resize(newSize); } + void Resize(size_t newSize) { Data.Resize(newSize); } // Reserve can only increase the capacity - void Reserve(UPInt newCapacity) + void Reserve(size_t newCapacity) { if (newCapacity > Data.GetCapacity()) Data.Reserve(newCapacity); } // Basic access. - ValueType& At(UPInt index) + ValueType& At(size_t index) { - OVR_ASSERT(index < Data.Size); - return Data.Data[index]; + OVR_ASSERT((Data.Data) && (index < Data.Size)); // Asserting that Data.Data is valid helps static analysis tools. + return Data.Data[index]; } - const ValueType& At(UPInt index) const + const ValueType& At(size_t index) const { - OVR_ASSERT(index < Data.Size); - return Data.Data[index]; + OVR_ASSERT((Data.Data) && (index < Data.Size)); + return Data.Data[index]; } - ValueType ValueAt(UPInt index) const + ValueType ValueAt(size_t index) const { - OVR_ASSERT(index < Data.Size); - return Data.Data[index]; + OVR_ASSERT((Data.Data) && (index < Data.Size)); + return Data.Data[index]; } // Basic access. - ValueType& operator [] (UPInt index) + ValueType& operator [] (size_t index) { - OVR_ASSERT(index < Data.Size); + OVR_ASSERT((Data.Data) && (index < Data.Size)); return Data.Data[index]; } - const ValueType& operator [] (UPInt index) const + const ValueType& operator [] (size_t index) const { - OVR_ASSERT(index < Data.Size); - return Data.Data[index]; + OVR_ASSERT((Data.Data) && (index < Data.Size)); + return Data.Data[index]; } // Raw pointer to the data. Use with caution! @@ -440,7 +442,7 @@ public: } // Remove the last element. - void PopBack(UPInt count = 1) + void PopBack(size_t count = 1) { OVR_ASSERT(Data.Size >= count); Data.Resize(Data.Size - count); @@ -454,6 +456,7 @@ public: ValueType Pop() { + OVR_ASSERT((Data.Data) && (Data.Size > 0)); ValueType t = Back(); PopBack(); return t; @@ -472,14 +475,15 @@ public: const SelfType& operator = (const SelfType& a) { Resize(a.GetSize()); - for (UPInt i = 0; i < Data.Size; i++) { + OVR_ASSERT((Data.Data != NULL) || (Data.Size == 0)); + for (size_t i = 0; i < Data.Size; i++) { *(Data.Data + i) = a[i]; } return *this; } // Removing multiple elements from the array. - void RemoveMultipleAt(UPInt index, UPInt num) + void RemoveMultipleAt(size_t index, size_t num) { OVR_ASSERT(index + num <= Data.Size); if (Data.Size == num) @@ -502,9 +506,9 @@ public: // If order of elements in the array is not important then use // RemoveAtUnordered, that could be much faster than the regular // RemoveAt. - void RemoveAt(UPInt index) + void RemoveAt(size_t index) { - OVR_ASSERT(index < Data.Size); + OVR_ASSERT((Data.Data) && (index < Data.Size)); if (Data.Size == 1) { Clear(); @@ -523,9 +527,9 @@ public: // Removes an element from the array without respecting of original order of // elements for better performance. Do not use on array where order of elements // is important, otherwise use it instead of regular RemoveAt(). - void RemoveAtUnordered(UPInt index) + void RemoveAtUnordered(size_t index) { - OVR_ASSERT(index < Data.Size); + OVR_ASSERT((Data.Data) && (index < Data.Size)); if (Data.Size == 1) { Clear(); @@ -535,7 +539,7 @@ public: // copy the last element into the 'index' position // and decrement the size (instead of moving all elements // in [index + 1 .. size - 1] range). - const UPInt lastElemIndex = Data.Size - 1; + const size_t lastElemIndex = Data.Size - 1; if (index < lastElemIndex) { AllocatorType::Destruct(Data.Data + index); @@ -547,7 +551,7 @@ public: } // Insert the given object at the given index shifting all the elements up. - void InsertAt(UPInt index, const ValueType& val = ValueType()) + void InsertAt(size_t index, const ValueType& val = ValueType()) { OVR_ASSERT(index <= Data.Size); @@ -563,7 +567,7 @@ public: } // Insert the given object at the given index shifting all the elements up. - void InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType()) + void InsertMultipleAt(size_t index, size_t num, const ValueType& val = ValueType()) { OVR_ASSERT(index <= Data.Size); @@ -575,7 +579,7 @@ public: Data.Data + index, Data.Size - num - index); } - for (UPInt i = 0; i < num; ++i) + for (size_t i = 0; i < num; ++i) AllocatorType::Construct(Data.Data + index + i, val); } @@ -586,7 +590,7 @@ public: } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { Data.Append(other, count); } @@ -594,11 +598,11 @@ public: class Iterator { SelfType* pArray; - SPInt CurIndex; + intptr_t CurIndex; public: Iterator() : pArray(0), CurIndex(-1) {} - Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} + Iterator(SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {} bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } @@ -607,7 +611,7 @@ public: { if (pArray) { - if (CurIndex < (SPInt)pArray->GetSize()) + if (CurIndex < (intptr_t)pArray->GetSize()) ++CurIndex; } return *this; @@ -641,7 +645,7 @@ public: { return Iterator(pArray, CurIndex - delta); } - SPInt operator-(const Iterator& right) const + intptr_t operator-(const Iterator& right) const { OVR_ASSERT(pArray == right.pArray); return CurIndex - right.CurIndex; @@ -658,21 +662,21 @@ public: pArray->RemoveAt(CurIndex); } - SPInt GetIndex() const { return CurIndex; } + intptr_t GetIndex() const { return CurIndex; } }; Iterator Begin() { return Iterator(this); } - Iterator End() { return Iterator(this, (SPInt)GetSize()); } - Iterator Last() { return Iterator(this, (SPInt)GetSize() - 1); } + Iterator End() { return Iterator(this, (intptr_t)GetSize()); } + Iterator Last() { return Iterator(this, (intptr_t)GetSize() - 1); } class ConstIterator { const SelfType* pArray; - SPInt CurIndex; + intptr_t CurIndex; public: ConstIterator() : pArray(0), CurIndex(-1) {} - ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} + ConstIterator(const SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {} bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } @@ -715,7 +719,7 @@ public: { return ConstIterator(pArray, CurIndex - delta); } - SPInt operator-(const ConstIterator& right) const + intptr_t operator-(const ConstIterator& right) const { OVR_ASSERT(pArray == right.pArray); return CurIndex - right.CurIndex; @@ -726,11 +730,11 @@ public: bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } - SPInt GetIndex() const { return CurIndex; } + intptr_t GetIndex() const { return CurIndex; } }; ConstIterator Begin() const { return ConstIterator(this); } - ConstIterator End() const { return ConstIterator(this, (SPInt)GetSize()); } - ConstIterator Last() const { return ConstIterator(this, (SPInt)GetSize() - 1); } + ConstIterator End() const { return ConstIterator(this, (intptr_t)GetSize()); } + ConstIterator Last() const { return ConstIterator(this, (intptr_t)GetSize() - 1); } protected: ArrayData Data; @@ -754,7 +758,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType; Array() : BaseType() {} - Array(UPInt size) : BaseType(size) {} + Array(size_t size) : BaseType(size) {} Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } Array(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -776,7 +780,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType; ArrayPOD() : BaseType() {} - ArrayPOD(UPInt size) : BaseType(size) {} + ArrayPOD(size_t size) : BaseType(size) {} ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } ArrayPOD(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -798,7 +802,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType; ArrayCPP() : BaseType() {} - ArrayCPP(UPInt size) : BaseType(size) {} + ArrayCPP(size_t size) : BaseType(size) {} ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } ArrayCPP(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -822,7 +826,7 @@ public: typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > BaseType; ArrayCC(const ValueType& defval) : BaseType(defval) {} - ArrayCC(const ValueType& defval, UPInt size) : BaseType(defval, size) {} + ArrayCC(const ValueType& defval, size_t size) : BaseType(defval, size) {} ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); } ArrayCC(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } diff --git a/LibOVR/Src/Kernel/OVR_Atomic.cpp b/LibOVR/Src/Kernel/OVR_Atomic.cpp index 9ea6e76..f7cf9a6 100644 --- a/LibOVR/Src/Kernel/OVR_Atomic.cpp +++ b/LibOVR/Src/Kernel/OVR_Atomic.cpp @@ -7,16 +7,16 @@ Content : Contains atomic operations and inline fastest locking Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -32,7 +32,7 @@ limitations under the License. #ifdef OVR_ENABLE_THREADS // Include Windows 8-Metro compatible Synchronization API -#if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) +#if defined(OVR_OS_MS) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) #include <synchapi.h> #endif @@ -41,43 +41,20 @@ namespace OVR { // ***** Windows Lock implementation -#if defined(OVR_OS_WIN32) +#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, spinCount, - OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO)); -#else - // Spin count init critical section function prototype for Window NT - typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount) - (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount); - - - // Try to load function dynamically so that we don't require NT - // On Windows NT we will use InitializeCriticalSectionAndSpinCount - static bool initTried = 0; - static Function_InitializeCriticalSectionAndSpinCount pInitFn = 0; - - if (!initTried) - { - HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll")); - pInitFn = (Function_InitializeCriticalSectionAndSpinCount) - ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount"); - initTried = true; - } - - // Initialize the critical section - if (pInitFn) - pInitFn(&cs, spinCount); - else - ::InitializeCriticalSection(&cs); -#endif - + #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 } @@ -107,7 +84,7 @@ Lock* SharedLock::GetLockAddRef() do { oldUseCount = UseCount; - if (oldUseCount == LockInitMarker) + if (oldUseCount == (int)LockInitMarker) continue; if (oldUseCount == 0) @@ -137,7 +114,7 @@ void SharedLock::ReleaseLock(Lock* plock) do { oldUseCount = UseCount; - OVR_ASSERT(oldUseCount != LockInitMarker); + OVR_ASSERT(oldUseCount != (int)LockInitMarker); if (oldUseCount == 1) { diff --git a/LibOVR/Src/Kernel/OVR_Atomic.h b/LibOVR/Src/Kernel/OVR_Atomic.h index b826251..478077b 100644 --- a/LibOVR/Src/Kernel/OVR_Atomic.h +++ b/LibOVR/Src/Kernel/OVR_Atomic.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Atomic.h Content : Contains atomic operations and inline fastest locking functionality. Will contain #ifdefs for OS efficiency. @@ -8,16 +8,16 @@ Content : Contains atomic operations and inline fastest locking Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -26,18 +26,26 @@ See the License for the specific language governing permissions and limitations under the License. ************************************************************************************/ + #ifndef OVR_Atomic_h #define OVR_Atomic_h #include "OVR_Types.h" // Include System thread functionality. -#if defined(OVR_OS_WIN32) -#include <windows.h> +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <Windows.h> #else #include <pthread.h> #endif +#ifdef OVR_CC_MSVC +#include <intrin.h> +#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier) +#endif namespace OVR { @@ -50,7 +58,7 @@ template<class C> class AtomicOps; template<class T> class AtomicInt; template<class T> class AtomicPtr; -class Lock; +class Lock; //----------------------------------------------------------------------------------- @@ -93,7 +101,7 @@ class Lock; struct AtomicOpsRawBase { -#if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_OS_WIN32) || defined(OVR_OS_IPHONE) +#if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) // Need to have empty constructor to avoid class 'unused' variable warning. struct FullSync { inline FullSync() { } }; struct AcquireSync { inline AcquireSync() { } }; @@ -109,12 +117,11 @@ struct AtomicOpsRawBase struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } }; struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } }; -#elif defined(OVR_CPU_ARM) +#elif defined(OVR_CPU_ARM) // Includes Android and iOS. struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } }; struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } }; struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } }; - #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4) // __sync functions are already full sync struct FullSync { inline FullSync() { } }; @@ -130,11 +137,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase #if !defined(OVR_ENABLE_THREADS) // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. - typedef UInt32 T; + typedef uint32_t T; // *** Thread - Safe Atomic Versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_MS) // Use special defined for VC6, where volatile is not used and // InterlockedCompareExchange is declared incorrectly. @@ -153,10 +160,10 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; } #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) - typedef UInt32 T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + typedef uint32_t T; + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -167,9 +174,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 dummy, ret; + uint32_t dummy, ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -181,9 +188,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -199,11 +206,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_MIPS) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "ll %[r],0(%[i])\n\t" @@ -215,9 +222,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "ll %[r],0(%[i])\n\t" @@ -230,9 +237,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret, dummy; + uint32_t ret, dummy; asm volatile("1:\n\t" "move %[r],$0\n\t" @@ -250,9 +257,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { for(;;) { @@ -261,7 +268,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return r; } } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { for(;;) { @@ -271,7 +278,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { for(;;) { @@ -284,11 +291,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_ARM) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret, dummy; + uint32_t ret, dummy; asm volatile("1:\n\t" "ldrex %[r],[%[i]]\n\t" @@ -300,9 +307,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret, dummy, test; + uint32_t ret, dummy, test; asm volatile("1:\n\t" "ldrex %[r],[%[i]]\n\t" @@ -315,9 +322,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret = 1, dummy, test; + uint32_t ret = 1, dummy, test; asm volatile("1:\n\t" "ldrex %[o],[%[i]]\n\t" @@ -334,9 +341,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_X86) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { asm volatile("xchgl %1,%[i]\n" : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory"); @@ -344,7 +351,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return j; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { asm volatile("lock; xaddl %1,%[i]\n" : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory"); @@ -352,9 +359,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return j; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret; + uint32_t ret; asm volatile("lock; cmpxchgl %[v],%[i]\n" : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory"); @@ -364,7 +371,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) - typedef UInt32 T; + typedef uint32_t T; static inline T Exchange_NoSync(volatile T *i, T j) { @@ -396,10 +403,10 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS) // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. - typedef UInt64 T; + typedef uint64_t T; // *** Thread - Safe OS specific versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_MS) // This is only for 64-bit systems. typedef LONG64 T; @@ -410,11 +417,11 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CPU_PPC64) - typedef UInt64 T; + typedef uint64_t T; - static inline UInt64 Exchange_NoSync(volatile UInt64 *i, UInt64 j) + static inline uint64_t Exchange_NoSync(volatile uint64_t *i, uint64_t j) { - UInt64 dummy, ret; + uint64_t dummy, ret; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -426,9 +433,9 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt64 ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j) + static inline uint64_t ExchangeAdd_NoSync(volatile uint64_t *i, uint64_t j) { - UInt64 dummy, ret; + uint64_t dummy, ret; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -440,9 +447,9 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value) + static inline bool CompareAndSet_NoSync(volatile uint64_t *i, uint64_t c, uint64_t value) { - UInt64 ret, dummy; + uint64_t ret, dummy; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -459,7 +466,7 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) - typedef UInt64 T; + typedef uint64_t T; static inline T Exchange_NoSync(volatile T *i, T j) { @@ -533,7 +540,22 @@ struct AtomicOpsRaw_DefImpl : public O #else inline static void Store_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; } #endif - inline static O_T Load_Acquire(const volatile O_T* p) { O_AcquireSync sync; OVR_UNUSED(sync); return *p; } + inline static O_T Load_Acquire(const volatile O_T* p) + { + O_AcquireSync sync; + OVR_UNUSED(sync); + +#if defined(OVR_CC_MSVC) + _ReadBarrier(); // Compiler fence and load barrier +#elif defined(OVR_CC_INTEL) + __memory_barrier(); // Compiler fence +#else + // GCC-compatible: + asm volatile ("" : : : "memory"); // Compiler fence +#endif + + return *p; + } }; @@ -583,11 +605,15 @@ public: inline static C ExchangeAdd_NoSync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_NoSync((PT)p, u.t); return u.c; } inline static bool CompareAndSet_Sync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Sync((PT)p, cu.t, u.t); } inline static bool CompareAndSet_Release(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Release((PT)p, cu.t, u.t); } - inline static bool CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); } + inline static bool CompareAndSet_Acquire(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); } inline static bool CompareAndSet_NoSync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_NoSync((PT)p, cu.t, u.t); } + // Loads and stores with memory fence. These have only the relevant versions. inline static void Store_Release(volatile C* p, C val) { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); } inline static C Load_Acquire(const volatile C* p) { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; } + + // Deprecated typo error: + inline static bool CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); } }; @@ -616,7 +642,7 @@ public: inline T Exchange_NoSync(T val) { return Ops::Exchange_NoSync(&Value, val); } inline bool CompareAndSet_Sync(T c, T val) { return Ops::CompareAndSet_Sync(&Value, c, val); } inline bool CompareAndSet_Release(T c, T val) { return Ops::CompareAndSet_Release(&Value, c, val); } - inline bool CompareAndSet_Acquire(T c, T val) { return Ops::CompareAndSet_Relse(&Value, c, val); } + inline bool CompareAndSet_Acquire(T c, T val) { return Ops::CompareAndSet_Acquire(&Value, c, val); } inline bool CompareAndSet_NoSync(T c, T val) { return Ops::CompareAndSet_NoSync(&Value, c, val); } // Load & Store. inline void Store_Release(T val) { Ops::Store_Release(&Value, val); } @@ -787,7 +813,6 @@ public: }; - //----------------------------------------------------------------------------------- // ***** Lock @@ -816,11 +841,11 @@ public: inline void Unlock() { } // Windows. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_MS) CRITICAL_SECTION cs; public: - Lock(unsigned spinCount = 0); + Lock(unsigned spinCount = 10000); // Mutexes with non-zero spin counts usually result in better performance. ~Lock(); // Locking functions. inline void DoLock() { ::EnterCriticalSection(&cs); } @@ -833,9 +858,9 @@ public: static pthread_mutexattr_t RecursiveAttr; static bool RecursiveAttrInit; - Lock (unsigned dummy = 0) + Lock (unsigned spinCount = 0) // To do: Support spin count, probably via a custom lock implementation. { - OVR_UNUSED(dummy); + OVR_UNUSED(spinCount); if (!RecursiveAttrInit) { pthread_mutexattr_init(&RecursiveAttr); @@ -881,7 +906,7 @@ private: // UseCount and max alignment. volatile int UseCount; - UInt64 Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)]; + uint64_t Buffer[(sizeof(Lock)+sizeof(uint64_t)-1)/sizeof(uint64_t)]; }; diff --git a/LibOVR/Src/Kernel/OVR_CRC32.cpp b/LibOVR/Src/Kernel/OVR_CRC32.cpp new file mode 100644 index 0000000..82cbe7f --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_CRC32.cpp @@ -0,0 +1,85 @@ +/************************************************************************************ + +Filename : OVR_CRC32.cpp +Content : CRC-32 with polynomial used for sensor devices +Created : June 20, 2014 +Author : Chris Taylor + +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_CRC32.h" + +namespace OVR { + + +static const uint32_t CRC_Table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + + +//// CRC-32 + +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t accumulator) +{ + const uint8_t* inputBytes = reinterpret_cast<const uint8_t*>( data ); + + for (int j = 0; j < bytes; ++j) + { + int i = ((uint32_t)(accumulator >> 24) ^ *inputBytes++) & 0xFF; + + accumulator = (accumulator << 8) ^ CRC_Table[i]; + } + + return ~accumulator; +} + + +} // OVR diff --git a/LibOVR/Src/Kernel/OVR_CRC32.h b/LibOVR/Src/Kernel/OVR_CRC32.h new file mode 100644 index 0000000..e4edd65 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_CRC32.h @@ -0,0 +1,45 @@ +/************************************************************************************ + +PublicHeader: OVR +Filename : OVR_CRC32.h +Content : CRC-32 with polynomial used for sensor devices +Created : June 20, 2014 +Author : Chris Taylor + +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. + +************************************************************************************/ + +#ifndef OVR_CRC32_h +#define OVR_CRC32_h + +#include "OVR_Types.h" + +namespace OVR { + + +//----------------------------------------------------------------------------------- +// ***** CRC-32 + +// Polynomial used and algorithm details are proprietary to our sensor board +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t prevCRC = 0); + + +} // namespace OVR + +#endif diff --git a/LibOVR/Src/Kernel/OVR_Color.h b/LibOVR/Src/Kernel/OVR_Color.h index cf536da..7b5e966 100644 --- a/LibOVR/Src/Kernel/OVR_Color.h +++ b/LibOVR/Src/Kernel/OVR_Color.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Color.h Content : Contains color struct. Created : February 7, 2013 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -31,11 +31,17 @@ limitations under the License. namespace OVR { + struct Color { - UByte R,G,B,A; + uint8_t R,G,B,A; - Color() {} + Color() + { + #if defined(OVR_BUILD_DEBUG) + R = G = B = A = 0; + #endif + } // Constructs color by channel. Alpha is set to 0xFF (fully visible) // if not specified. @@ -61,6 +67,7 @@ struct Color } }; -} + +} // namespace OVR #endif diff --git a/LibOVR/Src/Kernel/OVR_Compiler.h b/LibOVR/Src/Kernel/OVR_Compiler.h new file mode 100644 index 0000000..93a4181 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Compiler.h @@ -0,0 +1,1524 @@ +/************************************************************************************ + +PublicHeader: OVR.h +Filename : OVR_Compiler.h +Content : Compiler-specific feature identification and utilities +Created : June 19, 2014 +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. + +************************************************************************************/ + + +#ifndef OVR_Compiler_h +#define OVR_Compiler_h + +#pragma once + + +// References +// https://gcc.gnu.org/projects/cxx0x.html +// https://gcc.gnu.org/projects/cxx1y.html +// http://clang.llvm.org/cxx_status.html +// http://msdn.microsoft.com/en-us/library/hh567368.aspx +// https://docs.google.com/spreadsheet/pub?key=0AoBblDsbooe4dHZuVTRoSTFBejk5eFBfVk1GWlE5UlE&output=html +// http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros + + +//----------------------------------------------------------------------------------- +// ***** Compiler +// +// The following compilers are defined: (OVR_CC_x) +// +// MSVC - Microsoft Visual C/C++ +// INTEL - Intel C++ for Linux / Windows +// GNU - GNU C++ +// ARM - ARM C/C++ + +#if defined(__INTEL_COMPILER) +// Intel 4.0 = 400 +// Intel 5.0 = 500 +// Intel 6.0 = 600 +// Intel 8.0 = 800 +// Intel 9.0 = 900 +# define OVR_CC_INTEL __INTEL_COMPILER + +#elif defined(_MSC_VER) +// MSVC 5.0 = 1100 +// MSVC 6.0 = 1200 +// MSVC 7.0 (VC2002) = 1300 +// MSVC 7.1 (VC2003) = 1310 +// MSVC 8.0 (VC2005) = 1400 +// MSVC 9.0 (VC2008) = 1500 +// MSVC 10.0 (VC2010) = 1600 +// MSVC 11.0 (VC2012) = 1700 +// MSVC 12.0 (VC2013) = 1800 +# define OVR_CC_MSVC _MSC_VER + +#if _MSC_VER == 0x1600 +# if _MSC_FULL_VER < 160040219 +# error "Oculus does not support VS2010 without SP1 installed." +# endif +#endif + +#elif defined(__GNUC__) +# define OVR_CC_GNU + +#elif defined(__clang__) +# define OVR_CC_CLANG + +#elif defined(__CC_ARM) +# define OVR_CC_ARM + +#else +# error "Oculus does not support this Compiler" +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_VERSION +// +// M = major version +// m = minor version +// p = patch release +// b = build number +// +// Compiler Format Example +// ---------------------------- +// OVR_CC_GNU Mmm 408 means GCC 4.8 +// OVR_CC_CLANG Mmm 305 means clang 3.5 +// OVR_CC_MSVC MMMM 1700 means VS2012 +// OVR_CC_ARM Mmpbbb 401677 means 4.0, patch 1, build 677 +// OVR_CC_INTEL MMmm 1210 means 12.10 +// OVR_CC_EDG Mmm 407 means EDG 4.7 +// +#if defined(OVR_CC_GNU) + #define OVR_CC_VERSION ((__GNUC__ * 100) + __GNUC_MINOR__) +#elif defined(OVR_CC_CLANG) + #define OVR_CC_VERSION ((__clang_major__ * 100) + __clang_minor__) +#elif defined(OVR_CC_MSVC) + #define OVR_CC_VERSION _MSC_VER // Question: Should we recognize _MSC_FULL_VER? +#elif defined(OVR_CC_ARM) + #define OVR_CC_VERSION __ARMCC_VERSION +#elif defined(OVR_CC_INTEL) + #if defined(__INTEL_COMPILER) + #define OVR_CC_VERSION __INTEL_COMPILER + #elif defined(__ICL) + #define OVR_CC_VERSION __ICL + #elif defined(__ICC) + #define OVR_CC_VERSION __ICC + #elif defined(__ECC) + #define OVR_CC_VERSION __ECC + #endif +#elif defined(OVR_CC_EDG) + #define OVR_CC_VERSION __EDG_VERSION__ // This is a generic fallback for EDG-based compilers which aren't specified above (e.g. as OVR_CC_ARM) +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_OPTIMIZATION / OVR_RESTORE_OPTIMIZATION +// +// Allows for the dynamic disabling and restoring of compiler optimizations in code. +// This is useful for helping deal with potential compiler code generation problems. +// With VC++ the usage must be outside of function bodies. This can be used only to +// temporarily disable optimization for a block of code and not to temporarily enable +// optimization for a block of code. +// +// Clang doesn't support this as of June 2014, though function __attribute__((optimize(0)) +// is supposedly supported by clang in addition to GCC. To consider: Make a wrapper for +// this attribute-based functionality. +// +// Example usage: +// OVR_DISABLE_OPTIMIZATION() +// void Test() { ... } +// OVR_RESTORE_OPTIMIZATION() +// +#if !defined(OVR_DISABLE_OPTIMIZATION) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)) + #define OVR_DISABLE_OPTIMIZATION() \ + _Pragma("GCC push_options") \ + _Pragma("GCC optimize 0") + #elif defined(OVR_CC_MSVC) + #define OVR_DISABLE_OPTIMIZATION() __pragma(optimize("", off)) + #else + #define OVR_DISABLE_OPTIMIZATION() + #endif +#endif + +#if !defined(OVR_RESTORE_OPTIMIZATION) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)) + #define OVR_RESTORE_OPTIMIZATION() _Pragma("GCC pop_options") + #elif defined(OVR_CC_MSVC) + #define OVR_RESTORE_OPTIMIZATION() __pragma(optimize("", on)) + #else + #define OVR_RESTORE_OPTIMIZATION() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_GNU_WARNING / OVR_RESTORE_GNU_WARNING +// +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example +// usage for usage by example. +// +// Example usage: +// OVR_DISABLE_GNU_WARNING(-Wmissing-braces) // Only one warning per usage. +// OVR_DISABLE_GNU_WARNING(-Wunused-variable) +// <code> +// OVR_RESTORE_GNU_WARNINGS() +// OVR_RESTORE_GNU_WARNINGS() // Must match each disable with a restore. +// +#if !defined(OVR_DISABLE_GNU_WARNING) + #if defined(OVR_CC_GNU) + #define ODGW1(x) #x + #define ODGW2(x) ODGW1(GCC diagnostic ignored x) + #define ODGW3(x) ODGW2(#x) + #endif + + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 406) + #define OVR_DISABLE_GNU_WARNING(w) \ + _Pragma("GCC diagnostic push") \ + _Pragma(ODGW3(w)) + #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 404) // GCC 4.4 doesn't support diagnostic push, but supports disabling warnings. + #define OVR_DISABLE_GNU_WARNING(w) \ + _Pragma(ODGW3(w)) + #else + #define OVR_DISABLE_GNU_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_GNU_WARNING) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 4006) + #define OVR_RESTORE_GNU_WARNINGS() \ + _Pragma("GCC diagnostic pop") + #else + #define OVR_RESTORE_GNU_WARNING() + #endif +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_CLANG_WARNING / OVR_RESTORE_CLANG_WARNING +// +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example +// usage for usage by example. +// +// Example usage: +// OVR_DISABLE_CLANG_WARNING(-Wmissing-braces) // Only one warning per usage. +// OVR_DISABLE_CLANG_WARNING(-Wunused-variable) +// <code> +// OVR_RESTORE_CLANG_WARNINGS() +// OVR_RESTORE_CLANG_WARNINGS() // Must match each disable with a restore. +// +// +#if !defined(OVR_DISABLE_CLANG_WARNING) + #if defined(OVR_CC_CLANG) + #define ODCW1(x) #x + #define ODCW2(x) ODCW1(clang diagnostic ignored x) + #define ODCW3(x) ODCW2(#x) + + #define OVR_DISABLE_CLANG_WARNING(w) \ + _Pragma("clang diagnostic push") \ + _Pragma(ODCW3(w)) + #else + #define OVR_DISABLE_CLANG_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_CLANG_WARNING) + #if defined(OVR_CC_CLANG) + #define OVR_RESTORE_CLANG_WARNING() \ + _Pragma("clang diagnostic pop") + #else + #define OVR_RESTORE_CLANG_WARNING() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_MSVC_WARNING / OVR_RESTORE_MSVC_WARNING +// +// Portable wrapper for disabling VC++ compiler warnings. See example usage for usage +// by example. +// +// Example usage: +// OVR_DISABLE_MSVC_WARNING(4556 4782 4422) +// <code> +// OVR_RESTORE_MSVC_WARNING() +// +#if !defined(OVR_DISABLE_MSVC_WARNING) + #if defined(OVR_CC_MSVC) + #define OVR_DISABLE_MSVC_WARNING(w) \ + __pragma(warning(push)) \ + __pragma(warning(disable:w)) + #else + #define OVR_DISABLE_MSVC_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_MSVC_WARNING) + #if defined(OVR_CC_MSVC) + #define OVR_RESTORE_MSVC_WARNING() \ + __pragma(warning(pop)) + #else + #define OVR_RESTORE_MSVC_WARNING() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_ALL_MSVC_WARNINGS / OVR_RESTORE_ALL_MSVC_WARNINGS +// +// Portable wrapper for disabling all VC++ compiler warnings. +// OVR_RESTORE_ALL_MSVC_WARNINGS restores warnings that were disabled by +// OVR_DISABLE_ALL_MSVC_WARNINGS. Any previously enabled warnings will still be +// enabled after OVR_RESTORE_ALL_MSVC_WARNINGS. +// +// Example usage: +// OVR_DISABLE_ALL_MSVC_WARNINGS() +// <code> +// OVR_RESTORE_ALL_MSVC_WARNINGS() + +#if !defined(OVR_DISABLE_ALL_MSVC_WARNINGS) + #if defined(OVR_CC_MSVC) + #define OVR_DISABLE_ALL_MSVC_WARNINGS() \ + __pragma(warning(push, 0)) + #else + #define OVR_DISABLE_ALL_MSVC_WARNINGS() + #endif +#endif + +#if !defined(OVR_RESTORE_ALL_MSVC_WARNINGS) + #if defined(OVR_CC_MSVC) + #define OVR_RESTORE_ALL_MSVC_WARNINGS() \ + __pragma(warning(pop)) + #else + #define OVR_RESTORE_ALL_MSVC_WARNINGS() + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_HAS_FEATURE +// +// This is a portable way to use compile-time feature identification available +// with some compilers in a clean way. Direct usage of __has_feature in preprocessing +// statements of non-supporting compilers results in a preprocessing error. +// +// Example usage: +// #if OVR_CC_HAS_FEATURE(is_pod) +// if(__is_pod(T)) // If the type is plain data then we can safely memcpy it. +// memcpy(&destObject, &srcObject, sizeof(object)); +// #endif +// +#if !defined(OVR_CC_HAS_FEATURE) + #if defined(__clang__) // http://clang.llvm.org/docs/LanguageExtensions.html#id2 + #define OVR_CC_HAS_FEATURE(x) __has_feature(x) + #else + #define OVR_CC_HAS_FEATURE(x) 0 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_HAS_BUILTIN +// +// +// This is a portable way to use compile-time builtin identification available +// with some compilers in a clean way. Direct usage of __has_builtin in preprocessing +// statements of non-supporting compilers results in a preprocessing error. +// +// Example usage: +// #if OVR_CC_HAS_BUILTIN(__builtin_trap) +// #define DEBUG_BREAK __builtin_trap +// #endif +// +#if !defined(OVR_CC_HAS_BUILTIN) + #if defined(__clang__) + #define OVR_CC_HAS_BUILTIN(x) __has_builtin(x) // http://clang.llvm.org/docs/LanguageExtensions.html#id2 + #else + #define OVR_CC_HAS_BUILTIN(x) 0 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP11_ENABLED / OVR_CPP_CPP14_ENABLED +// +// Defined as 1 if the compiler has its available C++11 support enabled, else undefined. +// This does not mean that all of C++11 or any particular feature of C++11 is supported +// by the compiler. It means that whatever C++11 support the compiler has is enabled. +// This also includes existing and older compilers that still identify C++11 as C++0x. +// +#if !defined(OVR_CPP11_ENABLED) && defined(__cplusplus) + #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) + #define OVR_CPP11_ENABLED 1 + #elif defined(_MSC_VER) && (_MSC_VER >= 1500) // VS2010+, the first version with any significant C++11 support. + #define OVR_CPP11_ENABLED 1 + #elif (__cplusplus >= 201103L) // 201103 is the first C++11 version. + #define OVR_CPP11_ENABLED 1 + #else + // Leave undefined + #endif +#endif + +#if !defined(OVR_CPP_CPP14_ENABLED) && defined(__cplusplus) + #if defined(_MSC_VER) && (_MSC_VER >= 1800) // VS2013+, the first version with any significant C++14 support. + #define OVR_CPP_CPP14_ENABLED 1 + #elif (__cplusplus > 201103L) + #define OVR_CPP_CPP14_ENABLED 1 + #else + // Leave undefined + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXCEPTIONS / OVR_CPP_NO_UNWIND +// +// OVR_CPP_NO_EXCEPTIONS is defined as 1 if the compiler doesn't support C++ +// exceptions or is configured to disable support for them. Else not defined. +// If OVR_CPP_NO_EXCEPTIONS is defined then attempts to use try/catch +// related C++ statements result in a compilation error with many +// compilers. +// +// OVR_CPP_NO_UNWIND is defined as 1 if the compiler supports exceptions but +// doesn't support stack unwinding in the presence of an exception. Else not defined. +// For the Microsoft compiler, disabling exceptions means disabling stack unwinding +// and not disabling exceptions themselves. +// +// Example usage: +// void Test() { +// #if !defined(OVR_CPP_NO_EXCEPTIONS) +// try { +// #endif +// void* ptr = new Object; +// #if !defined(OVR_CPP_NO_EXCEPTIONS) +// catch(...) { ... } +// #endif + +#if !defined(OVR_CPP_NO_EXCEPTIONS) + #if defined(OVR_CPP_GNUC) && defined(_NO_EX) + #define OVR_CPP_NO_EXCEPTIONS 1 + #elif (defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || defined(OVR_CC_INTEL) || defined(OVR_CC_ARM)) && !defined(__EXCEPTIONS) + #define OVR_CPP_NO_EXCEPTIONS 1 + #elif defined(OVR_CC_MSVC) && !defined(_CPPUNWIND) + #define OVR_CPP_NO_UNWIND 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RTTI +// +// Defined as 1 if C++ run-time type information support is unavailable or disabled +// by the compiler. Else undefined. Allows you to write portable code in the face +// of the possibility that RTTI is disabled. +// +// Example usage: +// #if !OVR_CPP_NO_RTTI +// #include <typeinfo> +// int x = std::dynamic_cast<int>(3.4f); +// #endif + +#if defined(__clang__) && !OVR_CC_HAS_FEATURE(cxx_rtti) + #define OVR_CPP_NO_RTTI 1 +#elif defined(__GNUC__) && !defined(__GXX_RTTI) + #define OVR_CPP_NO_RTTI 1 +#elif defined(_MSC_VER) && !defined(_CPPRTTI) + #define OVR_CPP_NO_RTTI 1 +#elif defined(__CC_ARM) && defined(__TARGET_CPU_MPCORE) && !defined(__RTTI) + #define OVR_CPP_NO_RTTI 1 +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STATIC_ASSERT +// +// Defined as 1 if C++ run-time type information support is available and enabled +// by the compiler. Else undefined. +// +// Example usage: +// #if OVR_CPP_NO_STATIC_ASSERT +// #define MY_ASSERT(x) { int zero = 0; switch(zero) {case 0: case (x):;} } +// #else +// #define MY_ASSERT(x) static_assert((x), #x) +// #endif + +#if !defined(OVR_CPP_NO_STATIC_ASSERT) + #if !(defined(__GNUC__) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)))) && \ + !(defined(__clang__) && defined(__cplusplus) && OVR_CC_HAS_FEATURE(cxx_static_assert)) && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)) && /* VS2010+ */ \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) && defined(OVR_CPP11_ENABLED)) /* EDG 4.1+ */ + #define OVR_CPP_NO_STATIC_ASSERT 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NULLPTR +// +// Defined as 1 if the compiler doesn't support C++11 nullptr built in type. +// Otherwise undefined. Does not identify if the standard library defines +// std::nullptr_t, as some standard libraries are further behind in standardization +// than the compilers using them (e.g. Apple clang with the supplied libstdc++). +// +// OVR_Nullptr.h provides a portable nullptr and std::nullptr_t for when the +// compiler or standard library do not. + +#if !defined(OVR_CPP_NO_NULLPTR) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_nullptr)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_NULLPTR 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RVALUE_REFERENCES +// +// Defined as 1 if the compiler doesn't support C++11 rvalue references and move semantics. +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_RVALUE_REFERENCES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_rvalue_references)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_RVALUE_REFERENCES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_AUTO +// +// Defined as 1 if the compiler doesn't support C++11 auto keyword. Otherwise undefined. + +#if !defined(OVR_CPP_NO_AUTO) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_auto_type)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 309))) /* EDG 3.9+ */ + #define OVR_CPP_NO_AUTO 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RANGE_BASED_FOR_LOOP +// +// Defined as 1 if the compiler doesn't support C++11 range-based for loops. +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_RANGE_BASED_FOR_LOOP) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_range_for)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_RANGE_BASED_FOR_LOOP 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_CONSTEXPR / OVR_CPP_NO_RELAXED_CONSTEXPR +// +// OVR_CPP_NO_CONSTEXPR is defined as 1 if the compiler doesn't support C++11 constexpr. +// OVR_CPP_NO_RELAXED_CONSTEXPR is defined as 1 if the compiler doesn't support C++14 constexpr. +// Otherwise undefined. +// See the OVR_CONSTEXPR / OVR_CONSTEXPR_OR_CONST macros for portable wrappers of this functionality. + +#if !defined(OVR_CPP_NO_CONSTEXPR) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_constexpr)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + // Not supported by VC++ through at least VS2013. + #define OVR_CPP_NO_CONSTEXPR 1 + #endif +#endif + +#if !defined(OVR_CPP_NO_RELAXED_CONSTEXPR) + #if !defined(OVR_CPP14_ENABLED) || \ + !(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_relaxed_constexpr)) /* clang */ + // Supported only by clang as of this writing. + #define OVR_CPP_NO_RELAXED_CONSTEXPR 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_LAMBDA_EXPRESSIONS +// +// Defined as 1 if the compiler doesn't support C++11 lambda expressions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_LAMBDA_EXPRESSIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_lambdas)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Conversion of lambdas to function pointers is not supported until EDG 4.5. + #define OVR_CPP_NO_LAMBDA_EXPRESSIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_ALIGNOF +// +// Defined as 1 if the compiler supports C++11 alignof. Otherwise undefined. +// Some compilers support __alignof__ instead of alignof, so for portability you +// should use OVR_ALIGNOF instead of directly using C++11 alignof. + +#if !defined(OVR_CPP_NO_ALIGNOF) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 300)) /* Apple clang 3.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 401)) /* GCC 4.1+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400))) /* EDG 4.0+ */ + #define OVR_CPP_NO_ALIGNOF 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_ALIGNAS +// +// Defined as 1 if the compiler supports C++11 alignas. Otherwise undefined. +// See the OVR_ALIGNAS for a portable wrapper for alignas functionality. + +#if !defined(OVR_CPP_NO_ALIGNAS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_ALIGNAS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_OVERRIDE +// +// Defined as 1 if the compiler doesn't support C++11 override. Otherwise undefined. +// See the OVR_OVERRIDE and OVR_FINALOVERRIDE macros for a portable wrapper. + +#if !defined(OOVR_CPP_NO_OVERRIDE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_OVERRIDE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FINAL +// +// Defined as 1 if the compiler doesn't support C++11 final attribute. Otherwise undefined. +// See the OVR_FINAL and OVR_FINALOVERRIDE macros for a portable wrapper. + +#if !defined(OOVR_CPP_NO_FINAL) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_FINAL 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTERN_TEMPLATE +// +// Defined as 1 if the compiler doesn't support C++11 extern template. +// Otherwise undefined. See OVR_EXTERN_TEMPLATE for wrapper macro. + +#if !defined(OVR_CPP_NO_EXTERN_TEMPLATE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_EXTERN_TEMPLATE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_VARIADIC_TEMPLATES +// +// Defined as 1 if the compiler doesn't support C++11 variadic templates. Otherwise undefined. + +#if !defined(OVR_CPP_NO_VARIADIC_TEMPLATES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_variadic_templates)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_VARIADIC_TEMPLATES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NOEXCEPT +// +// Defined as 1 if the compiler supports C++11 noexcept. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/noexcept +// See OVR_NOEXCEPT / OVR_NOEXCEPT_IF / OVR_NOEXCEPT_EXPR for a portable wrapper +// for noexcept functionality. + +#if !defined(OVR_CPP_NO_NOEXCEPT) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_noexcept)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_NOEXCEPT 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DECLTYPE +// +// Defined as 1 if the compiler doesn't support C++11 decltype. Otherwise undefined. +// Some compilers (e.g. VS2012) support most uses of decltype but don't support +// decltype with incomplete types (which is an uncommon usage seen usually in +// template metaprogramming). We don't include this support as a requirement for +// our definition of decltype support here. + +#if !defined(OVR_CPP_NO_DECLTYPE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_decltype)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + // VC++ fails to support decltype for incomplete types until VS2013. + // EDG fails to support decltype for incomplete types until v4.8. + #define OVR_CPP_NO_DECLTYPE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DEFAULTED_FUNCTIONS +// +// Defined as 1 if the compiler doesn't support C++11 defaulted functions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions))/* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators. + // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators. + #define OVR_CPP_NO_DEFAULTED_FUNCTIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DELETED_FUNCTIONS +// +// Defined as 1 if the compiler doesn't support C++11 deleted functions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators. + // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators. + #define OVR_CPP_NO_DELETED_FUNCTIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STANDARD_LAYOUT_TYPES +// +// Defined as 1 if the compiler doesn't support C++11 standard layout (relaxed POD). Otherwise undefined. +// http://en.cppreference.com/w/cpp/types/is_standard_layout + +#if !defined(OVR_CPP_NO_STANDARD_LAYOUT_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_STANDARD_LAYOUT_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FORWARD_DECLARED_ENUMS +// +// Defined as 1 if the compiler doesn't support C++11 forward declared enums. Otherwise undefined. + +#if !defined(OVR_CPP_NO_FORWARD_DECLARED_ENUMS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_FORWARD_DECLARED_ENUMS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STRONGLY_TYPED_ENUMS +// +// Defined as 1 if the compiler doesn't support C++11 strongly typed enums. Otherwise undefined. + +#if !defined(OVR_CPP_NO_STRONGLY_TYPED_ENUMS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_strong_enums)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400))) /* EDG 4.0+ */ + #define OVR_CPP_NO_STRONGLY_TYPED_ENUMS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_TRAILING_RETURN_TYPES +// +// Defined as 1 if the compiler doesn't support C++11 trailing return types. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#Alternative_function_syntax + +#if !defined(OVR_CPP_NO_TRAILING_RETURN_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_trailing_return)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_TRAILING_RETURN_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_TEMPLATE_ALIASES +// +// Defined as 1 if the compiler doesn't support C++11 template aliases. Otherwise undefined. + +#if !defined(OVR_CPP_NO_TEMPLATE_ALIASES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_alias_templates)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + #define OVR_CPP_NO_TEMPLATE_ALIASES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INITIALIZER_LISTS +// +// Defined as 1 if the compiler doesn't support C++11 initializer lists. Otherwise undefined. +// This refers to the compiler support for this and not the Standard Library support for std::initializer_list, +// as a new compiler with an old standard library (e.g. Apple clang with libstdc++) may not support std::initializer_list. + +#if !defined(OVR_CPP_NO_INITIALIZER_LISTS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_INITIALIZER_LISTS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NORETURN +// +// Defined as 1 if the compiler doesn't support the C++11 noreturn attribute. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/attributes +// +#if !defined(OVR_CPP_NO_NORETURN) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + // Supported with VC++ only via __declspec(noreturn) (see OVR_NORETURN). + #define OVR_CPP_NO_NORETURN 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS +// +// Defined as 1 if the compiler doesn't support C++11 in-class non-static member initializers. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/data_members + +#if !defined(OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS +// +// Defined as 1 if the compiler supports nested template declarations with >>, +// as supported by C++11. Otherwise undefined. + +#if !defined(OVR_CPP_NO_DOUBLE_TEMPLATE_ANGLE_BRACKETS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS 1 + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INHERITING_CONSTRUCTORS +// +// Defined as 1 if the compiler supports C++11 inheriting constructors. Otherwise undefined. +// Example usage: +// struct A { explicit A(int x){} }; +// struct B : public A { using A::A; }; // As if B redeclared A::A(int). + +#if !defined(OVR_CPP_NO_INHERITING_CONSTRUCTORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_inheriting_constructors)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_INHERITING_CONSTRUCTORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DELEGATING_CONSTRUCTORS +// +// Defined as 1 if the compiler supports C++11 delegating constructors. Otherwise undefined. + +#if !defined(OVR_CPP_NO_DELEGATING_CONSTRUCTORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + #define OVR_CPP_NO_DELEGATING_CONSTRUCTORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS +// +// Defined as 1 if the compiler supports C++11 function template default arguments. Otherwise undefined. + +#if !defined(OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNRESTRICTED_UNIONS +// +// Defined as 1 if the compiler supports C++11 unrestricted unions. Otherwise undefined. + +#if !defined(OVR_CPP_NO_UNRESTRICTED_UNIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_UNRESTRICTED_UNIONS 1 + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTENDED_SIZEOF +// +// Defined as 1 if the compiler supports C++11 class sizeof extensions (e.g. sizeof SomeClass::someMember). +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_EXTENDED_SIZEOF) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_EXTENDED_SIZEOF 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INLINE_NAMESPACES +// +// Defined as 1 if the compiler supports C++11 inlined namespaces. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces + +#if !defined(OVR_CPP_NO_INLINE_NAMESPACES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_INLINE_NAMESPACES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS +// +// Defined as 1 if the compiler supports C++11 explicit conversion operators. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/explicit + +#if !defined(OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_explicit_conversions)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404))) /* EDG 4.4+ */ + #define OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS +// +// Defined as 1 if the compiler supports C++11 local class template parameters. Otherwise undefined. +// Example: +// void Test() { +// struct LocalClass{ }; +// SomeTemplateClass<LocalClass> t; // Allowed only in C++11 +// } + +#if !defined(OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_local_type_template_args)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + #define OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NEW_CHARACTER_TYPES +// +// Defined as 1 if the compiler natively supports C++11 char16_t and char32_t. Otherwise undefined. +// VC++ through at least VS2013 defines char16_t as unsigned short in its standard library, +// but it is not a native type or unique type, nor can you for a string literal with it. + +#if !defined(OVR_CPP_NO_NEW_CHARACTER_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_NEW_CHARACTER_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS +// +// Defined as 1 if the compiler supports C++11 \u and \U character literals for +// native char16_t and char32_t types. +// +#if !defined(OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + // Not supported by VC++ as of VS2013. VC++'s existing \U and \u are non-conforming. + #define OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_USER_DEFINED_LITERALS +// +// Defined as 1 if the compiler supports C++11 user-defined literals. Otherwise undefined. + +#if !defined(OVR_CPP_NO_USER_DEFINED_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_USER_DEFINED_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNICODE_STRING_LITERALS +// +// Defined as 1 if the compiler supports C++11 Unicode string literals. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + +#if !defined(OVR_CPP_NO_UNICODE_STRING_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_UNICODE_STRING_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RAW_STRING_LITERALS +// +// Defined as 1 if the compiler supports C++11 raw literals. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + +#if !defined(OVR_CPP_NO_RAW_STRING_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_raw_string_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_RAW_STRING_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX +// +// Defined as 1 if the compiler supports C++11 unified initialization. +// http://en.wikipedia.org/wiki/C%2B%2B11#Uniform_initialization + +#if !defined(OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS +// +// Defined as 1 if the compiler supports C++11 extended friends. + +#if !defined(OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_THREAD_LOCAL +// +// Defined as 1 if the compiler supports C++11 thread_local. Else undefined. Does not +// indicate if the compiler supports C thread-local compiler extensions such as __thread +// and declspec(thread). Use OVR_THREAD_LOCAL if you want to declare a thread-local +// variable that supports C++11 thread_local when available but the C extension when +// it's available. The primary difference between C++11 thread_local and C extensions is +// that C++11 thread_local supports non-PODs and calls their constructors and destructors. +// +// Note that thread_local requires both compiler and linker support, and so it's possible +// that the compiler may support thread_local but the linker does not. + +#if !defined(OVR_CPP_NO_THREAD_LOCAL) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_thread_local)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CC_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_THREAD_LOCAL 1 + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_ALIGNAS / OVR_ALIGNOF +// +// OVR_ALIGNAS(n) // Specifies a size_t power of two alignment for a type or instance. +// OVR_ALIGNOF(type) // Returns the size_t alignment of a type or instance. +// +// Example usage: +// OVR_ALIGNAS(8) char c = 'c'; // Specifies that the instance c be aligned to an 8 byte boundary. +// typedef OVR_ALIGNAS(8) char C; // Specifies that the type C be aligned to an 8 byte boundary. +// struct OVR_ALIGNAS(64) S{ char array[16]; }; // Specfies that the struct S have a natural alignment of 64. +// OVR_ALIGNAS(32) S s; // Specifies that the instance s of struct S be aligned to an 32 byte boundary. +// OVR_ALIGNAS(32) struct T{ char array[16]; } t; // Specfies that the instance t of struct T have a natural alignment of 32. +// struct OVR_ALIGNAS(T) U{}; // Specifes that U be aligned the same as T. Supported only by C++11 compilers (see OVR_CPP_NO_ALIGNAS). +// +// size_t a = OVR_ALIGNOF(double); // Returns the natural alignment of the double type. +// size_t a = OVR_ALIGNOF(S); // Returns the natural alignment of the struct S type. +// +// Note: If C++11 alignas is supported, then alignas/OVR_ALIGNAS may take a const expression in addition to a constant. +// Note: The C11 Standard species the _Alignas keyword and alignas as a macro for it in <stdalign.h> + +#if !defined(OVR_ALIGNAS) + #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNAS) // If C++11 alignas is supported... + #define OVR_ALIGNAS(n) alignas(n) + #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNAS) + #define OVR_ALIGNAS(n) alignas(n) + #elif defined(OVR_CC_GNU) || defined(__clang__) + #define OVR_ALIGNAS(n) __attribute__((aligned(n))) + #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL) + #define OVR_ALIGNAS(n) __declspec(align(n)) // For Microsoft the alignment must be a literal integer. + #elif defined(OVR_CC_ARM) + #define OVR_ALIGNAS(n) __align(n) + #else + #error Need to define OVR_ALIGNAS + #endif +#endif + +#if !defined(OVR_ALIGNOF) + #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNOF) // If C++11 alignof is supported... + #define OVR_ALIGNOF(type) alignof(type) + #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNOF) + #define OVR_ALIGNOF(type) alignof(type) + #elif defined(OVR_CC_GNU) || defined(__clang__) + #define OVR_ALIGNOF(type) ((size_t)__alignof__(type)) + #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL) + #define OVR_ALIGNOF(type) ((size_t)__alignof(type)) + #elif defined(OVR_CC_ARM) + #define OVR_ALIGNOF(type) ((size_t)__ALIGNOF__(type)) + #else + #error Need to define OVR_ALIGNOF + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_ASSUME / OVR_ANALYSIS_ASSUME +// +// This is a portable wrapper for VC++'s __assume and __analysis_assume. +// __analysis_assume is typically used to quell VC++ static analysis warnings. +// +// Example usage: +// void Test(char c){ +// switch(c){ +// case 'a': +// case 'b': +// case 'c': +// case 'd': +// break; +// default: +// OVR_ASSUME(0); // Unreachable code. +// } +// } +// +// size_t Test(char* str){ +// OVR_ANALYSIS_ASSUME(str != nullptr); +// return strlen(str); +// } + +#if !defined(OVR_ASSUME) + #if defined(OVR_CC_MSVC) + #define OVR_ASSUME(x) __assume(x) + #define OVR_ANALYSIS_ASSUME(x) __analysis_assume(!!(x)) + #else + #define OVR_ASSUME(x) + #define OVR_ANALYSIS_ASSUME(x) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_RESTRICT +// +// Wraps the C99 restrict keyword in a portable way. +// C++11 and C++14 don't have restrict but this functionality is supported by +// all C++ compilers. +// +// Example usage: +// void* memcpy(void* OVR_RESTRICT s1, const void* OVR_RESTRICT s2, size_t n); + +#if !defined(OVR_RESTRICT) + #define OVR_RESTRICT __restrict // Currently supported by all compilers of significance to us. +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_NOEXCEPT / OVR_NOEXCEPT_IF(predicate) / OVR_NOEXCEPT_EXPR(expression) +// +// Implements a portable wrapper for C++11 noexcept. +// http://en.cppreference.com/w/cpp/language/noexcept +// +// Example usage: +// void Test() OVR_NOEXCEPT {} // This function doesn't throw. +// +// template <typename T> +// void DoNothing() OVR_NOEXCEPT_IF(OVR_NOEXCEPT_EXPR(T())) // Throws an if and only if T::T(int) throws. +// { T t(3); } +// +#if !defined(OVR_NOEXCEPT) + #if defined(OVR_CPP_NOEXCEPT) + #define OVR_NOEXCEPT + #define OVR_NOEXCEPT_IF(predicate) + #define OVR_NOEXCEPT_EXPR(expression) false + #else + #define OVR_NOEXCEPT noexcept + #define OVR_NOEXCEPT_IF(predicate) noexcept((predicate)) + #define OVR_NOEXCEPT_EXPR(expression) noexcept((expression)) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FINAL +// +// Wraps the C++11 final keyword in a portable way. +// http://en.cppreference.com/w/cpp/language/final +// +// Example usage: +// struct Test { virtual int GetValue() OVR_FINAL; }; + +#if !defined(OVR_FINAL) + #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION < 1700) // VC++ 2012 and earlier + #define OVR_FINAL sealed + #elif defined(OVR_CPP_INHERITANCE_FINAL) + #define OVR_FINAL + #else + #define OVR_FINAL final + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_OVERRIDE +// +// Wraps the C++11 override keyword in a portable way. +// http://en.cppreference.com/w/cpp/language/override +// +// Example usage: +// struct Parent { virtual void Func(int); }; +// struct Child : public Parent { void Func(int) OVR_OVERRIDE; }; + +#if !defined(OVR_CPP11_ENABLED) +#define OVR_OVERRIDE +#elif !defined(OVR_OVERRIDE) + #if defined(OVR_CPP_OVERRIDE) + #define OVR_OVERRIDE + #else + #if (defined(_MSC_VER) && (_MSC_VER <= 1600)) + #pragma warning(disable : 4481) + #endif + #define OVR_OVERRIDE override + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FINAL_OVERRIDE +// +// Wraps the C++11 final+override keywords (a common combination) in a portable way. +// +// Example usage: +// struct Parent { virtual void Func(); }; +// struct Child : public Parent { virtual void Func() OVR_FINAL_OVERRIDE; }; + +#if !defined(OVR_FINAL_OVERRIDE) + #define OVR_FINAL_OVERRIDE OVR_FINAL OVR_OVERRIDE +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_EXTERN_TEMPLATE +// +// Portable wrapper for C++11 extern template. This tells the compiler to not instantiate +// the template in the current translation unit, which can significantly speed up +// compilation and avoid problems due to two translation units compiling code with +// different settings. +// +// Example usage: +// OVR_EXTERN_TEMPLATE(class basic_string<char>); // Nothing to do for non-C++11 compilers. + +#if !defined(OVR_EXTERN_TEMPLATE) + #if defined(OVR_CPP_EXTERN_TEMPLATE) + #define OVR_EXTERN_TEMPLATE(decl) + #else + #define OVR_EXTERN_TEMPLATE(decl) extern template decl + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_CONSTEXPR / OVR_CONSTEXPR_OR_CONST +// +// Portable wrapper for C++11 constexpr. Doesn't include C++14 relaxed constexpr, +// for which a different wrapper name is reserved. +// +// Example usage: +// OVR_CONSTEXPR int Test() { return 15; } // This can be optimized better by a C++11 compiler that supports constexpr. +// OVR_CONSTEXPR_OR_CONST float x = 3.14159f; // This can be optimized better by a C++11 compiler, but if not then at least make it const. + +#if !defined(OVR_CONSTEXPR) + #if defined(OVR_CPP_NO_CONSTEXPR) + #define OVR_CONSTEXPR + #else + #define OVR_CONSTEXPR constexpr + #endif +#endif + +#if !defined(OVR_CONSTEXPR_OR_CONST) + #if defined(OVR_CPP_NO_CONSTEXPR) + #define OVR_CONSTEXPR_OR_CONST const + #else + #define OVR_CONSTEXPR_OR_CONST constexpr + #endif +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FUNCTION_DELETE / OVR_FUNCTION_DEFAULT +// +// Wraps the C++11 delete and default keywords in a way that allows for cleaner code +// while making for a better version of uncallable or default functions. +// +// Example usage: +// struct Test{ +// Test() OVR_FUNCTION_DEFAULT; // Non-C++11 compilers will require a separate definition for Test(). +// private: // Users should put OVR_FUNCTION_DELETE usage in a private +// void Uncallable() OVR_FUNCTION_DELETE; // area for compatibility with pre-C++11 compilers. +// }; + +#if defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #define OVR_FUNCTION_DELETE +#else + #define OVR_FUNCTION_DELETE = delete +#endif + +#if defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS) + #define OVR_FUNCTION_DEFAULT +#else + #define OVR_FUNCTION_DEFAULT = default +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_NON_COPYABLE +// +// Allows you to specify a class as being neither copy-constructible nor assignable, +// which is a commonly needed pattern in C++ programming. Classes with this declaration +// are required to be default constructible (as are most classes). For pre-C++11 +// compilers this macro declares a private section for the class, which will be +// inherited by whatever code is directly below the macro invocation by default. +// +// Example usage: +// struct Test { +// Test(); +// ... +// OVR_NON_COPYABLE(Test) +// }; + +#if !defined(OVR_NON_COPYABLE) + #if defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #define OVR_NON_COPYABLE(Type) \ + private: \ + Type(const Type&); \ + void operator=(const Type&); + #else + #define OVR_NON_COPYABLE(Type) \ + Type(const Type&) = delete; \ + void operator=(const Type&) = delete; + #endif +#endif + + + +#endif // header include guard + + + + diff --git a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h index afc0e6a..46bea2e 100644 --- a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h +++ b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_ContainerAllocator.h Content : Template allocators and constructors for containers. Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -45,8 +45,8 @@ namespace OVR { class ContainerAllocatorBase { public: - static void* Alloc(UPInt size) { return OVR_ALLOC(size); } - static void* Realloc(void* p, UPInt newSize) { return OVR_REALLOC(p, newSize); } + static void* Alloc(size_t size) { return OVR_ALLOC(size); } + static void* Realloc(void* p, size_t newSize) { return OVR_REALLOC(p, newSize); } static void Free(void *p) { OVR_FREE(p); } }; @@ -73,29 +73,29 @@ public: *(T*)p = source; } - static void ConstructArray(void*, UPInt) {} + static void ConstructArray(void*, size_t) {} - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) *(T*)pdata = source; } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { memcpy(p, psource, sizeof(T) * count); } static void Destruct(T*) {} - static void DestructArray(T*, UPInt) {} + static void DestructArray(T*, size_t) {} - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } @@ -129,24 +129,24 @@ public: OVR::ConstructAlt<T,S>(p, source); } - static void ConstructArray(void* p, UPInt count) + static void ConstructArray(void* p, size_t count) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata); } - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, source); } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, *psource++); } @@ -156,19 +156,19 @@ public: OVR_UNUSED(p); // Suppress silly MSVC warning } - static void DestructArray(T* p, UPInt count) + static void DestructArray(T* p, size_t count) { p += count - 1; - for (UPInt i=0; i<count; ++i, --p) + for (size_t i=0; i<count; ++i, --p) p->~T(); } - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } @@ -202,24 +202,24 @@ public: OVR::ConstructAlt<T,S>(p, source); } - static void ConstructArray(void* p, UPInt count) + static void ConstructArray(void* p, size_t count) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata); } - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, source); } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, *psource++); } @@ -229,22 +229,22 @@ public: OVR_UNUSED(p); // Suppress silly MSVC warning } - static void DestructArray(T* p, UPInt count) + static void DestructArray(T* p, size_t count) { p += count - 1; - for (UPInt i=0; i<count; ++i, --p) + for (size_t i=0; i<count; ++i, --p) p->~T(); } - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { - for(UPInt i = 0; i < count; ++i) + for(size_t i = 0; i < count; ++i) dst[i] = src[i]; } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { - for(UPInt i = count; i; --i) + for(size_t i = count; i; --i) dst[i-1] = src[i-1]; } diff --git a/LibOVR/Src/Kernel/OVR_DebugHelp.cpp b/LibOVR/Src/Kernel/OVR_DebugHelp.cpp new file mode 100644 index 0000000..fe7b54f --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_DebugHelp.cpp @@ -0,0 +1,3926 @@ +/************************************************************************************ + +Filename : ExceptionHandler.cpp +Content : Platform-independent exception handling interface +Created : October 6, 2014 + +Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +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_DebugHelp.h" +#include "OVR_Types.h" +#include "OVR_UTF8Util.h" +#include "../OVR_CAPI.h" +#include "../OVR_CAPI_Keys.h" +#include "../CAPI/CAPI_HMDState.h" +#include <stdlib.h> + +#if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) + #pragma warning(push, 0) + #include <Windows.h> + #include <WinNT.h> + #include <DbgHelp.h> + #include <WinVer.h> + #include <share.h> + #include <Psapi.h> + #include <TlHelp32.h> + #include <comutil.h> + #include <Wbemcli.h> + #include <Wbemidl.h> + #include <ShlObj.h> + #include <ObjBase.h> + #pragma warning(pop) + + #pragma comment(lib, "Psapi.lib") // To consider: It may be a problem to statically link to these libraries if the application at runtime intends to dynamically + #pragma comment(lib, "ole32.lib") // link to a different version of the same library, and we are statically linked into that application instead of being a DLL. + #pragma comment(lib, "shell32.lib") + + // NtQueryInformation and THREAD_BASIC_INFORMATION are undocumented but frequently needed for digging into thread information. + typedef LONG (WINAPI *NtQueryInformationThreadFunc)(HANDLE, int, PVOID, ULONG, PULONG); + + struct THREAD_BASIC_INFORMATION + { + LONG ExitStatus; + PVOID TebBaseAddress; + PVOID UniqueProcessId; + PVOID UniqueThreadId; + PVOID Priority; + PVOID BasePriority; + }; + + #ifndef UNW_FLAG_NHANDLER // Older Windows SDKs don't support this. + #define UNW_FLAG_NHANDLER 0 + #endif + +#elif defined(OVR_OS_MAC) + #include <unistd.h> + #include <sys/sysctl.h> + #include <sys/utsname.h> + #include <sys/types.h> + #include <sys/mman.h> + #include <stdlib.h> + #include <stdio.h> + #include <pthread.h> + #include <mach/mach.h> + #include <mach/mach_error.h> + #include <mach/thread_status.h> + #include <mach/exception.h> + #include <mach/task.h> + #include <mach/thread_act.h> + #include <mach-o/dyld.h> + #include <mach-o/dyld_images.h> + #include <libproc.h> + #include <libgen.h> + #include <execinfo.h> + #include <cxxabi.h> + #include "OVR_mach_exc_OSX.h" + + #if defined(__LP64__) + typedef struct mach_header_64 MachHeader; + typedef struct segment_command_64 SegmentCommand; + typedef struct section_64 Section; + #define kLCSegment LC_SEGMENT_64 + #else + typedef struct mach_header MachHeader; + typedef struct segment_command SegmentCommand; + typedef struct section Section; + #define kLCSegment LC_SEGMENT + #endif + + extern "C" const struct dyld_all_image_infos* _dyld_get_all_image_infos(); // From libdyld.dylib + +#elif defined(OVR_OS_UNIX) + #include <unistd.h> + #include <sys/sysctl.h> + #include <sys/utsname.h> + #include <sys/types.h> + #include <sys/ptrace.h> + #include <sys/wait.h> + #include <sys/mman.h> + #include <stdlib.h> + #include <stdio.h> + #include <pthread.h> + #include <libgen.h> + #include <execinfo.h> + #include <cxxabi.h> + //#include <libunwind.h> // Can't use this until we can ensure that we have an installed version of it. +#endif + +#if !defined(MIN) + #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) + #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) +#endif + + +OVR_DISABLE_MSVC_WARNING(4351) // new behavior: elements of array will be default initialized +OVR_DISABLE_MSVC_WARNING(4996) // This function or variable may be unsafe + + + + +#if defined(OVR_OS_APPLE) + static OVR::ExceptionHandler* sExceptionHandler = nullptr; + const uint32_t sMachCancelMessageType = 0x0ca9ce11; // This is a made-up value of our own choice. + + extern "C" + { + kern_return_t catch_mach_exception_raise_OVR(mach_port_t /*exceptionPort*/, mach_port_t /*threadSysId*/, + mach_port_t /*machTask*/, exception_type_t /*machExceptionType*/, + mach_exception_data_t /*machExceptionData*/, mach_msg_type_number_t /*machExceptionDataCount*/) + { + return KERN_FAILURE; + } + + kern_return_t catch_mach_exception_raise_state_OVR(mach_port_t /*exceptionPort*/, exception_type_t /*exceptionType*/, + const mach_exception_data_t /*machExceptionData*/, mach_msg_type_number_t /*machExceptionDataCount*/, + int* /*pMachExceptionFlavor*/, const thread_state_t /*threadStatePrev*/, mach_msg_type_number_t /*threaStatePrevCount*/, + thread_state_t /*threadStateNew*/, mach_msg_type_number_t* /*pThreadStateNewCount*/) + { + return KERN_FAILURE; + } + + kern_return_t catch_mach_exception_raise_state_identity_OVR(mach_port_t exceptionPort, mach_port_t threadSysId, mach_port_t machTask, + exception_type_t exceptionType, mach_exception_data_type_t* machExceptionData, + mach_msg_type_number_t machExceptionDataCount, int* pMachExceptionFlavor, + thread_state_t threadStatePrev, mach_msg_type_number_t threadStatePrevCount, + thread_state_t threadStateNew, mach_msg_type_number_t* pThreadStateNewCount) + { + return sExceptionHandler->HandleMachException(exceptionPort, threadSysId, machTask, exceptionType, machExceptionData, + machExceptionDataCount, pMachExceptionFlavor, threadStatePrev, threadStatePrevCount, + threadStateNew, pThreadStateNewCount); + } + + void* MachHandlerThreadFunctionStatic(void* pExceptionHandlerVoid) + { + return static_cast<OVR::ExceptionHandler*>(pExceptionHandlerVoid)->MachHandlerThreadFunction(); + } + + } // extern "C" +#endif + + + + +namespace OVR { + + +void GetInstructionPointer(void*& pInstruction) +{ + #if defined(OVR_CC_MSVC) + pInstruction = _ReturnAddress(); + #else // GCC, clang + pInstruction = __builtin_return_address(0); + #endif +} + + +static size_t SprintfAddress(char* threadHandleStr, size_t threadHandleStrCapacity, const void* pAddress) +{ + #if defined(OVR_CC_MSVC) + #if (OVR_PTR_SIZE >= 8) + return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "0x%016I64x", pAddress); // e.g. 0x0123456789abcdef + #else + return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "0x%08x", pAddress); // e.g. 0x89abcdef + #endif + #else + #if (OVR_PTR_SIZE >= 8) + return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "%016llx", pAddress); // e.g. 0x0123456789abcdef + #else + return OVR_snprintf(threadHandleStr, threadHandleStrCapacity, "%08x", pAddress); // e.g. 0x89abcdef + #endif + #endif +} + + +static size_t SprintfThreadHandle(char* threadHandleStr, size_t threadHandleStrCapacity, const ThreadHandle& threadHandle) +{ + return SprintfAddress(threadHandleStr, threadHandleStrCapacity, threadHandle); +} + + +static size_t SprintfThreadSysId(char* threadSysIdStr, size_t threadSysIdStrCapacity, const ThreadSysId& threadSysId) +{ + #if defined(OVR_CC_MSVC) // Somebody could conceivably use VC++ with a different standard library that supports %ll. And VS2012+ also support %ll. + return OVR_snprintf(threadSysIdStr, threadSysIdStrCapacity, "%I64u", (uint64_t)threadSysId); + #else + return OVR_snprintf(threadSysIdStr, threadSysIdStrCapacity, "%llu", (uint64_t)threadSysId); + #endif +} + + + + + +void GetThreadStackBounds(void*& pStackBase, void*& pStackLimit, ThreadHandle threadHandle) +{ + #if defined(OVR_OS_WIN64) || defined(OVR_OS_WIN32) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE)) + ThreadSysId threadSysIdCurrent = (ThreadSysId)GetCurrentThreadId(); + ThreadSysId threadSysId; + NT_TIB* pTIB = nullptr; + + if(threadHandle == OVR_THREADHANDLE_INVALID) + threadSysId = threadSysIdCurrent; + else + threadSysId = ConvertThreadHandleToThreadSysId(threadHandle); + + if(threadSysId == threadSysIdCurrent) + { + #if (OVR_PTR_SIZE == 4) + // Need to use __asm__("movl %%fs:0x18, %0" : "=r" (pTIB) : : ); under gcc/clang. + __asm { + mov eax, fs:[18h] + mov pTIB, eax + } + #else + pTIB = (NT_TIB*)NtCurrentTeb(); + #endif + } + else + { + #if (OVR_PTR_SIZE == 4) + // It turns out we don't need to suspend the thread when getting SegFs/SegGS, as that's + // constant per thread and doesn't require the thread to be suspended. + //SuspendThread((HANDLE)threadHandle); + CONTEXT context; + memset(&context, 0, sizeof(context)); + context.ContextFlags = CONTEXT_SEGMENTS; + GetThreadContext((HANDLE)threadHandle, &context); // Requires THREAD_QUERY_INFORMATION privileges. + + LDT_ENTRY ldtEntry; + if(GetThreadSelectorEntry(threadHandle, context.SegFs, &ldtEntry)) // Requires THREAD_QUERY_INFORMATION + pTIB = (NT_TIB*)((ldtEntry.HighWord.Bits.BaseHi << 24 ) | (ldtEntry.HighWord.Bits.BaseMid << 16) | ldtEntry.BaseLow); + + //ResumeThread((HANDLE)threadHandle); + #else + // We cannot use GetThreadSelectorEntry or Wow64GetThreadSelectorEntry on Win64. + // We need to read the SegGs qword at offset 0x30. We can't use pTIB = (NT_TIB*)__readgsqword(0x30) because that reads only the current setGs offset. + // mov rax, qword ptr gs:[30h] + // mov qword ptr [pTIB],rax + // In the meantime we rely on the NtQueryInformationThread function. + + static NtQueryInformationThreadFunc spNtQueryInformationThread = nullptr; + + if(!spNtQueryInformationThread) + { + HMODULE hNTDLL = GetModuleHandleA("ntdll.dll"); + spNtQueryInformationThread = (NtQueryInformationThreadFunc)(uintptr_t)GetProcAddress(hNTDLL, "NtQueryInformationThread"); + } + + if(spNtQueryInformationThread) + { + THREAD_BASIC_INFORMATION tbi; + + memset(&tbi, 0, sizeof(tbi)); + LONG result = spNtQueryInformationThread(threadHandle, 0, &tbi, sizeof(tbi), nullptr); // Requires THREAD_QUERY_INFORMATION privileges + if(result == 0) + pTIB = (NT_TIB*)tbi.TebBaseAddress; + } + #endif + } + + if(pTIB) + { + pStackBase = (void*)pTIB->StackBase; + pStackLimit = (void*)pTIB->StackLimit; + } + else + { + pStackBase = nullptr; + pStackLimit = nullptr; + } + + #elif defined(OVR_OS_APPLE) + if(!threadHandle) + threadHandle = pthread_self(); + + pStackBase = pthread_get_stackaddr_np((pthread_t)threadHandle); + size_t stackSize = pthread_get_stacksize_np((pthread_t)threadHandle); + pStackLimit = (void*)((size_t)pStackBase - stackSize); + + #elif defined(OVR_OS_UNIX) + pStackBase = nullptr; + pStackLimit = nullptr; + + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + + #if defined(OVR_OS_LINUX) + int result = pthread_getattr_np((pthread_t)threadHandle, &threadAttr); + #else + int result = pthread_attr_get_np((pthread_t)threadHandle, &threadAttr); + #endif + + if(result == 0) + { + size_t stackSize = 0; + result = pthread_attr_getstack(&threadAttr, &pStackLimit, &stackSize); + + if(result == 0) + pStackBase = (void*)((uintptr_t)pStackLimit + stackSize); // We assume the stack grows downward. + } + + #endif +} + + +bool OVRIsDebuggerPresent() +{ + #if defined(OVR_OS_MS) + return ::IsDebuggerPresent() != 0; + + #elif defined(OVR_OS_APPLE) + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; + struct kinfo_proc info; + size_t size = sizeof(info); + + info.kp_proc.p_flag = 0; + sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0); + + return ((info.kp_proc.p_flag & P_TRACED) != 0); + + #elif (defined(OVR_OS_LINUX) || defined(OVR_OS_BSD)) && !defined(OVR_OS_ANDROID) + // This works better than the PT_TRACE_ME approach. + // However, it presents a problem: + // http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html + // When the application calls fork() from a signal handler and any of the + // fork handlers registered by pthread_atfork() calls a function that is + // not asynch-signal-safe, the behavior is undefined. + // We may need to provide two pathways within this function, one of which + // doesn't fork and instead uses PT_TRACE_ME. + int pid = fork(); + int status; + bool present = false; + + if (pid == -1) // If fork failed... + { + // perror("fork"); + } + else if (pid == 0) // If we are the child process... + { + int ppid = getppid(); + + #if defined(OVR_OS_LINUX) + if (ptrace(PTRACE_ATTACH, ppid, nullptr, nullptr) == 0) + #else + if (ptrace(PT_ATTACH, ppid, nullptr, nullptr) == 0) + #endif + { + waitpid(ppid, nullptr, 0); + + #if defined(OVR_OS_LINUX) + ptrace(PTRACE_CONT, getppid(), nullptr, nullptr); + ptrace(PTRACE_DETACH, getppid(), nullptr, nullptr); + #else + ptrace(PT_CONTINUE, getppid(), nullptr, nullptr); + ptrace(PT_DETACH, getppid(), nullptr, nullptr); + #endif + } + else + { + // ptrace failed so the debugger is present. + present = true; + } + + exit(present ? 1 : 0); // The WEXITSTATUS call below will read this exit value. + } + else // Else we are the original process. + { + waitpid(pid, &status, 0); + present = WEXITSTATUS(status) ? true : false; // Read the exit value from the child's call to exit. + } + + return present; + + #elif defined(PT_TRACE_ME) && !defined(OVR_OS_ANDROID) + return (ptrace(PT_TRACE_ME, 0, 1, 0) < 0); + + #else + return false; + #endif +} + + +// Exits the process with the given exit code. +void ExitProcess(intptr_t processReturnValue) +{ + exit((int)processReturnValue); +} + + +void* SafeMMapAlloc(size_t size) +{ + #if defined(OVR_OS_MS) + return VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); // size is rounded up to a page. // Returned memory is 0-filled. + + #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + #if !defined(MAP_FAILED) + #define MAP_FAILED ((void*)-1) + #endif + + void* result = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); // Returned memory is 0-filled. + if(result == MAP_FAILED) // mmap returns MAP_FAILED (-1) upon failure. + result = nullptr; + return result; + #endif +} + + +void SafeMMapFree(const void* memory, size_t size) +{ + #if defined(OVR_OS_MS) + OVR_UNUSED(size); + VirtualFree(const_cast<void*>(memory), 0, MEM_RELEASE); + + #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + size_t pageSize = getpagesize(); + size = (((size + (pageSize - 1)) / pageSize) * pageSize); + munmap(const_cast<void*>(memory), size); // Must supply the size to munmap. + #endif +} + + +// Note that we can't just return sizeof(void*) == 8, as we may have the case of a +// 32 bit app running on a 64 bit operating system. +static bool Is64BitOS() +{ + #if (OVR_PTR_SIZE >= 8) + return true; + + #elif defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) + BOOL is64BitOS = FALSE; + bool IsWow64ProcessPresent = (GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process") != nullptr); + return (IsWow64ProcessPresent && IsWow64Process(GetCurrentProcess(), &is64BitOS) && is64BitOS); + + #elif defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) + utsname utsName; + memset(&utsName, 0, sizeof(utsName)); + return (uname(&utsName) == 0) && (strcmp(utsName.machine, "x86_64") == 0); + + #else + return false; + #endif +} + + +// The output will always be 0-terminated. +// Returns the required strlen of the output. +// Returns (size_t)-1 on failure. +size_t SpawnShellCommand(const char* shellCommand, char* output, size_t outputCapacity) +{ + #if defined(OVR_OS_UNIX) || defined(OVR_OS_APPLE) + FILE* pFile = popen(shellCommand, "r"); + + if(pFile) + { + size_t requiredLength = 0; + char buffer[256]; + + while(fgets(buffer, sizeof(buffer), pFile)) // fgets 0-terminates the buffer. + { + size_t length = OVR_strlen(buffer); + requiredLength += length; + + if(outputCapacity) + { + OVR_strlcpy(output, buffer, outputCapacity); + length = MIN(outputCapacity, length); + } + + output += length; + outputCapacity -= length; + } + + pclose(pFile); + return requiredLength; + } + #else + // To do. Properly solving this on Windows requires a bit of code. + OVR_UNUSED(shellCommand); + OVR_UNUSED(output); + OVR_UNUSED(outputCapacity); + #endif + + return (size_t)-1; +} + + +// Retrieves a directory path which ends with a path separator. +// Returns the required strlen of the path. +// Guarantees the presence of the directory upon returning true. +static size_t GetUserDocumentsDirectory(char* directoryPath, size_t directoryPathCapacity) +{ + #if defined(OVR_OS_MS) + wchar_t pathW[MAX_PATH + 1]; // +1 because we append a path separator. + HRESULT hr = SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, SHGFP_TYPE_CURRENT, pathW); + + if(SUCCEEDED(hr)) + { + OVR_UNUSED(directoryPathCapacity); + + intptr_t requiredUTF8Length = OVR::UTF8Util::GetEncodeStringSize(pathW); // Returns required strlen. + if(requiredUTF8Length < MAX_PATH) // We need space for a trailing path separator. + { + OVR::UTF8Util::EncodeString(directoryPath, pathW, -1); + OVR::OVR_strlcat(directoryPath, "\\", directoryPathCapacity); + } + + return (requiredUTF8Length + 1); + } + + #elif defined(OVR_OS_MAC) + // This is the same location that Apple puts its OS-generated .crash files. + const char* home = getenv("HOME"); + size_t requiredStrlen = OVR::OVR_snprintf(directoryPath, directoryPathCapacity, "%s/Library/Logs/DiagnosticReports/", home ? home : "/Users/Shared/Logs/DiagnosticReports/"); + // To do: create the directory if it doesn't already exist. + return requiredStrlen; + + #elif defined(OVR_OS_UNIX) || defined(OVR_OS_MAC) + const char* home = getenv("HOME"); + size_t requiredStrlen = OVR::OVR_snprintf(directoryPath, directoryPathCapacity, "%s/Library/", home ? home : "/Users/Shared/"); + // To do: create the directory if it doesn't already exist. + return requiredStrlen; + #endif + + return 0; +} + + +// Retrieves the name of the given thread. +// To do: Move this to OVR_Threads.h +bool GetThreadName(OVR::ThreadHandle threadHandle, char* threadName, size_t threadNameCapacity) +{ + #if defined(OVR_OS_APPLE) || defined(OVR_OS_LINUX) + int result = pthread_getname_np((pthread_t)threadHandle, threadName, threadNameCapacity); + if(result == 0) + return true; + #else + // This is not currently possible on Windows, as only the debugger stores the thread name. We could potentially use a vectored + // exception handler to catch all thread name exceptions (0x406d1388) and record them in a static list at runtime. To detect + // thread exit we could use WMI Win32_ThreadStopTrace. Maintain a list of thread names between these two events. + OVR_UNUSED(threadHandle); + OVR_UNUSED(threadNameCapacity); + #endif + + if(threadNameCapacity) + threadName[0] = 0; + + return false; +} + + +OVR::ThreadSysId ConvertThreadHandleToThreadSysId(OVR::ThreadHandle threadHandle) +{ + #if defined(OVR_OS_WIN64) + return (OVR::ThreadSysId)::GetThreadId(threadHandle); // Requires THREAD_QUERY_INFORMATION privileges. + + #elif defined(OVR_OS_WIN32) + typedef DWORD (WINAPI *GetThreadIdFunc)(HANDLE); + + static volatile bool sInitialized = false; + static GetThreadIdFunc spGetThreadIdFunc = nullptr; + static NtQueryInformationThreadFunc spNtQueryInformationThread = nullptr; + + if(!sInitialized) + { + HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); + if(hKernel32) + spGetThreadIdFunc = (GetThreadIdFunc)(uintptr_t)GetProcAddress(hKernel32, "GetThreadId"); + + if(!spGetThreadIdFunc) + { + HMODULE hNTDLL = GetModuleHandleA("ntdll.dll"); + + if(hNTDLL) + spNtQueryInformationThread = (NtQueryInformationThreadFunc)(uintptr_t)GetProcAddress(hNTDLL, "NtQueryInformationThread"); + } + + sInitialized = true; + } + + if(spGetThreadIdFunc) + return (OVR::ThreadSysId)spGetThreadIdFunc(threadHandle); + + if(spNtQueryInformationThread) + { + THREAD_BASIC_INFORMATION tbi; + + if(spNtQueryInformationThread(threadHandle, 0, &tbi, sizeof(tbi), nullptr) == 0) + return (OVR::ThreadSysId)tbi.UniqueThreadId; + } + + return OVR_THREADSYSID_INVALID; + + #elif defined(OVR_OS_APPLE) + mach_port_t threadSysId = pthread_mach_thread_np((pthread_t)threadHandle); // OS 10.4 and later. + return (ThreadSysId)threadSysId; + + #elif defined(OVR_OS_LINUX) + + // I believe we can usually (though not portably) intepret the pthread_t as a pointer to a struct whose first member is a lwp id. + OVR_UNUSED(threadHandle); + return OVR_THREADSYSID_INVALID; + + #else + OVR_UNUSED(threadHandle); + return OVR_THREADSYSID_INVALID; + #endif +} + + +OVR::ThreadHandle ConvertThreadSysIdToThreadHandle(OVR::ThreadSysId threadSysId) +{ + #if defined(OVR_OS_MS) + // We currently request the given rights because that's what users of this function typically need it for. Ideally there would + // be a way to specify the requested rights in order to avoid the problem if we need only a subset of them but can't get it. + // The solution we use below to try opening with successively reduced rights will work for our uses here but isn't a good general solution to this. + OVR::ThreadHandle threadHandle = ::OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId); + + if(threadHandle == OVR_THREADHANDLE_INVALID) + { + threadHandle = ::OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId); + + if(threadHandle == OVR_THREADHANDLE_INVALID) + threadHandle = ::OpenThread(THREAD_QUERY_INFORMATION, TRUE, (DWORD)threadSysId); + } + + return threadHandle; + #elif defined(OVR_OS_MAC) + return (ThreadHandle)pthread_from_mach_thread_np((mach_port_t)threadSysId); + #else + return (ThreadHandle)threadSysId; + #endif +} + + +void FreeThreadHandle(OVR::ThreadHandle threadHandle) +{ + #if defined(OVR_OS_MS) + if(threadHandle != OVR_THREADHANDLE_INVALID) + ::CloseHandle(threadHandle); + #else + OVR_UNUSED(threadHandle); + #endif +} + + +OVR::ThreadSysId GetCurrentThreadSysId() +{ + #if defined(OVR_OS_MS) + return ::GetCurrentThreadId(); + #elif defined(OVR_OS_APPLE) + return (ThreadSysId)mach_thread_self(); + #else + return (ThreadSysId)pthread_self(); + #endif +} + + + +static void GetCurrentProcessFilePath(char* appPath, size_t appPathCapacity) +{ + appPath[0] = 0; + + #if defined(OVR_OS_MS) + wchar_t pathW[MAX_PATH]; + GetModuleFileNameW(0, pathW, (DWORD)OVR_ARRAY_COUNT(pathW)); + + size_t requiredUTF8Length = (size_t)OVR::UTF8Util::GetEncodeStringSize(pathW); // Returns required strlen. + + if(requiredUTF8Length < appPathCapacity) + { + OVR::UTF8Util::EncodeString(appPath, pathW, -1); + } + else + { + appPath[0] = 0; + } + + #elif defined(OVR_OS_APPLE) + struct BunderFolder + { + // Returns true if pStr ends with pFind, case insensitively. + // To do: Move OVR_striend to OVRKernel/Std.h + static bool OVR_striend(const char* pStr, const char* pFind, size_t strLength = (size_t)-1, size_t findLength = (size_t)-1) + { + if(strLength == (size_t)-1) + strLength = OVR_strlen(pStr); + if(findLength == (size_t)-1) + findLength = OVR_strlen(pFind); + if(strLength >= findLength) + return (OVR_stricmp(pStr + strLength - findLength, pFind) == 0); + return false; + } + + static bool IsBundleFolder(const char* filePath) + { + // https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/AboutBundles/AboutBundles.html#//apple_ref/doc/uid/10000123i-CH100-SW1 + static const char* extensionArray[] = { ".app", ".bundle", ".framework", ".plugin", ".kext" }; + + for(size_t i = 0; i < OVR_ARRAY_COUNT(extensionArray); i++) + { + if(OVR_striend(filePath, extensionArray[i])) + return true; + } + + return false; + } + }; + + char appPathTemp[PATH_MAX]; + uint32_t appPathTempCapacity32 = PATH_MAX; + size_t requiredStrlen = appPathCapacity; + + if(_NSGetExecutablePath(appPathTemp, &appPathTempCapacity32) == 0) + { + char appPathTempReal[PATH_MAX]; + + if(realpath(appPathTemp, appPathTempReal)) // If the path is a symbolic link, this converts it to the real path. + { + // To consider: Enable reading the internal bundle executable path. An application on Mac may in + // fact be within a file bundle, which is an private file system within a file. With Objective C + // we could use: [[NSWorkspace sharedWorkspace] isFilePackageAtPath:fullPath]; + bool shouldReadTheBunderPath = false; + + if(shouldReadTheBunderPath) + { + // We recursively call dirname() until we find .app/.bundle/.plugin as a directory name. + OVR_strlcpy(appPathTemp, appPathTempReal, OVR_ARRAY_COUNT(appPathTemp)); + bool found = BunderFolder::IsBundleFolder(appPathTemp); + + while(!found && OVR_strcmp(appPathTemp, ".") && OVR_strcmp(appPathTemp, "/")) + { + OVR_strlcpy(appPathTemp, dirname(appPathTemp), OVR_ARRAY_COUNT(appPathTemp)); + found = BunderFolder::IsBundleFolder(appPathTemp); + } + + if(found) // If somewhere above we found a parent bundle container... + requiredStrlen = OVR_strlcpy(appPath, appPathTemp, appPathCapacity); + else + requiredStrlen = OVR_strlcpy(appPath, appPathTempReal, appPathCapacity); + } + else + { + requiredStrlen = OVR_strlcpy(appPath, appPathTempReal, appPathCapacity); + } + } + } + + if(requiredStrlen >= appPathCapacity) + appPath[0] = '\0'; + + #elif defined(OVR_OS_LINUX) + ssize_t length = readlink("/proc/self/exe", appPath, appPathCapacity); + + if((length != -1) && ((size_t)length < (appPathCapacity - 1))) + { + appPath[length] = '\0'; + } + #endif +} + + +static const char* GetFileNameFromPath(const char* filePath) +{ + #if defined(OVR_OS_MS) + const char* lastPathSeparator = max(strrchr(filePath, '\\'), strrchr(filePath, '/')); // Microsoft APIs are inconsistent with respect to allowing / as a path separator. + #else + const char* lastPathSeparator = strrchr(filePath, '/'); + #endif + + if(lastPathSeparator) + return lastPathSeparator + 1; + + return filePath; +} + + + +static void FormatDateTime(char* buffer, size_t bufferCapacity, time_t timeValue, bool getDate, bool getTime, bool localDateTime, bool fileNameSafeCharacters = false) +{ + char temp[128]; + const tm* pTime = localDateTime ? localtime(&timeValue) : gmtime(&timeValue); + + if(bufferCapacity) + buffer[0] = 0; + + if(getDate) + { + const char* format = fileNameSafeCharacters ? "%Y-%m-%d" : "%Y/%m/%d"; + strftime(temp, OVR_ARRAY_COUNT(temp), format, pTime); + OVR::OVR_strlcpy(buffer, temp, bufferCapacity); + } + + if(getTime) + { + const char* format = fileNameSafeCharacters ? " %H.%M.%S" : " %H:%M:%S"; + strftime(temp, OVR_ARRAY_COUNT(temp), (getDate ? format : format + 1), pTime); + OVR::OVR_strlcat(buffer, temp, bufferCapacity); + } +} + + +static void GetOSVersionName(char* versionName, size_t versionNameCapacity) +{ + #if defined(OVR_OS_MS) + const char* name = "unknown"; + + OSVERSIONINFOEXW vi; + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + + if(GetVersionExW((LPOSVERSIONINFOW)&vi)) + { + if(vi.dwMajorVersion >= 7) + { + // Unknown recent version. + } + if(vi.dwMajorVersion >= 6) + { + if(vi.dwMinorVersion >= 4) + name = "Windows 10"; + else if(vi.dwMinorVersion >= 3) + { + if(vi.wProductType == VER_NT_WORKSTATION) + name = "Windows 8.1"; + else + name = "Windows Server 2012 R2"; + } + else if(vi.dwMinorVersion >= 2) + { + if(vi.wProductType == VER_NT_WORKSTATION) + name = "Windows 8"; + else + name = "Windows Server 2012"; + } + else if(vi.dwMinorVersion >= 1) + { + if(vi.wProductType == VER_NT_WORKSTATION) + name = "Windows 7"; + else + name = "Windows Server 2008 R2"; + } + else + { + if(vi.wProductType == VER_NT_WORKSTATION) + name = "Windows Vista"; + else + name = "Windows Server 2008"; + } + } + else if(vi.dwMajorVersion >= 5) + { + if(vi.dwMinorVersion == 0) + name = "Windows 2000"; + else if(vi.dwMinorVersion == 1) + name = "Windows XP"; + else // vi.dwMinorVersion == 2 + { + if(GetSystemMetrics(SM_SERVERR2) != 0) + name = "Windows Server 2003 R2"; + else if(vi.wSuiteMask & VER_SUITE_WH_SERVER) + name = "Windows Home Server"; + if(GetSystemMetrics(SM_SERVERR2) == 0) + name = "Windows Server 2003"; + else + name = "Windows XP Professional x64 Edition"; + } + } + else + name = "Windows 98 or earlier"; + } + + OVR_strlcpy(versionName, name, versionNameCapacity); + + #elif defined(OVR_OS_UNIX) || defined(OVR_OS_APPLE) + utsname utsName; + memset(&utsName, 0, sizeof(utsName)); + + if(uname(&utsName) == 0) + OVR_snprintf(versionName, versionNameCapacity, "%s %s %s %s", utsName.sysname, utsName.release, utsName.version, utsName.machine); + else + OVR_snprintf(versionName, versionNameCapacity, "Unix"); + #endif +} + + + + +void CreateException(CreateExceptionType exceptionType) +{ + char buffer[1024] = {}; + + switch(exceptionType) + { + case kCETAccessViolation: + { + int* pNullPtr = reinterpret_cast<int*>((rand() / 2) / RAND_MAX); + pNullPtr[0] = 0; // This line should generate an exception. + sprintf(buffer, "%p", pNullPtr); + break; + } + + case kCETDivideByZero: + { + int smallValue = 1; + int largeValue = (1000 * exceptionType); + int divByZero = (smallValue / largeValue); // This line should generate a div/0 exception. + sprintf(buffer, "%d", divByZero); + break; + } + + case kCETIllegalInstruction: + { + #if defined(OVR_CPU_X86) || (defined(OVR_CPU_X86_64) && !defined(OVR_CC_MSVC)) // (if x86) or (if x64 and any computer but VC++)... + #if defined(OVR_CC_MSVC) + __asm ud2 + #else // e.g. GCC + asm volatile("ud2"); + #endif + + #elif defined(OVR_CPU_X86_64) && (defined(OVR_OS_MS) && defined(PAGE_EXECUTE_READWRITE)) + // VC++ for x64 doesn't support inline asm. + void* pVoid = _AddressOfReturnAddress(); + void** ppVoid = reinterpret_cast<void**>(pVoid); + void* pReturnAddress = *ppVoid; + DWORD dwProtectPrev = 0; + + if(VirtualProtect(pReturnAddress, 2, PAGE_EXECUTE_READWRITE, &dwProtectPrev)) // If we can set the memory to be executable... + { + // Modify the code we return to. + uint8_t asm_ud2[] = { 0x0f, 0x0b }; + memcpy(pReturnAddress, asm_ud2, sizeof(asm_ud2)); + VirtualProtect(pReturnAddress, 2, dwProtectPrev, &dwProtectPrev); + } + else + { + // To do: Fix this. + } + + #else + // To do: Fix this. + #endif + + break; + } + + case kCETStackCorruption: + { + size_t size = (sizeof(buffer) * 16) - (rand() % 16); + char* pOutsizeStack = buffer - ((sizeof(buffer) * 16) + (rand() % 16)); + + memset(buffer, 0, size); + memset(pOutsizeStack, 0, size); // This line should generate an exception, or an exception will be generated upon return from this function. + break; + } + + case kCETStackOverflow: + { + CreateException(exceptionType); // Call ourselves recursively. This line should generate a div/0 exception. + sprintf(buffer, "%d", exceptionType); + break; + } + + case kCETAlignment: + { + // Not all platforms generate alignment exceptions. Some internally handle it. + void* pAligned = malloc(16); + char* pMisaligned = (char*)pAligned + 1; + uint64_t* pMisaligned64 = reinterpret_cast<uint64_t*>(pMisaligned); + + *pMisaligned64 = 0; // This line should generate an exception. + free(pAligned); + break; + } + + case kCETFPU: + // Platforms usually have FPU exceptions disabled. In order to test FPU exceptions we will need to at least + // temporarily disable them before executing code here to generate such exceptions. + // To do. + break; + + case kCETTrap: + // To do. This is hardware-specific. + break; + } +} + + + + +#if defined(OVR_OS_MS) + typedef BOOL (WINAPI * StackWalk64Type)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + typedef PVOID (WINAPI * SymFunctionTableAccess64Type)(HANDLE hProcess, DWORD64 dwAddr); + typedef DWORD64 (WINAPI * SymGetModuleBase64Type)(HANDLE hProcess, DWORD64 dwAddr); + typedef DWORD (WINAPI * SymSetOptionsType)(DWORD SymOptions); + typedef BOOL (WINAPI * SymInitializeWType)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess); + typedef BOOL (WINAPI * SymCleanupType)(HANDLE hProcess); + typedef DWORD64 (WINAPI * SymLoadModule64Type)(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll); + typedef BOOL (WINAPI * SymFromAddrType)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); + typedef BOOL (WINAPI * SymGetLineFromAddr64Type)(HANDLE hProcess, DWORD64 qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64); + + StackWalk64Type pStackWalk64; + SymFunctionTableAccess64Type pSymFunctionTableAccess64; + SymGetModuleBase64Type pSymGetModuleBase64; + SymSetOptionsType pSymSetOptions; + SymInitializeWType pSymInitializeW; + SymCleanupType pSymCleanup; + SymLoadModule64Type pSymLoadModule64; + SymFromAddrType pSymFromAddr; + SymGetLineFromAddr64Type pSymGetLineFromAddr64; +#endif + + + +SymbolLookup::SymbolLookup() + : initialized(false), + allowMemoryAllocation(true), + moduleListUpdated(false), + moduleInfoArray(), + moduleInfoArraySize(0) +{ +} + +SymbolLookup::~SymbolLookup() +{ + Shutdown(); +} + +void SymbolLookup::AddSourceCodeDirectory(const char* pDirectory) +{ + OVR_UNUSED(pDirectory); +} + +bool SymbolLookup::Initialize() +{ + if(!initialized) + { + #if defined(OVR_OS_MS) + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms679294%28v=vs.85%29.aspx + HANDLE hProcess = GetCurrentProcess(); + HMODULE hDbgHelp = LoadLibraryW(L"DbgHelp.dll"); // It's best if the application supplies a recent version of this. + + if(hDbgHelp) + { + pStackWalk64 = (StackWalk64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "StackWalk64"); + pSymFunctionTableAccess64 = (SymFunctionTableAccess64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymFunctionTableAccess64"); + pSymGetModuleBase64 = (SymGetModuleBase64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymGetModuleBase64"); + pSymSetOptions = (SymSetOptionsType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymSetOptions"); + pSymInitializeW = (SymInitializeWType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymInitializeW"); + pSymCleanup = (SymCleanupType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymCleanup"); + pSymLoadModule64 = (SymLoadModule64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymLoadModule64"); + pSymFromAddr = (SymFromAddrType)(uintptr_t)::GetProcAddress(hDbgHelp, "SymFromAddr"); + pSymGetLineFromAddr64 = (SymGetLineFromAddr64Type)(uintptr_t)::GetProcAddress(hDbgHelp, "SymGetLineFromAddr64"); + } + + pSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + + // To consider: Use a manually created search path: + // wchar_t searchPathW[4096]; // Semicolon-separated strings. + // The current working directory of the application. + // The directory of the application itself (GetModuleFileName). + // The _NT_SYMBOL_PATH environment variable. + // The _NT_ALTERNATE_SYMBOL_PATH environment variable. + + if(pSymInitializeW(hProcess, nullptr /*searchPathW*/, FALSE)) + { + initialized = true; + } + #endif + } + + return true; +} + +void SymbolLookup::Shutdown() +{ + if(initialized) + { + initialized = false; + + #if defined(OVR_OS_MS) + HANDLE hProcess = GetCurrentProcess(); + + // SymCleanup should handle this for us. + //if(moduleListUpdated) + //{ + // for(size_t i = 0; i < moduleInfoArraySize; i++) + // pSymUnloadModule64(hProcess, moduleInfoArray[i].baseAddress); + //} + + moduleInfoArraySize = 0; + + pSymCleanup(hProcess); + #endif + } +} + + +void SymbolLookup::EnableMemoryAllocation(bool enabled) +{ + allowMemoryAllocation = enabled; +} + + +OVR_DISABLE_MSVC_WARNING(4740) // flow in or out of inline asm code suppresses global optimization +OVR_DISABLE_MSVC_WARNING(4748) // /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function + + +size_t SymbolLookup::GetBacktrace(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, void* platformThreadContext, OVR::ThreadSysId threadSysIdHelp) +{ + #if defined(OVR_OS_WIN64) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE)) + OVR_UNUSED(threadSysIdHelp); + + if(platformThreadContext == nullptr) + return RtlCaptureStackBackTrace(1, (ULONG)addressArrayCapacity, addressArray, nullptr); + + // We need to get the call stack of another thread. + size_t frameIndex = 0; + CONTEXT context; + PRUNTIME_FUNCTION pRuntimeFunction; + ULONG64 imageBase = 0; + ULONG64 imageBasePrev = 0; + + memcpy(&context, (CONTEXT*)platformThreadContext, sizeof(CONTEXT)); + context.ContextFlags = CONTEXT_CONTROL; + + if(context.Rip && (frameIndex < addressArrayCapacity)) + addressArray[frameIndex++] = (void*)(uintptr_t)context.Rip; + + while(context.Rip && (frameIndex < addressArrayCapacity)) + { + imageBasePrev = imageBase; + pRuntimeFunction = (PRUNTIME_FUNCTION)RtlLookupFunctionEntry(context.Rip, &imageBase, nullptr); + + if(pRuntimeFunction) + { + VOID* handlerData = nullptr; + ULONG64 establisherFramePointers[2] = { 0, 0 }; + RtlVirtualUnwind(UNW_FLAG_NHANDLER, imageBase, context.Rip, pRuntimeFunction, &context, &handlerData, establisherFramePointers, nullptr); + } + else + { + context.Rip = (ULONG64)(*(PULONG64)context.Rsp); + context.Rsp += 8; + } + + if(context.Rip && (frameIndex < addressArrayCapacity)) + { + if(skipCount) + --skipCount; + else + addressArray[frameIndex++] = (void*)(uintptr_t)context.Rip; + } + } + + return frameIndex; + + #elif defined(OVR_OS_WIN32) + OVR_UNUSED(threadSysIdHelp); + + size_t frameIndex = 0; + + if(pStackWalk64) + { + CONTEXT context; + + if(platformThreadContext) + { + memcpy(&context, platformThreadContext, sizeof(context)); + context.ContextFlags = CONTEXT_CONTROL; + } + else + { + memset(&context, 0, sizeof(context)); + context.ContextFlags = CONTEXT_CONTROL; + + __asm { + mov context.Ebp, EBP + mov context.Esp, ESP + call GetEIP + GetEIP: + pop context.Eip + } + } + + STACKFRAME64 sf; + memset(&sf, 0, sizeof(sf)); + sf.AddrPC.Offset = context.Eip; + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Offset = context.Esp; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Offset = context.Ebp; + sf.AddrFrame.Mode = AddrModeFlat; + + const HANDLE hCurrentProcess = ::GetCurrentProcess(); + const HANDLE hCurrentThread = ::GetCurrentThread(); + + if(!platformThreadContext) // If we are reading the current thread's call stack then we ignore this current function. + skipCount++; + + while(frameIndex < addressArrayCapacity) + { + if(!pStackWalk64(IMAGE_FILE_MACHINE_I386, hCurrentProcess, hCurrentThread, &sf, &context, nullptr, pSymFunctionTableAccess64, pSymGetModuleBase64, nullptr)) + break; + + if(sf.AddrFrame.Offset == 0) + break; + + if(skipCount) + --skipCount; + else + addressArray[frameIndex++] = ((void*)(uintptr_t)sf.AddrPC.Offset); + } + } + + return frameIndex; + + #elif defined(OVR_OS_APPLE) + struct StackFrame + { + StackFrame* pParentStackFrame; + void* pReturnPC; + }; + + void* pInstruction; + StackFrame* pStackFrame; + size_t frameIndex = 0; + + if(platformThreadContext) + { + #if defined(OVR_CPU_ARM) + arm_thread_state_t* pThreadState = (arm_thread_state_t*)platformThreadContext; + pStackFrame = (StackFrame*)pThreadState->__fp; + pInstruction = (void*) pThreadState->__pc; + #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0x1) == 0) + #elif defined(OVR_CPU_X86_64) + x86_thread_state_t* pThreadState = (x86_thread_state_t*)platformThreadContext; + pInstruction = (void*) pThreadState->uts.ts64.__rip; + pStackFrame = (StackFrame*)pThreadState->uts.ts64.__rbp; + #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0xf) == 0) + #elif defined(OVR_CPU_X86) + x86_thread_state_t* pThreadState = (x86_thread_state_t*)platformThreadContext; + pInstruction = (void*) pThreadState->uts.ts32.__eip; + pStackFrame = (StackFrame*)pThreadState->uts.ts32.__ebp; + #define FrameIsAligned(pStackFrame) ((((uintptr_t)pStackFrame) & 0xf) == 8) + #endif + + if(frameIndex < addressArrayCapacity) + addressArray[frameIndex++] = pInstruction; + } + else // Else get the current values... + { + pStackFrame = (StackFrame*)__builtin_frame_address(0); + GetInstructionPointer(pInstruction); + } + + pthread_t threadSelf = pthread_self(); + void* pCurrentStackBase = pthread_get_stackaddr_np(threadSelf); + void* pCurrentStackLimit = (void*)((uintptr_t)pCurrentStackBase - pthread_get_stacksize_np(threadSelf)); + bool threadIsCurrent = (platformThreadContext == nullptr) || (((void*)pStackFrame > pCurrentStackLimit) && ((void*)pStackFrame <= pCurrentStackBase)); + StackFrame* pStackBase; + StackFrame* pStackLimit; + + if(threadIsCurrent) + { + pStackBase = (StackFrame*)pCurrentStackBase; + pStackLimit = (StackFrame*)pCurrentStackLimit; + } + else if(threadSysIdHelp) + { + pthread_t threadHandle = pthread_from_mach_thread_np((mach_port_t)threadSysIdHelp); + pStackBase = (StackFrame*)pthread_get_stackaddr_np(threadHandle); + pStackLimit = (StackFrame*)((uintptr_t)pStackBase - pthread_get_stacksize_np(threadHandle)); + } + else + { // We guess what the limits are. + pStackBase = pStackFrame + ((384 * 1024) / sizeof(StackFrame)); + pStackLimit = pStackFrame - ((384 * 1024) / sizeof(StackFrame)); + } + + if((frameIndex < addressArrayCapacity) && pStackFrame && FrameIsAligned(pStackFrame)) + { + addressArray[frameIndex++] = pStackFrame->pReturnPC; + + while(pStackFrame && pStackFrame->pReturnPC && (frameIndex < addressArrayCapacity)) + { + pStackFrame = pStackFrame->pParentStackFrame; + + if(pStackFrame && FrameIsAligned(pStackFrame) && pStackFrame->pReturnPC && (pStackFrame > pStackLimit) && (pStackFrame < pStackBase)) + { + if(skipCount) + --skipCount; + else + addressArray[frameIndex++] = pStackFrame->pReturnPC; + } + else + break; + } + } + + return frameIndex; + + #elif defined(OVR_OS_LINUX) && (defined( __LIBUNWIND__) || defined(LIBUNWIND_AVAIL)) + // Libunwind-based solution. Requires installation of libunwind package. + // Libunwind isn't always safe for threads that are in signal handlers. + // An approach to get the callstack of another thread is to use signal injection into the target thread. + + OVR_UNUSED(platformThreadContext); + OVR_UNUSED(threadSysIdHelp); + + size_t frameIndex = 0; + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t ip, sp; + + unw_getcontext(&uc); // This gets the current thread's context. We could alternatively initialize another thread's context with it. + unw_init_local(&cursor, &uc); + + while((unw_step(&cursor) > 0) && (frameIndex < addressArrayCapacity)) + { + // We can get the function name here too on some platforms with unw_get_proc_info() and unw_get_proc_name(). + + if(skipCount) + --skipCount; + else + { + unw_get_reg(&cursor, UNW_REG_IP, &ip); + addressArray[frameIndex++] = (void*)ip; + } + } + + return frameIndex; + #else + OVR_UNUSED(addressArray); + OVR_UNUSED(addressArrayCapacity); + OVR_UNUSED(skipCount); + OVR_UNUSED(platformThreadContext); + OVR_UNUSED(threadSysIdHelp); + + return 0; + #endif +} + + +size_t SymbolLookup::GetBacktraceFromThreadHandle(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, OVR::ThreadHandle threadHandle) +{ + #if defined(OVR_OS_MS) + size_t count = 0; + DWORD threadSysId = (DWORD)ConvertThreadHandleToThreadSysId(threadHandle); + + // Compare to 0, compare to the self 'pseudohandle' and compare to the self id. + if((threadHandle == OVR_THREADHANDLE_INVALID) || (threadHandle == ::GetCurrentThread()) || (threadSysId == ::GetCurrentThreadId())) // If threadSysId refers to the current thread... + return GetBacktrace(addressArray, addressArrayCapacity, skipCount, nullptr); + + // We are working with another thread. We need to suspend it and get its CONTEXT. + // Suspending other threads is risky, as they may be in some state that cannot be safely blocked. + BOOL result = false; + DWORD suspendResult = ::SuspendThread(threadHandle); // Requires that the handle have THREAD_SUSPEND_RESUME rights. + + if(suspendResult != (DWORD)-1) // Returns previous suspend count, or -1 if failed. + { + CONTEXT context; + context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; // Requires that the handle have THREAD_GET_CONTEXT rights. + result = ::GetThreadContext(threadHandle, &context); + count = GetBacktrace(addressArray, addressArrayCapacity, skipCount, &context); + suspendResult = ::ResumeThread(threadHandle); + OVR_ASSERT_AND_UNUSED(suspendResult != (DWORD)-1, suspendResult); + } + + return count; + + #elif defined(OVR_OS_APPLE) + mach_port_t threadSysID = pthread_mach_thread_np((pthread_t)threadHandle); // Convert pthread_t to mach thread id. + return GetBacktraceFromThreadSysId(addressArray, addressArrayCapacity, skipCount, (OVR::ThreadSysId)threadSysID); + + #elif defined(OVR_OS_LINUX) + // To do. + OVR_UNUSED(addressArray); + OVR_UNUSED(addressArrayCapacity); + OVR_UNUSED(skipCount); + OVR_UNUSED(threadHandle); + return 0; + #endif +} + + +size_t SymbolLookup::GetBacktraceFromThreadSysId(void* addressArray[], size_t addressArrayCapacity, size_t skipCount, OVR::ThreadSysId threadSysId) +{ + #if defined(OVR_OS_MS) + OVR::ThreadHandle threadHandle = ConvertThreadSysIdToThreadHandle(threadSysId); + if(threadHandle) + { + size_t count = GetBacktraceFromThreadHandle(addressArray, addressArrayCapacity, skipCount, threadHandle); + FreeThreadHandle(threadHandle); + return count; + } + return 0; + + #elif defined(OVR_OS_APPLE) + mach_port_t threadCurrent = pthread_mach_thread_np(pthread_self()); + mach_port_t thread = (mach_port_t)threadSysId; + + if(thread == threadCurrent) + { + return GetBacktrace(addressArray, addressArrayCapacity, skipCount, nullptr); + } + else + { + kern_return_t result = thread_suspend(thread); // Do we need to do this if it's an thread who exception is being handled? + size_t count = 0; + + if(result == KERN_SUCCESS) + { + #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + x86_thread_state_t threadState; + #elif defined(OVR_CPU_ARM) + arm_thread_state_t threadState; + #endif + mach_msg_type_number_t stateCount = MACHINE_THREAD_STATE_COUNT; + + result = thread_get_state(thread, MACHINE_THREAD_STATE, (natural_t*)(uintptr_t)&threadState, &stateCount); + + if(result == KERN_SUCCESS) + count = GetBacktrace(addressArray, addressArrayCapacity, skipCount, &threadState, threadSysId); + + thread_resume(thread); + + return count; + } + } + + return 0; + + #elif defined(OVR_OS_LINUX) + // To do. + OVR_UNUSED(addressArray); + OVR_UNUSED(addressArrayCapacity); + OVR_UNUSED(skipCount); + OVR_UNUSED(threadSysId); + return 0; + #endif +} + + +// We need to return the required moduleInfoArrayCapacity. +size_t SymbolLookup::GetModuleInfoArray(ModuleInfo* pModuleInfoArray, size_t moduleInfoArrayCapacity) +{ + #if defined(OVR_OS_MS) + size_t moduleCountRequired = 0; // The count we would copy to pModuleInfoArray if moduleInfoArrayCapacity was enough. + size_t moduleCount = 0; // The count we actually copy to pModuleInfoArray. Will be <= moduleInfoArrayCapacity. + HANDLE hProcess = GetCurrentProcess(); + HMODULE hModuleArray[200]; + DWORD cbNeeded = 0; + MODULEINFO mi; + + if(EnumProcessModules(hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded)) + { + moduleCountRequired = ((cbNeeded / sizeof(HMODULE)) < OVR_ARRAY_COUNT(hModuleArray)) ? (cbNeeded / sizeof(HMODULE)) : OVR_ARRAY_COUNT(hModuleArray); + moduleCount = MIN(moduleCountRequired, OVR_ARRAY_COUNT(hModuleArray)); + moduleCount = MIN(moduleCount, moduleInfoArrayCapacity); + + for(size_t i = 0; i < moduleCount; i++) + { + ModuleInfo& moduleInfo = pModuleInfoArray[i]; + + memset(&mi, 0, sizeof(mi)); + BOOL result = GetModuleInformation(hProcess, hModuleArray[i], &mi, sizeof(mi)); + + if(result) + { + wchar_t pathW[MAX_PATH]; + char pathA[MAX_PATH * 3]; // *3 to handle UTF8 multibyte encoding. + + moduleInfo.handle = hModuleArray[i]; + moduleInfo.baseAddress = (uintptr_t)mi.lpBaseOfDll; + moduleInfo.size = mi.SizeOfImage; + + GetModuleFileNameW(hModuleArray[i], pathW, OVR_ARRAY_COUNT(pathW)); + OVR::UTF8Util::EncodeString(pathA, pathW, -1); // Problem: DecodeString provides no way to specify the destination capacity. + OVR::OVR_strlcpy(moduleInfo.filePath, pathA, OVR_ARRAY_COUNT(moduleInfo.filePath)); + + const char* fileName = GetFileNameFromPath(pathA); + OVR::OVR_strlcpy(moduleInfo.name, fileName, OVR_ARRAY_COUNT(moduleInfo.name)); + } + else + { + moduleInfo.handle = 0; + moduleInfo.baseAddress = 0; + moduleInfo.size = 0; + moduleInfo.filePath[0] = 0; + moduleInfo.name[0] = 0; + } + } + } + + return moduleCountRequired; + + #elif defined(OVR_OS_MAC) + size_t moduleCountRequired = 0; + size_t moduleCount = 0; + + struct MacModuleInfo // This struct exists solely so we can have a local function within this function.. + { + static void AddMacModuleInfo(ModuleInfo* pModuleInfoArrayL, size_t& moduleCountRequiredL, size_t& moduleCountL, size_t moduleInfoArrayCapacityL, + const char* pTypeFilterL, const char* pModulePath, uintptr_t currentSegmentPos, const MachHeader* pMachHeader, uint64_t offset) + { + for(size_t i = 0; i < pMachHeader->ncmds; i++) + { + const SegmentCommand* pSegmentCommand = reinterpret_cast<const SegmentCommand*>(currentSegmentPos); + + if(pSegmentCommand->cmd == kLCSegment) + { + const size_t segnameSize = (sizeof(pSegmentCommand->segname) + 1); // +1 so we can have a trailing '\0'. + char segname[segnameSize]; + + memcpy(segname, pSegmentCommand->segname, sizeof(pSegmentCommand->segname)); + segname[segnameSize - 1] = '\0'; + + if(!pTypeFilterL || OVR_strncmp(segname, pTypeFilterL, sizeof(segname))) + { + moduleCountRequiredL++; + + if(moduleCountL < moduleInfoArrayCapacityL) + { + ModuleInfo& info = pModuleInfoArrayL[moduleCountL++]; + + info.baseAddress = (uint64_t)(pSegmentCommand->vmaddr + offset); + info.handle = reinterpret_cast<ModuleHandle>((uintptr_t)info.baseAddress); + info.size = (uint64_t)pSegmentCommand->vmsize; + OVR_strlcpy(info.filePath, pModulePath, OVR_ARRAY_COUNT(info.filePath)); + OVR_strlcpy(info.name, GetFileNameFromPath(pModulePath), OVR_ARRAY_COUNT(info.name)); + + info.permissions[0] = (pSegmentCommand->initprot & VM_PROT_READ) ? 'r' : '-'; + info.permissions[1] = (pSegmentCommand->initprot & VM_PROT_WRITE) ? 'w' : '-'; + info.permissions[2] = (pSegmentCommand->initprot & VM_PROT_EXECUTE) ? 'x' : '-'; + info.permissions[3] = '/'; + info.permissions[4] = (pSegmentCommand->maxprot & VM_PROT_READ) ? 'r' : '-'; + info.permissions[5] = (pSegmentCommand->maxprot & VM_PROT_WRITE) ? 'w' : '-'; + info.permissions[6] = (pSegmentCommand->maxprot & VM_PROT_EXECUTE) ? 'x' : '-'; + info.permissions[7] = '\0'; + + OVR_strlcpy(info.type, pSegmentCommand->segname, OVR_ARRAY_COUNT(info.type)); + } + } + } + + currentSegmentPos += pSegmentCommand->cmdsize; + } + } + }; + + // Iterate dyld_all_image_infos->infoArray + const struct dyld_all_image_infos* pAllImageInfos = _dyld_get_all_image_infos(); + + for(uint32_t i = 0; i < pAllImageInfos->infoArrayCount; i++) + { + const char* pModulePath = pAllImageInfos->infoArray[i].imageFilePath; + + if(pModulePath && *pModulePath) + { + uintptr_t currentSegmentPos = (uintptr_t)pAllImageInfos->infoArray[i].imageLoadAddress; + const MachHeader* pMachHeader = reinterpret_cast<const MachHeader*>(currentSegmentPos); + uint64_t offset = (uint64_t)_dyld_get_image_vmaddr_slide(i); + + currentSegmentPos += sizeof(*pMachHeader); + + MacModuleInfo::AddMacModuleInfo(pModuleInfoArray, moduleCountRequired, moduleCount, moduleInfoArrayCapacity, + nullptr /*"__TEXT"*/, pModulePath, currentSegmentPos, pMachHeader, offset); + } + } + + // In addition to iterating dyld_all_image_infos->infoArray we need to also iterate /usr/lib/dyld entries. + const MachHeader* pMachHeader = (const MachHeader*)pAllImageInfos->dyldImageLoadAddress; + uintptr_t currentSegmentPos = (uintptr_t)pMachHeader + sizeof(*pMachHeader); + char modulePath[OVR_MAX_PATH] = ""; + pid_t pid = getpid(); + int filenameLen = proc_regionfilename((int)pid, currentSegmentPos, modulePath, (uint32_t)sizeof(modulePath)); + + if(filenameLen > 0) + MacModuleInfo::AddMacModuleInfo(pModuleInfoArray, moduleCountRequired, moduleCount, moduleInfoArrayCapacity, + "__TEXT", modulePath, currentSegmentPos, pMachHeader, 0); + + return moduleCountRequired; + + #elif defined(EA_PLATFORM_LINUX) + // One approach is to read /proc/self/maps, which is supported by Linux (though not BSD). + // Linux glibc dladdr() can tell us what module an arbitrary function address comes from, but can't tell us the list of modules. + OVR_UNUSED(pModuleInfoArray); + OVR_UNUSED(moduleInfoArrayCapacity); + return 0; + + #else + OVR_UNUSED(pModuleInfoArray); + OVR_UNUSED(moduleInfoArrayCapacity); + return 0; + #endif +} + + +size_t SymbolLookup::GetThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCapacity) +{ + size_t countRequired = 0; + size_t count = 0; + + #if defined(OVR_OS_MS) + // Print a list of threads. + DWORD currentProcessId = GetCurrentProcessId(); + HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, currentProcessId); // ICreateToolhelp32Snapshot actually ignores currentProcessId. + + if(hThreadSnap != INVALID_HANDLE_VALUE) + { + THREADENTRY32 te32; + te32.dwSize = sizeof(THREADENTRY32); + + if(Thread32First(hThreadSnap, &te32)) + { + do + { + if(te32.th32OwnerProcessID == currentProcessId) + { + HANDLE hThread = ConvertThreadSysIdToThreadHandle(te32.th32ThreadID); + + if(hThread) + { + ++countRequired; + + if((threadHandleArray || threadSysIdArray) && (count < threadArrayCapacity)) + { + if(threadHandleArray) + threadHandleArray[count] = hThread; // The caller must call CloseHandle on this thread, or call DoneThreadList on the returned array. + if(threadSysIdArray) + threadSysIdArray[count] = ConvertThreadHandleToThreadSysId(hThread); + ++count; + } + + if(!threadHandleArray) // If we aren't giving this back to the user... + FreeThreadHandle(hThread); + } + } + } while(Thread32Next(hThreadSnap, &te32)); + } + + CloseHandle(hThreadSnap); + } + + #elif defined(OVR_OS_APPLE) + mach_port_t taskSelf = mach_task_self(); + thread_act_port_array_t threadArray; + mach_msg_type_number_t threadCount; + + kern_return_t result = task_threads(taskSelf, &threadArray, &threadCount); + + if(result == KERN_SUCCESS) + { + for(mach_msg_type_number_t i = 0; i < threadCount; i++) + { + ++countRequired; + + if((threadHandleArray || threadSysIdArray) && (count < threadArrayCapacity)) + { + if(threadHandleArray) + threadHandleArray[count] = pthread_from_mach_thread_np(threadArray[i]); + if(threadSysIdArray) + threadSysIdArray[count] = threadArray[i]; + ++count; + } + } + + vm_deallocate(taskSelf, (vm_address_t)threadArray, threadCount * sizeof(thread_act_t)); + } + + #elif defined(OVR_OS_LINUX) + // To do. + OVR_UNUSED(count); + OVR_UNUSED(threadHandleArray); + OVR_UNUSED(threadSysIdArray); + OVR_UNUSED(threadArrayCapacity); + #endif + + return countRequired; +} + + +void SymbolLookup::DoneThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCount) +{ + #if defined(OVR_OS_MS) + for(size_t i = 0; i != threadArrayCount; ++i) + { + if(threadHandleArray[i]) + { + CloseHandle(threadHandleArray[i]); + threadHandleArray[i] = OVR_THREADHANDLE_INVALID; + } + } + + OVR_UNUSED(threadSysIdArray); + #else + OVR_UNUSED(threadHandleArray); + OVR_UNUSED(threadSysIdArray); + OVR_UNUSED(threadArrayCount); + #endif +} + + +// Writes a given thread's callstack wity symbols to the given output. +// It may not be safe to call this from an exception handler, as sOutput allocates memory. +bool SymbolLookup::ReportThreadCallstack(OVR::String& sOutput, size_t skipCount, ThreadSysId threadSysId) +{ + if(!threadSysId) + threadSysId = GetCurrentThreadSysId(); + + void* addressArray[64]; + size_t addressCount = GetBacktraceFromThreadSysId(addressArray, OVR_ARRAY_COUNT(addressArray), skipCount, threadSysId); + + // Print the header + char headerBuffer[256]; + char threadName[32]; + char threadHandleStr[24]; + char threadSysIdStr[24]; + char stackBaseStr[24]; + char stackLimitStr[24]; + void* pStackBase; + void* pStackLimit; + //void* pStackCurrent; // Current stack pointer. To do: support reporting this. + ThreadHandle threadHandle = ConvertThreadSysIdToThreadHandle(threadSysId); + OVR::GetThreadStackBounds(pStackBase, pStackLimit, threadHandle); + + Thread::GetThreadName(threadName, OVR_ARRAY_COUNT(threadName), threadName); + SprintfThreadHandle(threadHandleStr, OVR_ARRAY_COUNT(threadHandleStr), threadHandle); + SprintfThreadSysId(threadSysIdStr, OVR_ARRAY_COUNT(threadSysIdStr), threadSysId); + SprintfAddress(stackBaseStr, OVR_ARRAY_COUNT(stackBaseStr), pStackBase); + SprintfAddress(stackLimitStr, OVR_ARRAY_COUNT(stackLimitStr), pStackLimit); + + if(threadName[0]) + OVR_snprintf(headerBuffer, OVR_ARRAY_COUNT(headerBuffer), "Thread \"%s\" handle: %s, id: %s, stack base: %s, stack limit: %s\r\n", threadName, threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr); + else + OVR_snprintf(headerBuffer, OVR_ARRAY_COUNT(headerBuffer), "Thread handle: %s, id: %s, stack base: %s, stack limit: %s\r\n", threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr); + + sOutput += headerBuffer; + + // Print the backtrace info + char backtraceBuffer[1024]; // Sometimes function symbol names are very long. + SymbolInfo symbolInfo; + const char* pModuleName; + + if(addressCount == 0) + { + sOutput += "<Unable to read backtrace>\r\n"; + } + else + { + for(size_t i = 0; i < addressCount; ++i) + { + LookupSymbol((uint64_t)addressArray[i], symbolInfo); + + if(symbolInfo.pModuleInfo && symbolInfo.pModuleInfo->name[0]) + pModuleName = symbolInfo.pModuleInfo->name; + else + pModuleName = "(unknown module)"; + + char addressStr[24]; + SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), addressArray[i]); + + if(symbolInfo.filePath[0]) + OVR_snprintf(backtraceBuffer, OVR_ARRAY_COUNT(backtraceBuffer), "%-2u %-24s %s %s+%d %s:%d\r\n", (unsigned)i, pModuleName, addressStr, symbolInfo.function, symbolInfo.functionOffset, symbolInfo.filePath, symbolInfo.fileLineNumber); + else + OVR_snprintf(backtraceBuffer, OVR_ARRAY_COUNT(backtraceBuffer), "%-2u %-24s %s %s+%d\r\n", (unsigned)i, pModuleName, addressStr, symbolInfo.function, symbolInfo.functionOffset); + + sOutput += backtraceBuffer; + } + } + + FreeThreadHandle(threadHandle); + + return (addressCount > 0); +} + + +// Writes all thread's callstacks with symbols to the given output. +// It may not be safe to call this from an exception handler, as sOutput allocates memory. +bool SymbolLookup::ReportThreadCallstacks(OVR::String& sOutput, size_t skipCount) +{ + ThreadSysId threadSysIdArray[64]; + size_t threadSysIdCount = GetThreadList(nullptr, threadSysIdArray, OVR_ARRAY_COUNT(threadSysIdArray)); + + if(threadSysIdCount > OVR_ARRAY_COUNT(threadSysIdArray)) + threadSysIdCount = OVR_ARRAY_COUNT(threadSysIdArray); + + for(size_t i = 0; i < threadSysIdCount; i++) + { + String sTemp; + ReportThreadCallstack(sTemp, skipCount, threadSysIdArray[i]); + if(i > 0) + sOutput += "\r\n"; + sOutput += sTemp; + } + + return (threadSysIdCount > 0); +} + + +bool SymbolLookup::RefreshModuleList() +{ + if(!moduleListUpdated) + { + #if defined(OVR_OS_MS) + // We can't rely on SymRefreshModuleList because it's present in DbgHelp 6.5, + // which doesn't distribute with Windows 7. + + // Currently we support only refreshing the list once ever. With a little effort we could revise this code to + // support re-refreshing the list at runtime to account for the possibility that modules have recently been + // added or removed. + if(pSymLoadModule64) + { + const size_t requiredCount = GetModuleInfoArray(moduleInfoArray, OVR_ARRAY_COUNT(moduleInfoArray)); + moduleInfoArraySize = MIN(requiredCount, OVR_ARRAY_COUNT(moduleInfoArray)); + + HANDLE hProcess = GetCurrentProcess(); + + for(size_t i = 0; i < moduleInfoArraySize; i++) + pSymLoadModule64(hProcess, nullptr, moduleInfoArray[i].filePath, nullptr, moduleInfoArray[i].baseAddress, (DWORD)moduleInfoArray[i].size); + + moduleListUpdated = true; + } + #else + const size_t requiredCount = GetModuleInfoArray(moduleInfoArray, OVR_ARRAY_COUNT(moduleInfoArray)); + moduleInfoArraySize = MIN(requiredCount, OVR_ARRAY_COUNT(moduleInfoArray)); + moduleListUpdated = true; + #endif + } + + return true; +} + + +bool SymbolLookup::LookupSymbol(uint64_t address, SymbolInfo& symbolInfo) +{ + return LookupSymbols(&address, &symbolInfo, 1); +} + + +bool SymbolLookup::LookupSymbols(uint64_t* addressArray, SymbolInfo* pSymbolInfoArray, size_t arraySize) +{ + if(!moduleListUpdated) + { + RefreshModuleList(); + } + + #if defined(OVR_OS_MS) + union SYMBOL_INFO_UNION + { + SYMBOL_INFO msSymbolInfo; + char suffixPadding[sizeof(SYMBOL_INFO) + 1024]; + }; + + for(size_t i = 0; i < arraySize; i++) + { + uint64_t& address = addressArray[i]; + SymbolInfo& symbolInfo = pSymbolInfoArray[i]; + + // Copy the address and ModuleInfo + symbolInfo.address = addressArray[i]; + symbolInfo.pModuleInfo = GetModuleInfoForAddress(address); // We could also use siu.msSymbolInfo.ModBase to get the module slightly faster. + + // Get the function/offset. + SYMBOL_INFO_UNION siu; + memset(&siu, 0, sizeof(siu)); + siu.msSymbolInfo.SizeOfStruct = sizeof(siu.msSymbolInfo); + siu.msSymbolInfo.MaxNameLen = sizeof(siu.suffixPadding) - sizeof(SYMBOL_INFO) + 1; // +1 because SYMBOL_INFO itself has Name[1]. + + HANDLE hProcess = GetCurrentProcess(); + DWORD64 displacement64 = 0; + bool bResult = (pSymFromAddr != nullptr) && (pSymFromAddr(hProcess, address, &displacement64, &siu.msSymbolInfo) != FALSE); + + if(bResult) + { + symbolInfo.size = siu.msSymbolInfo.Size; + OVR_strlcpy(symbolInfo.function, siu.msSymbolInfo.Name, OVR_ARRAY_COUNT(symbolInfo.function)); + symbolInfo.functionOffset = (int32_t)displacement64; + } + else + { + symbolInfo.size = kMISizeInvalid; + symbolInfo.function[0] = 0; + symbolInfo.functionOffset = kMIFunctionOffsetInvalid; + } + + // Get the file/line + IMAGEHLP_LINE64 iLine64; + DWORD displacement = 0; + memset(&iLine64, 0, sizeof(iLine64)); + iLine64.SizeOfStruct = sizeof(iLine64); + + bResult = (pSymGetLineFromAddr64 != nullptr) && (pSymGetLineFromAddr64(hProcess, address, &displacement, &iLine64) != FALSE); + + if(bResult) + { + OVR_strlcpy(symbolInfo.filePath, iLine64.FileName, OVR_ARRAY_COUNT(symbolInfo.filePath)); + symbolInfo.fileLineNumber = (int32_t)iLine64.LineNumber; + } + else + { + symbolInfo.filePath[0] = 0; + symbolInfo.fileLineNumber = kMILineNumberInvalid; + } + + // To do: get the source code when possible. We need to use the user-registered directory paths and the symbolInfo.filePath + // and find the given file in the tree(s), then open the file and find the symbolInfo.fileLineNumber line (and surrounding lines). + // symbolInfo.sourceCode[1024] + symbolInfo.sourceCode[0] = '\0'; + } + + #elif defined(OVR_OS_APPLE) + // Apple has an internal CoreSymbolication library which could help with this. + // Third party implementations of the CoreSymbolication header are available and could be used + // to get file/line info better than other means. It used Objective C, so we'll need a .m or .mm file. + + memset(pSymbolInfoArray, 0, arraySize * sizeof(SymbolInfo)); + + for(size_t i = 0; i < arraySize; i++) + { + pSymbolInfoArray[i].address = addressArray[i]; + pSymbolInfoArray[i].pModuleInfo = GetModuleInfoForAddress(addressArray[i]); + } + + // Problem: backtrace_symbols allocates memory from malloc. If you got into a SIGSEGV due to + // malloc arena corruption (quite common) you will likely fault in backtrace_symbols. + // To do: Use allowMemoryAllocation here. + + #if (OVR_PTR_SIZE == 4) + // backtrace_symbols takes a void* array, but we have a uint64_t array. So for 32 bit we + // need to convert the 64 bit array to 32 bit temporarily for the backtrace_symbols call. + void* ptr32Array[256]; // To do: Remove this limit. + for(size_t i = 0, iEnd = MIN(arraySize, OVR_ARRAY_COUNT(ptr32Array)); i < iEnd; i++) + ptr32Array[i] = reinterpret_cast<void*>(addressArray[i]); + char** symbolArray = backtrace_symbols(reinterpret_cast<void**>(ptr32Array), (int)arraySize); + #else + char** symbolArray = backtrace_symbols(reinterpret_cast<void**>(addressArray), (int)arraySize); + #endif + + if(symbolArray) + { + for(size_t i = 0; i < arraySize; i++) + { + + // Generates a string like this: "0 OculusWorldDemo 0x000000010000cfd5 _ZN18OculusWorldDemoApp9OnStartupEiPPKc + 213" + static_assert(OVR_ARRAY_COUNT(pSymbolInfoArray[i].function) == 128, "Need to change the string format size below"); + + sscanf(symbolArray[i], "%*d %*s %*x %128s + %d", pSymbolInfoArray[i].function, &pSymbolInfoArray[i].functionOffset); + + if(allowMemoryAllocation) + { + int status = 0; + char* strDemangled = abi::__cxa_demangle(pSymbolInfoArray[i].function, nullptr, nullptr, &status); + + if(strDemangled) + { + OVR_strlcpy(pSymbolInfoArray[i].function, strDemangled, OVR_ARRAY_COUNT(pSymbolInfoArray[i].function)); + free(strDemangled); + } + } + } + + free(symbolArray); + } + + // To consider: use CoreSybolication to get file/line info instead. atos is a bit slow and cumbersome. + // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/atos.1.html + // atos -p <pid> <addr> <addr> ... + // atos -o <binary image path> -l <load-address> <addr> <addr> ... + // Generates output like this: "OVR::CreateException(OVR::CreateExceptionType) (in OculusWorldDemo) (ExceptionHandler.cpp:598)" + for(size_t i = 0; i < arraySize; i++) + { + struct stat statStruct; + + if(pSymbolInfoArray[i].pModuleInfo && pSymbolInfoArray[i].pModuleInfo->filePath[0] && (stat(pSymbolInfoArray[i].pModuleInfo->filePath, &statStruct) == 0)) + { + char command[PATH_MAX * 2]; // Problem: We can't unilaterally use pSymbolInfoArray[0] for all addresses. We need to match addresses to the corresponding modules. + OVR_snprintf(command, OVR_ARRAY_COUNT(command), "atos -o %s -l 0x%llx 0x%llx", + pSymbolInfoArray[i].pModuleInfo->filePath, (int64_t)pSymbolInfoArray[i].pModuleInfo->baseAddress, (int64_t)pSymbolInfoArray[i].address); + + char output[512]; + if(SpawnShellCommand(command, output, OVR_ARRAY_COUNT(output)) != (size_t)-1) + { + char* pLastOpenParen = strrchr(output, '('); + char* pColon = strrchr(output, ':'); + + if(pLastOpenParen && (pColon > pLastOpenParen)) + { + *pColon = '\0'; + OVR_strlcpy(pSymbolInfoArray[i].filePath, pLastOpenParen + 1, OVR_ARRAY_COUNT(pSymbolInfoArray[i].filePath)); + } + } + } + } + + #elif defined(OVR_OS_LINUX) + // We can use libunwind's unw_get_proc_name to try to get function name info. It can work regardless of relocation. + // Use backtrace_symbols and addr2line. Need to watch out for module load-time relocation. + // Ned to pass the -rdynamic flag to the linker. It will cause the linker to out in the link + // tables the name of all the none static functions in your code, not just the exported ones. + OVR_UNUSED(addressArray); + OVR_UNUSED(pSymbolInfoArray); + OVR_UNUSED(arraySize); + #endif + + return true; // To do: Return true only if something was found. +} + + +const ModuleInfo* SymbolLookup::GetModuleInfoForAddress(uint64_t address) +{ + // This is a linear seach. To consider: it would be significantly faster to search by + // address if we ordered it by base address and did a binary search. + for(size_t i = 0; i < moduleInfoArraySize; ++i) + { + const ModuleInfo& mi = moduleInfoArray[i]; + + if((mi.baseAddress <= address) && (address < (mi.baseAddress + mi.size))) + return &mi; + } + + return nullptr; +} + + + + +ExceptionInfo::ExceptionInfo() + : time() + , timeVal(0) + , backtrace() + , backtraceCount(0) + , threadHandle(OVR_THREADHANDLE_INVALID) + , threadSysId(OVR_THREADSYSID_INVALID) + , threadName() + , pExceptionInstructionAddress(nullptr) + , pExceptionMemoryAddress(nullptr) + , cpuContext() + , exceptionDescription() + , symbolInfo() + #if defined(OVR_OS_MS) + , exceptionRecord() + #elif defined(OVR_OS_APPLE) + , exceptionType(0) + , cpuExceptionId(0) + , cpuExceptionIdError(0) + , machExceptionDetail() + , machExceptionDetailCount(0) + #endif +{ +} + + + +ExceptionHandler::ExceptionHandler() + : enabled(false) + , reportPrivacyEnabled(true) + , exceptionResponse(kERHandle) + , exceptionListener(nullptr) + , exceptionListenerUserValue(0) + , appDescription() + , codeBasePathArray() + , reportFilePath() + , miniDumpFlags(0) + , miniDumpFilePath() + , file(nullptr) + , scratchBuffer() + , exceptionOccurred(false) + , handlingBusy(0) + , reportFilePathActual() + , minidumpFilePathActual() + , terminateReturnValue(0) + , exceptionInfo() + #if defined(OVR_OS_MS) + , vectoredHandle(nullptr) + , previousFilter(nullptr) + , pExceptionPointers(nullptr) + #elif defined(OVR_OS_MAC) + , machHandlerInitialized(false) + , machExceptionPort(0) + , machExceptionPortsSaved() + , machThreadShouldContinue(false) + , machThreadExecuting(false) + , machThread((pthread_t)OVR_THREADHANDLE_INVALID) + #endif +{ + SetExceptionPaths("default", "default"); +} + + +ExceptionHandler::~ExceptionHandler() +{ + if(enabled) + { + Enable(false); + } +} + + +#if defined(OVR_OS_MS) + static ExceptionHandler* sExceptionHandler = nullptr; + + LONG WINAPI Win32ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers) + { + if(sExceptionHandler) + return (LONG)sExceptionHandler->ExceptionFilter(pExceptionPointers); + return EXCEPTION_CONTINUE_SEARCH; + } + + LONG ExceptionHandler::ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers) + { + // Exception codes < 0x80000000 are not true exceptions but rather are debugger notifications. They include DBG_TERMINATE_THREAD, + // DBG_TERMINATE_PROCESS, DBG_CONTROL_BREAK, DBG_COMMAND_EXCEPTION, DBG_CONTROL_C, DBG_PRINTEXCEPTION_C, DBG_RIPEXCEPTION, + // and 0x406d1388 (thread named, http://blogs.msdn.com/b/stevejs/archive/2005/12/19/505815.aspx). + + if(pExceptionPointers->ExceptionRecord->ExceptionCode < 0x80000000) + return EXCEPTION_CONTINUE_SEARCH; + + // VC++ C++ exceptions use code 0xe06d7363 ('Emsc') + // http://support.microsoft.com/kb/185294 + // http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx + if(pExceptionPointers->ExceptionRecord->ExceptionCode == 0xe06d7363) + return EXCEPTION_CONTINUE_SEARCH; + + if(handlingBusy.CompareAndSet_Acquire(0, 1)) // If we can successfully change it from 0 to 1. + { + exceptionOccurred = true; + + this->pExceptionPointers = pExceptionPointers; + + // Disable the handler while we do this processing. + ULONG result = RemoveVectoredExceptionHandler(vectoredHandle); + OVR_ASSERT_AND_UNUSED(result != 0, result); + + // Time + exceptionInfo.timeVal = time(nullptr); + exceptionInfo.time = *gmtime(&exceptionInfo.timeVal); + + // Thread id + // This is the thread id of the current thread and not the exception thread. + if(!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &exceptionInfo.threadHandle, 0, true, DUPLICATE_SAME_ACCESS)) + exceptionInfo.threadHandle = 0; + exceptionInfo.threadSysId = ConvertThreadHandleToThreadSysId(exceptionInfo.threadHandle); + + OVR::GetThreadName(exceptionInfo.threadHandle, exceptionInfo.threadName, OVR_ARRAY_COUNT(exceptionInfo.threadName)); + + // Backtraces + exceptionInfo.backtraceCount = symbolLookup.GetBacktrace(exceptionInfo.backtrace, OVR_ARRAY_COUNT(exceptionInfo.backtrace)); + + // Context + exceptionInfo.cpuContext = *pExceptionPointers->ContextRecord; + exceptionInfo.exceptionRecord = *pExceptionPointers->ExceptionRecord; + exceptionInfo.pExceptionInstructionAddress = exceptionInfo.exceptionRecord.ExceptionAddress; + if((exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) || (exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_IN_PAGE_ERROR)) + exceptionInfo.pExceptionMemoryAddress = (void*)exceptionInfo.exceptionRecord.ExceptionInformation[1]; // ExceptionInformation[0] indicates if it was a read (0), write (1), or data execution attempt (8). + else + exceptionInfo.pExceptionMemoryAddress = pExceptionPointers->ExceptionRecord->ExceptionAddress; + + WriteExceptionDescription(); + + if(miniDumpFilePath[0]) + WriteMiniDump(); + + if(reportFilePath[0]) + WriteReport(); + + if(exceptionListener) + exceptionListener->HandleException(exceptionListenerUserValue, this, &exceptionInfo, reportFilePathActual); + + if(exceptionInfo.threadHandle) + { + CloseHandle(exceptionInfo.threadHandle); + exceptionInfo.threadHandle = 0; + } + + // Restore the handler that we temporarily disabled above. + vectoredHandle = AddVectoredExceptionHandler(1, Win32ExceptionFilter); + + handlingBusy.Store_Release(0); + } + + if(exceptionResponse == ExceptionHandler::kERTerminate) + { + TerminateProcess(GetCurrentProcess(), (UINT)terminateReturnValue); + return terminateReturnValue; + } + else if(exceptionResponse == ExceptionHandler::kERThrow) + return EXCEPTION_CONTINUE_SEARCH; + else if(exceptionResponse == ExceptionHandler::kERContinue) + return EXCEPTION_CONTINUE_EXECUTION; + return EXCEPTION_EXECUTE_HANDLER; + } + +#endif // defined(OVR_OS_MS) + + +#if defined(OVR_OS_APPLE) + // http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/ + // http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/ + // http://www.opensource.apple.com/source/Libc/Libc-825.26/ + // https://mikeash.com/pyblog/friday-qa-2013-01-11-mach-exception-handlers.html + + void* ExceptionHandler::MachHandlerThreadFunction() + { + __Request__mach_exception_raise_state_identity_t msg; + __Reply__mach_exception_raise_state_identity_t reply; + mach_msg_return_t result; + + machThreadExecuting = true; + pthread_setname_np("ExceptionHandler"); + + while(machThreadShouldContinue) + { + mach_msg_option_t options = MACH_RCV_MSG | MACH_RCV_LARGE; + natural_t timeout = 0; // Would be better to support a non-zero time. + + if(timeout) + options |= MACH_RCV_TIMEOUT; + + result = mach_msg(&msg.Head, options, 0, sizeof(msg), machExceptionPort, timeout, MACH_PORT_NULL); + + if(msg.Head.msgh_id != sMachCancelMessageType) + { + if(result == MACH_MSG_SUCCESS) + { + if(mach_exc_server_OVR(&msg.Head, &reply.Head) == 0) //This will call our HandleMachException function. + result = ~MACH_MSG_SUCCESS; + } + + // Send the reply + if(result == MACH_MSG_SUCCESS) + { + result = mach_msg(&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + if(result != MACH_MSG_SUCCESS) + { + // Failure. + } + } + } + } + + machThreadExecuting = false; + + return nullptr; + } + + + kern_return_t ExceptionHandler::HandleMachException(mach_port_t /*machPort*/, mach_port_t threadSysId, mach_port_t machTask, + exception_type_t machExceptionType, mach_exception_data_type_t* pExceptionDetail, + mach_msg_type_number_t exceptionDetailCount, int* /*pMachExceptionFlavor*/, thread_state_t threadStatePrev, + mach_msg_type_number_t /*threadStatePrevCount*/, thread_state_t /*threadStateNew*/, + mach_msg_type_number_t* /*pThreadStateNewCount*/) + { + // We don't want to handle exceptions for other processes. + if(machTask != mach_task_self()) + return ForwardMachException(threadSysId, machTask, machExceptionType, pExceptionDetail, exceptionDetailCount); + + if(handlingBusy.CompareAndSet_Acquire(0, 1)) // If we can successfully change it from 0 to 1. + { + exceptionOccurred = true; + + // Disable the handler while we do this processing. + // To do. + + // Time + exceptionInfo.timeVal = time(nullptr); + exceptionInfo.time = *gmtime(&exceptionInfo.timeVal); + + // Thread id + exceptionInfo.threadHandle = pthread_from_mach_thread_np(threadSysId); + exceptionInfo.threadSysId = threadSysId; + pthread_getname_np((pthread_t)exceptionInfo.threadHandle, exceptionInfo.threadName, sizeof(exceptionInfo.threadName)); + + // Backtraces + exceptionInfo.backtraceCount = symbolLookup.GetBacktraceFromThreadSysId(exceptionInfo.backtrace, OVR_ARRAY_COUNT(exceptionInfo.backtrace), 0, threadSysId); + + // Context + #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + // We can read x86_THREAD_STATE directly fromk threadStatePrev. + exceptionInfo.cpuContext.threadState = *reinterpret_cast<x86_thread_state_t*>(threadStatePrev); + + mach_msg_type_number_t stateCount = x86_FLOAT_STATE_COUNT; + thread_get_state(threadSysId, x86_FLOAT_STATE, (natural_t*)&exceptionInfo.cpuContext.floatState, &stateCount); + + stateCount = x86_DEBUG_STATE_COUNT; + thread_get_state(threadSysId, x86_DEBUG_STATE, (natural_t*)&exceptionInfo.cpuContext.debugState, &stateCount); + + stateCount = x86_AVX_STATE_COUNT; + thread_get_state(threadSysId, x86_AVX_STATE, (natural_t*)&exceptionInfo.cpuContext.avxState, &stateCount); + + stateCount = x86_EXCEPTION_STATE_COUNT; + thread_get_state(threadSysId, x86_EXCEPTION_STATE, (natural_t*)&exceptionInfo.cpuContext.exceptionState, &stateCount); + + #if defined(OVR_CPU_X86) + exceptionInfo.pExceptionInstructionAddress = (void*)exceptionInfo.cpuContext.threadState.uts.ts32.__eip; + exceptionInfo.pExceptionMemoryAddress = (void*)exceptionInfo.cpuContext.exceptionState.ues.es32.__faultvaddr; + exceptionInfo.cpuExceptionId = exceptionInfo.cpuContext.exceptionState.ues.es32.__trapno; + exceptionInfo.cpuExceptionIdError = exceptionInfo.cpuContext.exceptionState.ues.es32.__err; + #else + exceptionInfo.pExceptionInstructionAddress = (void*)exceptionInfo.cpuContext.threadState.uts.ts64.__rip; + exceptionInfo.pExceptionMemoryAddress = (void*)exceptionInfo.cpuContext.exceptionState.ues.es64.__faultvaddr; + exceptionInfo.cpuExceptionId = exceptionInfo.cpuContext.exceptionState.ues.es64.__trapno; + exceptionInfo.cpuExceptionIdError = exceptionInfo.cpuContext.exceptionState.ues.es64.__err; + #endif + #endif + + exceptionInfo.exceptionType = machExceptionType; + + exceptionInfo.machExceptionDetailCount = MIN(exceptionDetailCount, OVR_ARRAY_COUNT(exceptionInfo.machExceptionDetail)); + for(int i = 0; i < exceptionInfo.machExceptionDetailCount; i++) + exceptionInfo.machExceptionDetail[i] = pExceptionDetail[i]; + + WriteExceptionDescription(); + + if(reportFilePath[0]) + WriteReport(); + + if(miniDumpFilePath[0]) + WriteMiniDump(); + + if(exceptionListener) + exceptionListener->HandleException(exceptionListenerUserValue, this, &exceptionInfo, reportFilePathActual); + + // Re-restore the handler. + // To do. + + handlingBusy.Store_Release(0); + } + + kern_return_t result = KERN_FAILURE; // By default pass on the exception to another handler after we are done here. + + if(exceptionResponse == ExceptionHandler::kERTerminate) + ::exit(terminateReturnValue); + else if(exceptionResponse == ExceptionHandler::kERThrow) + ForwardMachException(threadSysId, machTask, machExceptionType, pExceptionDetail, exceptionDetailCount); + else if(exceptionResponse == ExceptionHandler::kERDefault) + ::exit(terminateReturnValue); + else if(exceptionResponse == ExceptionHandler::kERContinue) + result = KERN_SUCCESS; // This will trigger a re-execution of the function. + + return result; + } + + + bool ExceptionHandler::InitMachExceptionHandler() + { + if(!machHandlerInitialized) + { + mach_port_t machTaskSelf = mach_task_self(); + kern_return_t result = MACH_MSG_SUCCESS; + exception_mask_t mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_CRASH; + + if(machExceptionPort == MACH_PORT_NULL) + { + result = mach_port_allocate(machTaskSelf, MACH_PORT_RIGHT_RECEIVE, &machExceptionPort); + + if(result == MACH_MSG_SUCCESS) + { + result = mach_port_insert_right(machTaskSelf, machExceptionPort, machExceptionPort, MACH_MSG_TYPE_MAKE_SEND); + + if(result == MACH_MSG_SUCCESS) + result = task_get_exception_ports(machTaskSelf, mask, machExceptionPortsSaved.masks, &machExceptionPortsSaved.count, + machExceptionPortsSaved.ports, machExceptionPortsSaved.behaviors, machExceptionPortsSaved.flavors); + } + } + + if(result == MACH_MSG_SUCCESS) + { + result = task_set_exception_ports(machTaskSelf, mask, machExceptionPort, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE); + + if(result == MACH_MSG_SUCCESS) + { + machThreadShouldContinue = true; + + pthread_attr_t attr; + pthread_attr_init(&attr); + + result = pthread_create(&machThread, &attr, MachHandlerThreadFunctionStatic, (void*)this); + pthread_attr_destroy(&attr); + + machHandlerInitialized = (result == 0); + } + } + + if(!machHandlerInitialized) + ShutdownMachExceptionHandler(); + } + + return machHandlerInitialized; + } + + + void ExceptionHandler::ShutdownMachExceptionHandler() + { + if(machThreadExecuting) + { + machThreadShouldContinue = false; // Tell it to stop. + + // Cancel the current exception handler thread (which is probably blocking in a call to mach_msg) by sending it a cencel message. + struct CancelMessage + { + mach_msg_header_t msgHeader; + }; + + CancelMessage msg; + memset(&msg.msgHeader, 0, sizeof(CancelMessage)); + msg.msgHeader.msgh_id = sMachCancelMessageType; + msg.msgHeader.msgh_size = sizeof(CancelMessage); + msg.msgHeader.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND); + msg.msgHeader.msgh_remote_port = machExceptionPort; + msg.msgHeader.msgh_local_port = MACH_PORT_NULL; + + mach_msg_return_t result = mach_msg(&msg.msgHeader, MACH_SEND_MSG, msg.msgHeader.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + if(result == MACH_MSG_SUCCESS) + { + const double threeSecondsLater = ovr_GetTimeInSeconds() + 3.f; + + while(machThreadExecuting && (ovr_GetTimeInSeconds() < threeSecondsLater)) + { + timespec ts = { 0, 1000000000 }; + nanosleep(&ts, nullptr); + } + } + + void* joinResult = nullptr; + pthread_join(machThread, &joinResult); + machThread = 0; + } + + if(machExceptionPort != MACH_PORT_NULL) + { + // Restore the previous ports + kern_return_t result = KERN_SUCCESS; + mach_port_t machTaskSelf = mach_task_self(); + + for(unsigned i = 0; (i < machExceptionPortsSaved.count) && (result == KERN_SUCCESS); i++) + { + result = task_set_exception_ports(machTaskSelf, machExceptionPortsSaved.masks[i], machExceptionPortsSaved.ports[i], + machExceptionPortsSaved.behaviors[i], machExceptionPortsSaved.flavors[i]); + } + + mach_port_deallocate(machTaskSelf, machExceptionPort); + machExceptionPort = MACH_PORT_NULL; + } + + machHandlerInitialized = false; + } + + + kern_return_t ExceptionHandler::ForwardMachException(mach_port_t thread, mach_port_t task, exception_type_t exceptionType, + mach_exception_data_t pExceptionDetail, mach_msg_type_number_t exceptionDetailCount) + { + kern_return_t result = KERN_FAILURE; + mach_msg_type_number_t i; + + for(i = 0; i < machExceptionPortsSaved.count; i++) + { + if(machExceptionPortsSaved.masks[i] & (1 << exceptionType)) + break; + } + + if(i < machExceptionPortsSaved.count) + { + mach_port_t port = machExceptionPortsSaved.ports[i]; + exception_behavior_t behavior = machExceptionPortsSaved.behaviors[i]; + thread_state_flavor_t flavor = machExceptionPortsSaved.flavors[i]; + mach_msg_type_number_t threadStateCount = THREAD_STATE_MAX; + thread_state_data_t threadState; + + if(behavior != EXCEPTION_DEFAULT) + thread_get_state(thread, flavor, threadState, &threadStateCount); + + switch(behavior) + { + case EXCEPTION_DEFAULT: + result = mach_exception_raise_OVR(port, thread, task, exceptionType, pExceptionDetail, exceptionDetailCount); + break; + + case EXCEPTION_STATE: + result = mach_exception_raise_state_OVR(port, exceptionType, pExceptionDetail, exceptionDetailCount, + &flavor, threadState, threadStateCount, threadState, &threadStateCount); + break; + + case EXCEPTION_STATE_IDENTITY: + result = mach_exception_raise_state_identity_OVR(port, thread, task, exceptionType, pExceptionDetail, + exceptionDetailCount, &flavor, threadState, threadStateCount, threadState, &threadStateCount); + break; + + default: + result = KERN_FAILURE; + break; + } + + if(behavior != EXCEPTION_DEFAULT) + result = thread_set_state(thread, flavor, threadState, threadStateCount); + } + + return result; + } + + +#endif // OVR_OS_APPLE + + +bool ExceptionHandler::Enable(bool enable) +{ + #if defined(OVR_OS_MS) + if(enable && !enabled) + { + OVR_ASSERT(vectoredHandle == nullptr); + vectoredHandle = AddVectoredExceptionHandler(1, Win32ExceptionFilter); // Windows call. + enabled = (vectoredHandle != nullptr); + OVR_ASSERT(enabled); + sExceptionHandler = this; + return enabled; + } + else if(!enable && enabled) + { + if(sExceptionHandler == this) + sExceptionHandler = nullptr; + OVR_ASSERT(vectoredHandle != nullptr); + ULONG result = RemoveVectoredExceptionHandler(vectoredHandle); // Windows call. + OVR_ASSERT_AND_UNUSED(result != 0, result); + vectoredHandle = nullptr; + enabled = false; + return true; + } + + #elif defined(OVR_OS_APPLE) + + if(enable && !enabled) + { + enabled = InitMachExceptionHandler(); + OVR_ASSERT(enabled); + sExceptionHandler = this; + return enabled; + } + else if(!enable && enabled) + { + if(sExceptionHandler == this) + sExceptionHandler = nullptr; + ShutdownMachExceptionHandler(); + enabled = false; + return true; + } + #else + OVR_UNUSED(enable); + #endif + + return true; +} + + +void ExceptionHandler::EnableReportPrivacy(bool enable) +{ + reportPrivacyEnabled = enable; +} + +void ExceptionHandler::WriteExceptionDescription() +{ + #if defined(OVR_OS_MS) + // There is some extra information available for AV exception. + if(exceptionInfo.exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) + { + const char* error = (exceptionInfo.exceptionRecord.ExceptionInformation[0] == 0) ? "reading" : + ((exceptionInfo.exceptionRecord.ExceptionInformation[0] == 1) ? "writing" : "executing"); + + char addressStr[24]; + SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionMemoryAddress); + OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), "ACCESS_VIOLATION %s address %s", error, addressStr); + } + else + { + exceptionInfo.exceptionDescription[0] = 0; + + // Process "standard" exceptions, other than 'access violation' + #define FORMAT_EXCEPTION(x) \ + case EXCEPTION_##x: \ + OVR::OVR_strlcpy(exceptionInfo.exceptionDescription, #x, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription)); \ + break; + + switch(exceptionInfo.exceptionRecord.ExceptionCode) + { + //FORMAT_EXCEPTION(ACCESS_VIOLATION) Already handled above. + FORMAT_EXCEPTION(DATATYPE_MISALIGNMENT) + FORMAT_EXCEPTION(BREAKPOINT) + FORMAT_EXCEPTION(SINGLE_STEP) + FORMAT_EXCEPTION(ARRAY_BOUNDS_EXCEEDED) + FORMAT_EXCEPTION(FLT_DENORMAL_OPERAND) + FORMAT_EXCEPTION(FLT_DIVIDE_BY_ZERO) + FORMAT_EXCEPTION(FLT_INEXACT_RESULT) + FORMAT_EXCEPTION(FLT_INVALID_OPERATION) + FORMAT_EXCEPTION(FLT_OVERFLOW) + FORMAT_EXCEPTION(FLT_STACK_CHECK) + FORMAT_EXCEPTION(FLT_UNDERFLOW) + FORMAT_EXCEPTION(INT_DIVIDE_BY_ZERO) + FORMAT_EXCEPTION(INT_OVERFLOW) + FORMAT_EXCEPTION(PRIV_INSTRUCTION) + FORMAT_EXCEPTION(IN_PAGE_ERROR) + FORMAT_EXCEPTION(ILLEGAL_INSTRUCTION) + FORMAT_EXCEPTION(NONCONTINUABLE_EXCEPTION) + FORMAT_EXCEPTION(STACK_OVERFLOW) + FORMAT_EXCEPTION(INVALID_DISPOSITION) + FORMAT_EXCEPTION(GUARD_PAGE) + FORMAT_EXCEPTION(INVALID_HANDLE) + #if defined(EXCEPTION_POSSIBLE_DEADLOCK) && defined(STATUS_POSSIBLE_DEADLOCK) // This type seems to be non-existant in practice. + FORMAT_EXCEPTION(POSSIBLE_DEADLOCK) + #endif + } + + // If not one of the "known" exceptions, try to get the string from NTDLL.DLL's message table. + if(exceptionInfo.exceptionDescription[0] == 0) + { + char addressStr[24]; + SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionMemoryAddress); + + #if !defined(OVR_OS_CONSOLE) // If FormatMessage is supported... + char buffer[384]; + DWORD capacity = OVR_ARRAY_COUNT(buffer); + + const size_t length = (size_t)FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, + GetModuleHandleW(L"NTDLL.DLL"), exceptionInfo.exceptionRecord.ExceptionCode, 0, buffer, capacity, nullptr); + if(length) + OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), + "%s at instruction %s", buffer, addressStr); + #endif + + // If everything else failed just show the hex code. + if(exceptionInfo.exceptionDescription[0] == 0) + OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), + "Unknown exception 0x%08x at instruction %s", exceptionInfo.exceptionRecord.ExceptionCode, addressStr); + } + } + + #elif defined(OVR_OS_APPLE) + struct MachExceptionInfo + { + static const char* GetCPUExceptionIdString(uint32_t cpuExceptionId) + { + const char* id; + + #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + switch (cpuExceptionId) + { + case 0: id = "integer div/0"; break; + case 1: id = "breakpoint fault"; break; + case 2: id = "non-maskable interrupt"; break; + case 3: id = "int 3"; break; + case 4: id = "overflow"; break; + case 5: id = "bounds check failure"; break; + case 6: id = "invalid instruction"; break; + case 7: id = "coprocessor unavailable"; break; + case 8: id = "exception within exception"; break; + case 9: id = "coprocessor segment overrun"; break; + case 10: id = "invalid task switch"; break; + case 11: id = "segment not present"; break; + case 12: id = "stack exception"; break; + case 13: id = "general protection fault"; break; + case 14: id = "page fault"; break; + case 16: id = "coprocessor error"; break; + default: id = "<unknown>"; break; + } + #else + // To do: Support ARM or others. + #endif + + return id; + } + + static const char* GetMachExceptionTypeString(uint64_t exceptionCause) + { + switch (exceptionCause) + { + case EXC_ARITHMETIC: return "EXC_ARITHMETIC"; + case EXC_BAD_ACCESS: return "EXC_BAD_ACCESS"; + case EXC_BAD_INSTRUCTION: return "EXC_BAD_INSTRUCTION"; + case EXC_BREAKPOINT: return "EXC_BREAKPOINT"; + case EXC_CRASH: return "EXC_CRASH"; + case EXC_EMULATION: return "EXC_EMULATION"; + case EXC_MACH_SYSCALL: return "EXC_MACH_SYSCALL"; + case EXC_RPC_ALERT: return "EXC_RPC_ALERT"; + case EXC_SOFTWARE: return "EXC_SOFTWARE"; + case EXC_SYSCALL: return "EXC_SYSCALL"; + }; + + return "EXC_<unknown>"; + } + + static const char* GetMachExceptionIdString(uint64_t machExceptionId, uint64_t code0) + { + const char* id = "<unknown>"; + + #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + switch (machExceptionId) + { + case EXC_ARITHMETIC: + switch (code0) + { + case EXC_I386_BOUND: id = "EXC_I386_BOUND"; break; + case EXC_I386_DIV: id = "EXC_I386_DIV"; break; + case EXC_I386_EMERR: id = "EXC_I386_EMERR"; break; + case EXC_I386_EXTERR: id = "EXC_I386_EXTERR"; break; + case EXC_I386_EXTOVR: id = "EXC_I386_EXTOVR"; break; + case EXC_I386_INTO: id = "EXC_I386_INTO"; break; + case EXC_I386_NOEXT: id = "EXC_I386_NOEXT"; break; + case EXC_I386_SSEEXTERR: id = "EXC_I386_SSEEXTERR"; break; + } + break; + + case EXC_BAD_INSTRUCTION: + if(code0 == EXC_I386_INVOP) + id = "EXC_I386_INVOP"; + break; + + case EXC_BREAKPOINT: + if(code0 == EXC_I386_BPT) + id = "EXC_I386_BPT"; + else if(code0 == EXC_I386_SGL) + id = "EXC_I386_SGL"; + break; + }; + #else + // To do. + #endif + + return id; + } + }; + + OVR::OVR_snprintf(exceptionInfo.exceptionDescription, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription), + "Mach exception type: %llu (%s)\r\n", exceptionInfo.exceptionType, MachExceptionInfo::GetMachExceptionTypeString(exceptionInfo.exceptionType)); + + OVR::OVR_snprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), "CPU exception info: exception id: %u (%s), exception id error: %u, fault memory address: %p\r\n", + exceptionInfo.cpuExceptionId, MachExceptionInfo::GetCPUExceptionIdString(exceptionInfo.cpuExceptionId), exceptionInfo.cpuExceptionIdError, exceptionInfo.pExceptionMemoryAddress); + OVR::OVR_strlcat(exceptionInfo.exceptionDescription, scratchBuffer, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription)); + + + OVR::OVR_snprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), "Mach exception info: exception id: %llu (%s), 0x%llx (%llu)\r\n", (uint64_t)exceptionInfo.machExceptionDetail[0], + MachExceptionInfo::GetMachExceptionIdString(exceptionInfo.exceptionType, exceptionInfo.machExceptionDetail[0]), + (uint64_t)exceptionInfo.machExceptionDetail[1], (uint64_t)exceptionInfo.machExceptionDetail[1]); + OVR::OVR_strlcat(exceptionInfo.exceptionDescription, scratchBuffer, OVR_ARRAY_COUNT(exceptionInfo.exceptionDescription)); + #else + // To do. + exceptionInfo.exceptionDescription[0] = 0; + #endif +} + + +void ExceptionHandler::WriteReportLine(const char* pLine) +{ + fwrite(pLine, strlen(pLine), 1, file); +} + + +void ExceptionHandler::WriteReportLineF(const char* format, ...) +{ + va_list args; + va_start(args, format); + int length = OVR_vsnprintf(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), format, args); + if(length >= (int)OVR_ARRAY_COUNT(scratchBuffer)) // If we didn't have enough space... + length = (OVR_ARRAY_COUNT(scratchBuffer) - 1); // ... use what we have. + va_end(args); + + fwrite(scratchBuffer, length, 1, file); +} + + +// Thread <name> <handle> <id> +// 0 <module> <address> <function> <file>:<line> +// 1 <module> <address> <function> <file>:<line> +// . . . +// +void ExceptionHandler::WriteThreadCallstack(ThreadHandle threadHandle, ThreadSysId threadSysId, const char* additionalInfo) +{ + // We intentionally do not directly use the SymbolInfo::ReportThreadCallstack function because that function allocates memory, + // which we cannot do due to possibly being within an exception handler. + + // Print the header + char threadName[32]; + char threadHandleStr[32]; + char threadSysIdStr[32]; + char stackBaseStr[24]; + char stackLimitStr[24]; + char stackCurrentStr[24]; + void* pStackBase; + void* pStackLimit; + bool isExceptionThread = (threadSysId == exceptionInfo.threadSysId); + + #if defined(OVR_OS_MS) && (OVR_PTR_SIZE == 8) + void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.Rsp : nullptr; // We would need to suspend the thread, get its context, resume it, then read the rsp register. It turns out we are already doing that suspend/resume below in the backtrace call. + #elif defined(OVR_OS_MS) + void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.Esp : nullptr; + #elif defined(OVR_OS_MAC) && (OVR_PTR_SIZE == 8) + void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.threadState.uts.ts64.__rsp : nullptr; + #elif defined(OVR_OS_MAC) + void* pStackCurrent = (threadSysId == exceptionInfo.threadSysId) ? (void*)exceptionInfo.cpuContext.threadState.uts.ts32.__esp : nullptr; + #elif defined(OVR_OS_LINUX) + void* pStackCurrent = nullptr; // To do. + #endif + + OVR::GetThreadStackBounds(pStackBase, pStackLimit, threadHandle); + + OVR::Thread::GetThreadName(threadName, OVR_ARRAY_COUNT(threadName), threadName); + SprintfThreadHandle(threadHandleStr, OVR_ARRAY_COUNT(threadHandleStr), threadHandle); + SprintfThreadSysId(threadSysIdStr, OVR_ARRAY_COUNT(threadSysIdStr), threadSysId); + SprintfAddress(stackBaseStr, OVR_ARRAY_COUNT(stackBaseStr), pStackBase); + SprintfAddress(stackLimitStr, OVR_ARRAY_COUNT(stackLimitStr), pStackLimit); + SprintfAddress(stackCurrentStr, OVR_ARRAY_COUNT(stackCurrentStr), pStackCurrent); + + if(threadName[0]) + WriteReportLineF("Thread \"%s\" handle: %s, id: %s, stack base: %s, stack limit: %s, stack current: %s, %s\r\n", threadName, threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr, stackCurrentStr, additionalInfo ? additionalInfo : ""); + else + WriteReportLineF("Thread handle: %s, id: %s, stack base: %s, stack limit: %s, stack current: %s, %s\r\n", threadHandleStr, threadSysIdStr, stackBaseStr, stackLimitStr, stackCurrentStr, additionalInfo ? additionalInfo : ""); + + // Print the backtrace info + void* addressArray[64]; + size_t addressCount = symbolLookup.GetBacktraceFromThreadSysId(addressArray, OVR_ARRAY_COUNT(addressArray), 0, threadSysId); + SymbolInfo symbolInfo; + const char* pModuleName; + size_t backtraceSkipCount = 0; + + if(isExceptionThread) + { + // If this thread is the exception thread, skip some frames. + #if defined(OVR_OS_MS) + size_t i, iEnd = MIN(16, addressCount); + + for(i = 0; i < iEnd; i++) + { + symbolLookup.LookupSymbol((uint64_t)addressArray[i], symbolInfo); + if(strstr(symbolInfo.function, "UserExceptionDispatcher") != nullptr) + break; + } + + if(i < iEnd) // If found... + backtraceSkipCount = i; + else if(addressCount >= 9) // Else default to 9, which is coincidentally what works. + backtraceSkipCount = 9; + else + backtraceSkipCount = 0; + + addressArray[backtraceSkipCount] = exceptionInfo.pExceptionInstructionAddress; + #endif + } + + if(addressCount == 0) + { + WriteReportLine("<Unable to read backtrace>\r\n\r\n"); + } + else + { + for(size_t i = backtraceSkipCount; i < addressCount; ++i) + { + symbolLookup.LookupSymbol((uint64_t)addressArray[i], symbolInfo); + + if(symbolInfo.pModuleInfo && symbolInfo.pModuleInfo->name[0]) + pModuleName = symbolInfo.pModuleInfo->name; + else + pModuleName = "(unknown module)"; + + char addressStr[24]; + SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), addressArray[i]); + + if(symbolInfo.filePath[0]) + WriteReportLineF("%-2u %-24s %s %s+%d %s:%d\r\n%s", (unsigned)i, pModuleName, addressStr, + symbolInfo.function, symbolInfo.functionOffset, symbolInfo.filePath, + symbolInfo.fileLineNumber, (i + 1) == addressCount ? "\r\n" : ""); + else + WriteReportLineF("%-2u %-24s %s %s+%d\r\n%s", (unsigned)i, pModuleName, addressStr, + symbolInfo.function, symbolInfo.functionOffset, (i + 1) == addressCount ? "\r\n" : ""); // If this is the last line, append another \r\n. + } + } +} + + +void ExceptionHandler::WriteReport() +{ + // It's important that we don't allocate any memory here if we can help it. + using namespace OVR; + + if(strstr(reportFilePath, "%s")) // If the user-specified file path includes a date/time component... + { + char dateTimeBuffer[64]; + FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, true); + OVR_snprintf(reportFilePathActual, OVR_ARRAY_COUNT(reportFilePathActual), reportFilePath, dateTimeBuffer); + } + else + { + OVR_strlcpy(reportFilePathActual, reportFilePath, OVR_ARRAY_COUNT(reportFilePathActual)); + } + + file = fopen(reportFilePathActual, "w"); + OVR_ASSERT(file != nullptr); + if(!file) + return; + + symbolLookup.Initialize(); + + { + // Exception information + WriteReportLine("Exception Info\r\n"); + + WriteReportLineF("Exception report file: %s\r\n", reportFilePathActual); + + #if defined(OVR_OS_MS) + if(miniDumpFilePath[0]) + WriteReportLineF("Exception minidump file: %s\r\n", minidumpFilePathActual); + #endif + + char dateTimeBuffer[64]; + FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, false); + WriteReportLineF("Time (GMT): %s\r\n", dateTimeBuffer); + + FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.timeVal, true, true, true, false); + WriteReportLineF("Time (local): %s\r\n", dateTimeBuffer); + WriteReportLineF("Thread name: %s\r\n", exceptionInfo.threadName[0] ? exceptionInfo.threadName : "(not available)"); // It's never possible on Windows to get thread names, as they are stored in the debugger at runtime. + + SprintfThreadHandle(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.threadHandle); + OVR_strlcat(scratchBuffer, "\r\n", OVR_ARRAY_COUNT(scratchBuffer)); + WriteReportLine("Thread handle: "); + WriteReportLine(scratchBuffer); + + SprintfThreadSysId(scratchBuffer, OVR_ARRAY_COUNT(scratchBuffer), exceptionInfo.threadSysId); + OVR_strlcat(scratchBuffer, "\r\n", OVR_ARRAY_COUNT(scratchBuffer)); + WriteReportLine("Thread sys id: "); + WriteReportLine(scratchBuffer); + + char addressStr[24]; + SprintfAddress(addressStr, OVR_ARRAY_COUNT(addressStr), exceptionInfo.pExceptionInstructionAddress); + WriteReportLineF("Exception instruction address: %s (see callstack below)\r\n", addressStr); + WriteReportLineF("Exception description: %s\r\n", exceptionInfo.exceptionDescription); + + if(symbolLookup.LookupSymbol((uint64_t)exceptionInfo.pExceptionInstructionAddress, exceptionInfo.symbolInfo)) + { + if(exceptionInfo.symbolInfo.filePath[0]) + WriteReportLineF("Exception location: %s (%d)\r\n", exceptionInfo.symbolInfo.filePath, exceptionInfo.symbolInfo.fileLineNumber); + else + WriteReportLineF("Exception location: %s (%d)\r\n", exceptionInfo.symbolInfo.function, exceptionInfo.symbolInfo.functionOffset); + } + + // To consider: print exceptionInfo.cpuContext registers + } + + // OVR information + WriteReportLine("\r\nOVR Info\r\n"); + WriteReportLineF("OVR time: %f\r\n", ovr_GetTimeInSeconds()); + WriteReportLineF("OVR version: %s\r\n", ovr_GetVersionString()); + + // OVR util information + // The following would be useful to use if they didn't allocate memory, which we can't do. + // To do: see if we can have versions of the functions below which don't allocate memory + // or allocate it safely (e.g. use an alternative heap). + // String OVR::GetDisplayDriverVersion(); + // String OVR::GetCameraDriverVersion(); + + // OVR HMD information + WriteReportLine("\r\nOVR HMD Info\r\n"); + + const OVR::List<OVR::CAPI::HMDState>& hmdStateList = OVR::CAPI::HMDState::GetHMDStateList(); + const OVR::CAPI::HMDState* pHMDState = hmdStateList.GetFirst(); + + if(hmdStateList.IsNull(pHMDState)) + { + WriteReportLine("No HMDs found.\r\n"); + } + + while(!hmdStateList.IsNull(pHMDState)) + { + if(pHMDState->pProfile) + { + const char* user = pHMDState->pProfile->GetValue(OVR_KEY_USER); + + if(user) + WriteReportLineF("Profile user: %s\r\n", reportPrivacyEnabled ? "<disabled by report privacy settings>" : user); + else + WriteReportLine("Null profile user\r\n"); + + float NeckEyeDistance[2]; + float EyeToNoseDistance[2]; + float MaxEyeToPlateDist[2]; + pHMDState->pProfile->GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, NeckEyeDistance, 2); + pHMDState->pProfile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, EyeToNoseDistance, 2); + pHMDState->pProfile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, MaxEyeToPlateDist, 2); + + WriteReportLineF("Player height: %f, eye height: %f, IPD: %f, Neck eye distance: %f,%f, eye relief dial: %d, eye to nose distance: %f,%f, max eye to plate distance: %f,%f, custom eye render: %s\r\n", + pHMDState->pProfile->GetFloatValue(OVR_KEY_PLAYER_HEIGHT, 0.f), + pHMDState->pProfile->GetFloatValue(OVR_KEY_EYE_HEIGHT, 0.f), + pHMDState->pProfile->GetFloatValue(OVR_KEY_IPD, 0.f), + NeckEyeDistance[0], NeckEyeDistance[1], + pHMDState->pProfile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, 0), + EyeToNoseDistance[0], EyeToNoseDistance[1], + MaxEyeToPlateDist[0], MaxEyeToPlateDist[1], + pHMDState->pProfile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, false) ? "yes" : "no"); + + // Not currently used: + // OVR_KEY_NAME + // OVR_KEY_GENDER + // OVR_KEY_EYE_CUP + // OVR_KEY_CAMERA_POSITION + } + else + { + WriteReportLine("Null HMD profile\r\n"); + } + + if(pHMDState->pHmdDesc) // This should usually be true. + { + WriteReportLineF("HMD %d: Type: %u ProductName: %s, Manufacturer: %s VendorId: %d, ProductId: %d, SerialNumber: %s, FirmwareMajor: %d, FirmwareMinor: %d, Resolution: %dx%d, DisplayDeviceName: %s, DisplayId: %d\r\n", + 0, (unsigned)pHMDState->pHmdDesc->Type, pHMDState->pHmdDesc->ProductName, pHMDState->pHmdDesc->Manufacturer, pHMDState->pHmdDesc->VendorId, + pHMDState->pHmdDesc->ProductId, pHMDState->pHmdDesc->SerialNumber, pHMDState->pHmdDesc->FirmwareMajor, pHMDState->pHmdDesc->FirmwareMinor, + pHMDState->pHmdDesc->Resolution.w, pHMDState->pHmdDesc->Resolution.h, pHMDState->pHmdDesc->DisplayDeviceName, pHMDState->pHmdDesc->DisplayId); + + // HSW display state + ovrHSWDisplayState hswDS; + ovrHmd_GetHSWDisplayState(pHMDState->pHmdDesc, &hswDS); + WriteReportLineF("HSW displayed for hmd: %s\r\n", hswDS.Displayed ? "yes" : "no"); + } + + char threadIdStr[24]; + SprintfAddress(threadIdStr, OVR_ARRAY_COUNT(threadIdStr), pHMDState->BeginFrameThreadId); + + WriteReportLineF("Hmd Caps: %x, Hmd Service Caps: %x, Latency test active: %s, Last frame time: %f, Last get frame time: %f, Rendering configred: %s, Begin frame called: %s, Begin frame thread id: %s\r\n", + pHMDState->EnabledHmdCaps, pHMDState->EnabledServiceHmdCaps, pHMDState->LatencyTestActive ? "yes" : "no", pHMDState->LastFrameTimeSeconds, pHMDState->LastGetFrameTimeSeconds, pHMDState->RenderingConfigured ? "yes" : "no", + pHMDState->BeginFrameCalled ? "yes" : "no", threadIdStr); + + if(pHMDState->pLastError) + { + WriteReportLineF("OVR last error for hmd: %s\r\n", pHMDState->pLastError); + } + + pHMDState = hmdStateList.GetNext(pHMDState); + } + + #if defined(OVR_OS_WIN32) + { + WriteReportLine("\r\nApp Info\r\n"); + + // Print the app path. + char appPath[MAX_PATH]; + GetCurrentProcessFilePath(appPath, OVR_ARRAY_COUNT(appPath)); + WriteReportLineF("Process path: %s\r\n", appPath); + + #if (OVR_PTR_SIZE == 4) + WriteReportLine("App format: 32 bit\r\n"); + #else + WriteReportLine("App format: 64 bit\r\n"); + #endif + + // Print the app version + wchar_t pathW[MAX_PATH] = {}; + GetModuleFileNameW(0, pathW, (DWORD)OVR_ARRAY_COUNT(pathW)); + DWORD dwUnused; + DWORD dwSize = GetFileVersionInfoSizeW(pathW, &dwUnused); + scratchBuffer[0] = 0; + + if(dwSize > 0) + { + void* const pVersionData = SafeMMapAlloc(dwSize); + + if(pVersionData) + { + if(GetFileVersionInfoW(pathW, 0, dwSize, pVersionData)) + { + VS_FIXEDFILEINFO* pFFI; + UINT size; + + if(VerQueryValueA(pVersionData, "\\", (void**)&pFFI, &size)) + { + WriteReportLineF("App version: %u.%u.%u.%u\r\n", + HIWORD(pFFI->dwFileVersionMS), LOWORD(pFFI->dwFileVersionMS), + HIWORD(pFFI->dwFileVersionLS), LOWORD(pFFI->dwFileVersionLS)); + } + } + + SafeMMapFree(pVersionData, dwSize); + } + } + + if(!scratchBuffer[0]) // If version info couldn't be found or read... + WriteReportLine("App version info not present\r\n"); + } + + { + WriteReportLine("\r\nSystem Info\r\n"); + + OSVERSIONINFOEXW vi; + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + GetVersionExW((LPOSVERSIONINFOW)&vi); // Cast to the older type. + + char osVersionName[256]; + GetOSVersionName(osVersionName, OVR_ARRAY_COUNT(osVersionName)); + WriteReportLineF("OS name: %s, version: %u.%u build %u, %s, platform id: %u, service pack: %ls\r\n", + osVersionName, vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber, Is64BitOS() ? "64 bit" : "32 bit", + vi.dwPlatformId, vi.szCSDVersion[0] ? vi.szCSDVersion : L"<none>"); + + WriteReportLineF("Debugger present: %s\r\n", OVRIsDebuggerPresent() ? "yes" : "no"); + + // System info + SYSTEM_INFO systemInfo; + GetNativeSystemInfo(&systemInfo); + + WriteReportLineF("Processor count: %u\r\n", systemInfo.dwNumberOfProcessors); + + // Windows Vista and later: + // BOOL WINAPI GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, PDWORD ReturnLength); + + if(systemInfo.wProcessorArchitecture == 0) + WriteReportLineF("Processor type: x86\r\n"); + else if(systemInfo.wProcessorArchitecture == 9) + WriteReportLineF("Processor type: x86-64\r\n"); + else if(systemInfo.wProcessorArchitecture == 10) + WriteReportLineF("Processor type: x86 on x86-64\r\n"); + + WriteReportLineF("Processor level: %u\r\n", systemInfo.wProcessorLevel); + WriteReportLineF("Processor revision: %u\r\n", systemInfo.wProcessorRevision); + + // Memory information + MEMORYSTATUSEX memoryStatusEx; + memset(&memoryStatusEx, 0, sizeof(memoryStatusEx)); + memoryStatusEx.dwLength = sizeof(memoryStatusEx); + GlobalMemoryStatusEx(&memoryStatusEx); + + WriteReportLineF("Memory load: %d%%\r\n", memoryStatusEx.dwMemoryLoad); + WriteReportLineF("Total physical memory: %I64d MiB\r\n", memoryStatusEx.ullTotalPhys / (1024 * 1024)); // Or are Mebibytes equal to (1024 * 1000) + WriteReportLineF("Available physical memory: %I64d MiB\r\n", memoryStatusEx.ullAvailPhys / (1024 * 1024)); + WriteReportLineF("Total page file memory: %I64d MiB\r\n", memoryStatusEx.ullTotalPageFile / (1024 * 1024)); + WriteReportLineF("Available page file memory: %I64d MiB\r\n", memoryStatusEx.ullAvailPageFile / (1024 * 1024)); + WriteReportLineF("Total virtual memory: %I64d MiB\r\n", memoryStatusEx.ullTotalVirtual / (1024 * 1024)); + WriteReportLineF("Free virtual memory: %I64d MiB\r\n", memoryStatusEx.ullAvailVirtual / (1024 * 1024)); + + DISPLAY_DEVICE dd; + memset(&dd, 0, sizeof(DISPLAY_DEVICE)); + dd.cb = sizeof(DISPLAY_DEVICE); + + for(int i = 0; EnumDisplayDevicesW(nullptr, (DWORD)i, &dd, EDD_GET_DEVICE_INTERFACE_NAME); ++i) + { + WriteReportLineF("Display Device %d name: %ls, context: %ls, primary: %s, mirroring: %s\r\n", + i, dd.DeviceName, dd.DeviceString, (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) ? "yes" : "no", (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ? "yes" : "no"); + } + } + + // Print video card information + // http://msdn.microsoft.com/en-us/library/aa394512%28v=vs.85%29.aspx + { + IWbemLocator* pIWbemLocator = nullptr; + BSTR bstrServer = nullptr; + IWbemServices* pIWbemServices = nullptr; + BSTR bstrWQL = nullptr; + BSTR bstrPath = nullptr; + IEnumWbemClassObject* pEnum = nullptr; + + CoInitializeEx(nullptr, COINIT_MULTITHREADED); + + HRESULT hr = CoCreateInstance(__uuidof(WbemLocator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator); + if(FAILED(hr)) + goto End; + + bstrServer = SysAllocString(L"\\\\.\\root\\cimv2"); + hr = pIWbemLocator->ConnectServer(bstrServer, nullptr, nullptr, 0L, 0L, nullptr, nullptr, &pIWbemServices); + if(FAILED(hr)) + goto End; + + hr = CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, + RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DEFAULT); + if(FAILED(hr)) + goto End; + + bstrWQL = SysAllocString(L"WQL"); + bstrPath = SysAllocString(L"select * from Win32_VideoController"); + hr = pIWbemServices->ExecQuery(bstrWQL, bstrPath, WBEM_FLAG_FORWARD_ONLY, nullptr, &pEnum); + if(FAILED(hr)) + goto End; + + ULONG uReturned; + IWbemClassObject* pObj = nullptr; + hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &uReturned); + if(FAILED(hr)) + goto End; + + WriteReportLine("\r\nDisplay adapter list\r\n"); + + for(unsigned i = 0; SUCCEEDED(hr) && uReturned; i++) + { + char sString[256]; + VARIANT var; + + if(i > 0) + WriteReportLine("\r\n"); + + WriteReportLineF("Info for display adapter %u\r\n", i); + + hr = pObj->Get(L"Name", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr); + WriteReportLineF("Display Adapter Name: %s\r\n", sString); + } + + hr = pObj->Get(L"AdapterRAM", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WriteReportLineF("Display Adapter RAM: %u %s\r\n", + ((uint32_t)var.lVal > (1024*1024*1024) ? (uint32_t)var.lVal/(1024*1024*1024) : (uint32_t)var.lVal/(1024*1024)), ((uint32_t)var.lVal > (1024*1024*1024) ? "GiB" : "MiB")); + } + + hr = pObj->Get(L"DeviceID", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr); + WriteReportLineF("Display Adapter DeviceID: %s\r\n", sString); + } + + hr = pObj->Get(L"DriverVersion", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr); + WriteReportLineF("Display Adapter DriverVersion: %s\r\n", sString); + } + + hr = pObj->Get(L"DriverDate", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + // http://technet.microsoft.com/en-us/library/ee156576.aspx + wchar_t year[5] = { var.bstrVal[0], var.bstrVal[1], var.bstrVal[2], var.bstrVal[3], 0 }; + wchar_t month[3] = { var.bstrVal[4], var.bstrVal[5], 0 }; + wchar_t monthDay[3] = { var.bstrVal[6], var.bstrVal[7], 0 }; + + WriteReportLineF("Display Adapter DriverDate (US format): %ls/%ls/%ls\r\n", month, monthDay, year); + } + + // VideoProcessor + hr = pObj->Get(L"VideoProcessor", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr); + WriteReportLineF("Display Adapter VideoProcessor %s\r\n", sString); + } + + hr = pObj->Get(L"VideoModeDescription", 0, &var, nullptr, nullptr); + if(SUCCEEDED(hr)) + { + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, sString, sizeof(sString), nullptr, nullptr); + WriteReportLineF("Display Adapter VideoModeDescription: %s\r\n", sString); + } + + pObj->Release(); + + hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &uReturned); + } + + End: + if(pEnum) + pEnum->Release(); + if(bstrPath) + SysFreeString(bstrPath); + if(bstrWQL) + SysFreeString(bstrWQL); + if(pIWbemServices) + pIWbemServices->Release(); + if(bstrServer) + SysFreeString(bstrServer); + if(pIWbemLocator) + pIWbemLocator->Release(); + + CoUninitialize(); + } + + { + // Print a list of threads. + DWORD currentProcessId = GetCurrentProcessId(); + HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, currentProcessId); // ICreateToolhelp32Snapshot actually ignores currentProcessId. + + if(hThreadSnap != INVALID_HANDLE_VALUE) + { + THREADENTRY32 te32; + te32.dwSize = sizeof(THREADENTRY32); + + if(Thread32First(hThreadSnap, &te32)) + { + WriteReportLine("\r\nThread list\r\n"); + + do { + if(te32.th32OwnerProcessID == currentProcessId) + { + HANDLE hThread = ConvertThreadSysIdToThreadHandle(te32.th32ThreadID); + + if(hThread) + { + char buffer[96]; // Can't use scratchBuffer, because it's used by WriteThreadCallstack. + OVR_snprintf(buffer, OVR_ARRAY_COUNT(buffer), "base priority: %ld, delta priority: %ld", te32.tpBasePri, te32.tpDeltaPri); + + bool threadIsExceptionThread = (te32.th32ThreadID == (DWORD)exceptionInfo.threadSysId); + if(threadIsExceptionThread) + OVR_strlcat(buffer, ", exception thread", OVR_ARRAY_COUNT(buffer)); + + WriteThreadCallstack(hThread, (OVR::ThreadSysId)te32.th32ThreadID, buffer); + FreeThreadHandle(hThread); + } + } + } while(Thread32Next(hThreadSnap, &te32)); + } + + CloseHandle(hThreadSnap); + } + } + + { + // Print a list of the current modules within this process. + // DbgHelp.dll also provides a EnumerateLoadedModules64 function. + // To do: Convert the code below to use the GetModuleInfoArray function which we now have. + #if defined(OVR_OS_CONSOLE) + struct MODULEINFO { + LPVOID lpBaseOfDll; + DWORD SizeOfImage; + LPVOID EntryPoint; + }; + HMODULE hModule = LoadLibraryW(L"toolhelpx.dll"); + #else + HMODULE hModule = LoadLibraryW(L"psapi.dll"); + #endif + + if(hModule) + { + typedef BOOL (WINAPI * ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE* phModule, DWORD cb, LPDWORD lpcbNeeded); + typedef DWORD (WINAPI * GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize); + typedef DWORD (WINAPI * GETMODULEFILENAMEEX) (HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize); + typedef BOOL (WINAPI * GETMODULEINFORMATION)(HANDLE hProcess, HMODULE hModule, MODULEINFO* pmi, DWORD nSize); + + #if defined(OVR_OS_CONSOLE) + ENUMPROCESSMODULES pEnumProcessModules = (ENUMPROCESSMODULES) (uintptr_t)GetProcAddress(hModule, "K32EnumProcessModules"); + GETMODULEBASENAME pGetModuleBaseName = (GETMODULEBASENAME) (uintptr_t)GetProcAddress(hModule, "K32GetModuleBaseNameW"); + GETMODULEFILENAMEEX pGetModuleFileNameEx = (GETMODULEFILENAMEEX) (uintptr_t)GetProcAddress(hModule, "K32GetModuleFileNameExW"); + GETMODULEINFORMATION pGetModuleInformation = (GETMODULEINFORMATION)(uintptr_t)GetProcAddress(hModule, "K32GetModuleInformation"); + #else + ENUMPROCESSMODULES pEnumProcessModules = (ENUMPROCESSMODULES) (uintptr_t)GetProcAddress(hModule, "EnumProcessModules"); + GETMODULEBASENAME pGetModuleBaseName = (GETMODULEBASENAME) (uintptr_t)GetProcAddress(hModule, "GetModuleBaseNameW"); + GETMODULEFILENAMEEX pGetModuleFileNameEx = (GETMODULEFILENAMEEX) (uintptr_t)GetProcAddress(hModule, "GetModuleFileNameExW"); + GETMODULEINFORMATION pGetModuleInformation = (GETMODULEINFORMATION)(uintptr_t)GetProcAddress(hModule, "GetModuleInformation"); + #endif + + HANDLE hProcess = GetCurrentProcess(); + HMODULE hModuleArray[200]; + DWORD cbNeeded; + + if(pEnumProcessModules(hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded)) + { + size_t actualModuleCount = (cbNeeded / sizeof(HMODULE)); + + if(actualModuleCount > OVR_ARRAY_COUNT(hModuleArray)) //If hModuleArray's capacity was not enough... + actualModuleCount = OVR_ARRAY_COUNT(hModuleArray); + + // Print a header + WriteReportLine("\r\nModule list\r\n"); + + #if (OVR_PTR_SIZE == 4) + WriteReportLine("Base Size Entrypoint Name Path\r\n"); + #else + WriteReportLine("Base Size Entrypoint Name Path\r\n"); + #endif + + // And go through the list one by one + for(size_t i = 0; i < actualModuleCount; i++) + { + MODULEINFO mi; + size_t length; + + if(!pGetModuleInformation(hProcess, hModuleArray[i], &mi, sizeof(mi))) + { + mi.EntryPoint = nullptr; + mi.lpBaseOfDll = nullptr; + mi.SizeOfImage = 0; + } + + // Write the base name. + wchar_t name[MAX_PATH + 3]; + name[0] = '"'; + if(pGetModuleBaseName(hProcess, hModuleArray[i], name + 1, MAX_PATH)) + length = wcslen(name); + else + { + wcscpy(name + 1, L"(unknown)"); + length = 10; + } + + name[length] = '"'; + name[length + 1] = '\0'; + + // Write the path + wchar_t path[MAX_PATH + 3]; + path[0] = '"'; + if(pGetModuleFileNameEx(hProcess, hModuleArray[i], path + 1, MAX_PATH)) + length = wcslen(path); + else + { + wcscpy(path + 1, L"(unknown)"); + length = 10; + } + path[length] = '"'; + path[length + 1] = '\0'; + + #if (OVR_PTR_SIZE == 4) + WriteReportLineF("0x%08x, 0x%08x 0x%08x %-24ls %ls\r\n", (uint32_t)mi.lpBaseOfDll, (uint32_t)mi.SizeOfImage, (uint32_t)mi.EntryPoint, name, path); + #else + WriteReportLineF("0x%016I64x 0x%016I64x 0x%016I64x %-24ls %ls\r\n", (uint64_t)mi.lpBaseOfDll, (uint64_t)mi.SizeOfImage, (uint64_t)mi.EntryPoint, name, path); + #endif + } + } + } + } + + { + // Print a list of processes. + // DbgHelp.dll provides a SymEnumProcesses function, but it's available with DbgHelp.dll v6.2 which doesn't ship with Windows until Windows 8. + WriteReportLine("\r\nProcess list\r\n"); + + if(reportPrivacyEnabled) + WriteReportLine("Disabled by report privacy settings\r\n"); + else + { + HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if(hProcessSnapshot != INVALID_HANDLE_VALUE) + { + PROCESSENTRY32W pe32; + memset(&pe32, 0, sizeof(pe32)); + pe32.dwSize = sizeof(pe32); + + if(Process32FirstW(hProcessSnapshot, &pe32)) + { + WriteReportLine("Process Id File\r\n"); + + do { + // Try to get the full path to the process, as pe32.szExeFile holds only the process file name. + // This will typically fail with a privilege error unless this process has debug privileges: http://support.microsoft.com/kb/131065/en-us + wchar_t filePathW[MAX_PATH]; + const wchar_t* pFilePathW = pe32.szExeFile; + HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); // With Windows Vista+ we can use PROCESS_QUERY_LIMITED_INFORMATION. + if(hProcess) + { + if(GetProcessImageFileName(hProcess, filePathW, (DWORD)OVR_ARRAY_COUNT(filePathW))) + pFilePathW = filePathW; + } + + WriteReportLineF("0x%08x %ls\r\n", pe32.th32ProcessID, pFilePathW); + } while(Process32NextW(hProcessSnapshot, &pe32)); + } + + CloseHandle(hProcessSnapshot); + } + else + { + WriteReportLine("Unable to read process list\r\n"); + } + } + } + + #elif defined(OVR_OS_APPLE) + + WriteReportLine("\r\nApp Info\r\n"); + + // App path + const pid_t processId = getpid(); + WriteReportLineF("Process id: ", "%lld (0x%llx)\r\n", (int64_t)processId, (int64_t)processId); + + char appPath[PATH_MAX]; + GetCurrentProcessFilePath(appPath, OVR_ARRAY_COUNT(appPath)); + WriteReportLineF("Process path: %s\r\n", appPath); + + #if (OVR_PTR_SIZE == 4) + WriteReportLine("App format: 32 bit\r\n"); + #else + WriteReportLine("App format: 64 bit\r\n"); + #endif + + // App version + // To do. + + // System Info + WriteReportLine("\r\nSystem Info\r\n"); + + char osVersionName[256]; + GetOSVersionName(osVersionName, OVR_ARRAY_COUNT(osVersionName)); + WriteReportLineF("OS name: %s, %s\r\n", osVersionName, Is64BitOS() ? "64 bit" : "32 bit"); + + int name[2]; + int intValue; + size_t length; + char tempBuffer[256]; + + name[0] = CTL_KERN; + name[1] = KERN_OSTYPE; + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0) + { + WriteReportLineF("KERN_OSTYPE: %s\r\n", tempBuffer); + } + + name[0] = CTL_KERN; + name[1] = KERN_OSREV; + length = sizeof(intValue); + intValue = 0; + if(sysctl(name, 2, &intValue, &length, nullptr, 0) == 0) + { + WriteReportLineF("KERN_OSREV: %d\r\n", intValue); + } + + name[0] = CTL_KERN; + name[1] = KERN_OSRELEASE; + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0) + WriteReportLineF("KERN_OSRELEASE: %s\r\n", tempBuffer); + + name[0] = CTL_HW; + name[1] = HW_MACHINE; + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0) + WriteReportLineF("HW_MACHINE: %s\r\n", tempBuffer); + + name[0] = CTL_HW; + name[1] = HW_MODEL; + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctl(name, 2, tempBuffer, &length, nullptr, 0) == 0) + WriteReportLineF("sHW_MODEL: %s\r\n", tempBuffer); + + name[0] = CTL_HW; + name[1] = HW_NCPU; + length = sizeof(intValue); + intValue = 0; + if(sysctl(name, 2, &intValue, &length, nullptr, 0) == 0) + WriteReportLineF("HW_NCPU: %d\r\n", intValue); + + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctlbyname("machdep.cpu.brand_string", &tempBuffer, &length, nullptr, 0) == 0) + WriteReportLineF("machdep.cpu.brand_string: %s\r\n", tempBuffer); + + length = sizeof(tempBuffer); + tempBuffer[0] = 0; + if(sysctlbyname("hw.acpi.thermal.tz0.temperature", &tempBuffer, &length, nullptr, 0) == 0) + WriteReportLineF("hw.acpi.thermal.tz0.temperature: %s\r\n", tempBuffer); + + host_basic_info_data_t hostinfo; + mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; + kern_return_t kr = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostinfo, &count); + + if(kr == KERN_SUCCESS) + { + const uint64_t memoryMib = (uint64_t)hostinfo.max_mem / (1024 * 1024); + WriteReportLineF("System memory: %lld Mib (%.1f Gib)\r\n", memoryMib, (double)memoryMib / 1024); + } + + // Video card info + // To do. + + // Thread list + mach_port_t taskSelf = mach_task_self(); + thread_act_port_array_t threadArray; + mach_msg_type_number_t threadCount; + + kern_return_t result = task_threads(taskSelf, &threadArray, &threadCount); + + if(result == KERN_SUCCESS) + { + WriteReportLine("\r\nThread list\r\n"); + + for(mach_msg_type_number_t i = 0; i < threadCount; i++) + { + union TBIUnion{ + natural_t words[THREAD_INFO_MAX]; + thread_basic_info tbi; + }; + + TBIUnion tbiUnion; + mach_port_t thread = threadArray[i]; + pthread_t pthread = pthread_from_mach_thread_np(thread); // We assume the thread was created through pthreads. + + char threadState[32] = "unknown"; + mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX; + result = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&tbiUnion, &threadInfoCount); + + if(result == KERN_SUCCESS) + { + const char* state; + + switch (tbiUnion.tbi.run_state) + { + case TH_STATE_HALTED: state = "halted"; break; + case TH_STATE_RUNNING: state = "running"; break; + case TH_STATE_STOPPED: state = "stopped"; break; + case TH_STATE_UNINTERRUPTIBLE: state = "uninterruptible"; break; + case TH_STATE_WAITING: state = "waiting"; break; + default: state = "<unknown>"; break; + } + + OVR_snprintf(threadState, OVR_ARRAY_COUNT(threadState), "%s", state); + if(tbiUnion.tbi.flags & TH_FLAGS_IDLE) + OVR_strlcat(threadState, ", idle", sizeof(threadState)); + if(tbiUnion.tbi.flags & TH_FLAGS_SWAPPED) + OVR_strlcat(threadState, ", swapped", sizeof(threadState)); + } + + thread_identifier_info threadIdentifierInfo; + memset(&threadIdentifierInfo, 0, sizeof(threadIdentifierInfo)); + + mach_msg_type_number_t threadIdentifierInfoCount = THREAD_IDENTIFIER_INFO_COUNT; + thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&threadIdentifierInfo, &threadIdentifierInfoCount); + + proc_threadinfo procThreadInfo; + memset(&procThreadInfo, 0, sizeof(procThreadInfo)); + result = proc_pidinfo(processId, PROC_PIDTHREADINFO, threadIdentifierInfo.thread_handle, &procThreadInfo, sizeof(procThreadInfo)); + OVR_UNUSED(result); + + char buffer[256]; // Can't use scratchBuffer, because it's used by WriteThreadCallstack. + OVR_snprintf(buffer, OVR_ARRAY_COUNT(buffer), "state: %s, suspend count: %d, kernel priority: %d", threadState, (int)tbiUnion.tbi.suspend_count, (int)procThreadInfo.pth_curpri); + + bool threadIsExceptionThread = (thread == exceptionInfo.threadSysId); + if(threadIsExceptionThread) + OVR_strlcat(buffer, ", exception thread", OVR_ARRAY_COUNT(buffer)); + + WriteThreadCallstack(pthread, thread, buffer); + } + + vm_deallocate(taskSelf, (vm_address_t)threadArray, threadCount * sizeof(thread_act_t)); + } + + + WriteReportLine("\r\nModule list\r\n"); + + const size_t mifCapacity = 256; + const size_t mifAllocSize = mifCapacity * sizeof(ModuleInfo); + ModuleInfo* moduleInfoArray = (ModuleInfo*)SafeMMapAlloc(mifAllocSize); + + if(moduleInfoArray) + { + #if (OVR_PTR_SIZE == 4) + WriteReportLine("Base Size Name Path\r\n"); + #else + WriteReportLine("Base Size Name Path\r\n"); + #endif + + size_t moduleCount = symbolLookup.GetModuleInfoArray(moduleInfoArray, mifCapacity); + if(moduleCount > mifCapacity) + moduleCount = mifCapacity; + + for(size_t i = 0; i < moduleCount; i++) + { + const ModuleInfo& mi = moduleInfoArray[i]; + + #if (OVR_PTR_SIZE == 4) + WriteReportLineF("0x%08x, 0x%08x %-24s %s\r\n", (uint32_t)mi.baseAddress, (uint32_t)mi.size, mi.name, mi.filePath); + #else + WriteReportLineF("0x%016llx 0x%016llx %-24s %s\r\n", (uint64_t)mi.baseAddress, (uint64_t)mi.size, mi.name, mi.filePath); + #endif + } + + SafeMMapFree(moduleInfoArray, mifAllocSize); + } + + + WriteReportLine("\r\nProcess list\r\n"); + + if(reportPrivacyEnabled) + WriteReportLine("Disabled by report privacy settings\r\n"); + else + { + WriteReportLine("Process Id File\r\n"); + + pid_t pidArray[1024]; + int processCount = proc_listpids(PROC_ALL_PIDS, 0, pidArray, sizeof(pidArray)); // Important that we use sizeof not OVR_ARRAY_COUNT. + char processFilePath[PATH_MAX]; + + for(int i = 0; i < processCount; i++) + { + if(proc_pidpath(pidArray[i], processFilePath, sizeof(processFilePath)) > 0) + WriteReportLineF("%-10d %s\r\n", pidArray[i], processFilePath); + } + + if(!processCount) + WriteReportLine("Unable to read process list\r\n"); + } + + #elif defined(OVR_OS_UNIX) + Is64BitOS(); + GetCurrentProcessFilePath(nullptr, 0); + GetFileNameFromPath(nullptr); + GetOSVersionName(nullptr, 0); + + #endif // OVR_OS_MS + + symbolLookup.Shutdown(); + + fclose(file); + file = nullptr; +} + + +void ExceptionHandler::WriteMiniDump() +{ + if(strstr(miniDumpFilePath, "%s")) // If the user-specified file path includes a date/time component... + { + char dateTimeBuffer[64]; + FormatDateTime(dateTimeBuffer, OVR_ARRAY_COUNT(dateTimeBuffer), exceptionInfo.timeVal, true, true, false, true); + OVR_snprintf(minidumpFilePathActual, OVR_ARRAY_COUNT(minidumpFilePathActual), miniDumpFilePath, dateTimeBuffer); + } + else + { + OVR_strlcpy(minidumpFilePathActual, miniDumpFilePath, OVR_ARRAY_COUNT(minidumpFilePathActual)); + } + + #if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) || (defined(OVR_OS_MS) && defined(OVR_OS_CONSOLE)) + #if defined(OVR_OS_CONSOLE) + typedef BOOL (WINAPI * MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE dumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PVOID CallbackParam); + HMODULE hModuleDbgHelp = LoadLibraryW(L"toolhelpx.dll"); + #else + typedef BOOL (WINAPI * MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE dumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + HMODULE hModuleDbgHelp = LoadLibraryW(L"DbgHelp.dll"); + #endif + + MINIDUMPWRITEDUMP pMiniDumpWriteDump = hModuleDbgHelp ? (MINIDUMPWRITEDUMP)(void*)GetProcAddress(hModuleDbgHelp, "MiniDumpWriteDump") : nullptr; + + if(pMiniDumpWriteDump) + { + wchar_t miniDumpFilePathW[OVR_MAX_PATH]; + OVR::UTF8Util::DecodeString(miniDumpFilePathW, minidumpFilePathActual, -1); // Problem: DecodeString provides no way to specify the destination capacity. + + HANDLE hFile = CreateFileW(miniDumpFilePathW, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0); + + if(hFile != INVALID_HANDLE_VALUE) + { + MINIDUMP_EXCEPTION_INFORMATION minidumpExceptionInfo = { ::GetCurrentThreadId(), pExceptionPointers, TRUE }; + + #if defined(OVR_OS_CONSOLE) + BOOL result = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, + (MINIDUMP_TYPE)miniDumpType, &exceptionInfo, + (CONST PMINIDUMP_USER_STREAM_INFORMATION)nullptr, nullptr); + #else + BOOL result = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, + (MINIDUMP_TYPE)miniDumpFlags, &minidumpExceptionInfo, + (CONST PMINIDUMP_USER_STREAM_INFORMATION)nullptr, (CONST PMINIDUMP_CALLBACK_INFORMATION)nullptr); + #endif + + OVR_ASSERT_AND_UNUSED(result, result); + CloseHandle(hFile); + hFile = 0; + } + else + { + OVR_ASSERT(pMiniDumpWriteDump); // OVR_FAIL_F(("ExceptionHandler::WriteMiniDump: Failed to create minidump file at %s", minidumpFilePathActual)); + } + } + + FreeLibrary(hModuleDbgHelp); + #else + // Some platforms support various forms or exception reports and core dumps which are automatically generated upon us + // returning from our own exception handling. We might want to put something here if we are using a custom version of + // this, such as Google Breakpad. + #endif +} + + +void ExceptionHandler::SetExceptionListener(ExceptionListener* pExceptionListener, uintptr_t userValue) +{ + exceptionListener = pExceptionListener; + exceptionListenerUserValue = userValue; +} + + +void ExceptionHandler::SetAppDescription(const char* pAppDescription) +{ + appDescription = pAppDescription; +} + + +void ExceptionHandler::SetExceptionPaths(const char* exceptionReportPath, const char* exceptionMiniDumpFilePath) +{ + char tempPath[OVR_MAX_PATH]; + + if(exceptionReportPath) + { + if(OVR_stricmp(exceptionReportPath, "default") == 0) + { + GetUserDocumentsDirectory(tempPath, OVR_ARRAY_COUNT(tempPath)); + OVR::OVR_strlcat(tempPath, "Exception Report (%s).txt", OVR_ARRAY_COUNT(tempPath)); + exceptionReportPath = tempPath; + } + + OVR_strlcpy(reportFilePath, exceptionReportPath, OVR_ARRAY_COUNT(reportFilePath)); + } + else + { + reportFilePath[0] = '\0'; + } + + if(exceptionMiniDumpFilePath) + { + if(OVR_stricmp(exceptionMiniDumpFilePath, "default") == 0) + { + GetUserDocumentsDirectory(tempPath, OVR_ARRAY_COUNT(tempPath)); + OVR::OVR_strlcat(tempPath, "Exception Minidump (%s).mdmp", OVR_ARRAY_COUNT(tempPath)); + exceptionMiniDumpFilePath = tempPath; + } + + OVR_strlcpy(miniDumpFilePath, exceptionMiniDumpFilePath, OVR_ARRAY_COUNT(miniDumpFilePath)); + } + else + { + miniDumpFilePath[0] = '\0'; + } +} + + +void ExceptionHandler::SetCodeBaseDirectoryPaths(const char* codeBaseDirectoryPathArray[], size_t codeBaseDirectoryPathCount) +{ + for(size_t i = 0, iCount = OVR::Alg::Min<size_t>(codeBaseDirectoryPathCount, OVR_ARRAY_COUNT(codeBasePathArray)); i != iCount; ++i) + { + codeBasePathArray[i] = codeBaseDirectoryPathArray[i]; + } +} + +const char* ExceptionHandler::GetExceptionUIText(const char* exceptionReportPath) +{ + char* uiText = nullptr; + OVR::SysFile file(exceptionReportPath, SysFile::Open_Read, SysFile::Mode_ReadWrite); + + if(file.IsValid()) + { + size_t length = (size_t)file.GetLength(); + uiText = (char*)OVR::SafeMMapAlloc(length + 1); + + if(uiText) + { + file.Read((uint8_t*)uiText, (int)length); + uiText[length] = '\0'; + file.Close(); + + // Currently on Mac our message box implementation is unable to display arbitrarily large amounts of text. + // So we reduce its size to a more summary version before presenting. + #if defined(OVR_OS_MAC) + struct Find { static char* PreviousChar(char* p, char c){ while(*p != c) p--; return p; } }; // Assumes the given c is present prior to p. + + // Print that the full report is at <file path> + // Exception Info section + // Exception thread callstack. + char empty[] = ""; + char* pExceptionInfoBegin = strstr(uiText, "Exception Info") ? strstr(uiText, "Exception Info") : empty; + char* pExceptionInfoEnd = (pExceptionInfoBegin == empty) ? (empty + 1) : strstr(uiText, "\r\n\r\n"); + char* pExceptionThreadArea = strstr(uiText, ", exception thread"); + char* pExceptionThreadBegin = pExceptionThreadArea ? Find::PreviousChar(pExceptionThreadArea, '\n') + 1 : empty; + char* pExceptionThreadEnd = (pExceptionThreadBegin == empty) ? (empty + 1) : strstr(pExceptionThreadArea, "\r\n\r\n"); + + if(!pExceptionInfoEnd) + pExceptionInfoEnd = pExceptionInfoBegin; + *pExceptionInfoEnd = '\0'; + + if(!pExceptionThreadEnd) + pExceptionThreadEnd = pExceptionThreadBegin; + *pExceptionThreadEnd = '\0'; + + size_t uiTextBriefLength = OVR_snprintf(nullptr, 0, "Full report:%s\n\nSummary report:\n%s\n\n%s", exceptionReportPath, pExceptionInfoBegin, pExceptionThreadBegin); + char* uiTextBrief = (char*)OVR::SafeMMapAlloc(uiTextBriefLength + 1); + + if(uiTextBrief) + { + OVR_snprintf(uiTextBrief, uiTextBriefLength + 1, "Full report:%s\n\nSummary report:\n%s\n\n%s", exceptionReportPath, pExceptionInfoBegin, pExceptionThreadBegin); + OVR::SafeMMapFree(uiText, length); + uiText = uiTextBrief; + } + #endif + } + } + + return uiText; +} + +void ExceptionHandler::FreeExceptionUIText(const char* messageBoxText) +{ + OVR::SafeMMapFree(messageBoxText, OVR_strlen(messageBoxText)); +} + + +} // namespace OVR + + +OVR_RESTORE_MSVC_WARNING() + diff --git a/LibOVR/Src/Kernel/OVR_DebugHelp.h b/LibOVR/Src/Kernel/OVR_DebugHelp.h new file mode 100644 index 0000000..2430ae4 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_DebugHelp.h @@ -0,0 +1,461 @@ +/************************************************************************************ + +Filename : OVR_DebugHelp.h +Content : Platform-independent exception handling interface +Created : October 6, 2014 + +Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +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. + +************************************************************************************/ + +#ifndef OVR_ExceptionHandler_h +#define OVR_ExceptionHandler_h + + +#include "OVR_Types.h" +#include "OVR_String.h" +#include "OVR_Threads.h" +#include "OVR_Atomic.h" +#include "OVR_Nullptr.h" +#include <stdio.h> +#include <time.h> + +#if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) + #include <Windows.h> + +#elif defined(OVR_OS_APPLE) + #include <pthread.h> + #include <mach/thread_status.h> + #include <mach/mach_types.h> + + extern "C" void* MachHandlerThreadFunctionStatic(void*); + extern "C" int catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t, mach_exception_data_type_t*, + mach_msg_type_number_t, int*, thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*); +#elif defined(OVR_OS_LINUX) + #include <pthread.h> +#endif + + +OVR_DISABLE_MSVC_WARNING(4351) // new behavior: elements of array will be default initialized + + +namespace OVR { + + // Thread identifiers + //typedef void* ThreadHandle; // Already defined by OVR Threads. Same as Windows thread handle, Unix pthread_t. + //typedef void* ThreadId; // Already defined by OVR Threads. Used by Windows as DWORD thread id, by Unix as pthread_t. + typedef uintptr_t ThreadSysId; // System thread identifier. Used by Windows the same as ThreadId (DWORD), thread_act_t on Mac/BSD, lwp id on Linux. + + // Thread constants + // To do: Move to OVR Threads + #define OVR_THREADHANDLE_INVALID ((ThreadHandle*)nullptr) + #define OVR_THREADID_INVALID ((ThreadId*)nullptr) + #define OVR_THREADSYSID_INVALID ((uintptr_t)0) + + OVR::ThreadSysId ConvertThreadHandleToThreadSysId(OVR::ThreadHandle threadHandle); + OVR::ThreadHandle ConvertThreadSysIdToThreadHandle(OVR::ThreadSysId threadSysId); // The returned handle must be freed with FreeThreadHandle. + void FreeThreadHandle(OVR::ThreadHandle threadHandle); // Frees the handle returned by ConvertThreadSysIdToThreadHandle. + OVR::ThreadSysId GetCurrentThreadSysId(); + + // CPUContext + #if defined(OVR_OS_MS) + typedef CONTEXT CPUContext; + #elif defined(OVR_OS_MAC) + struct CPUContext + { + x86_thread_state_t threadState; // This works for both x86 and x64. + x86_float_state_t floatState; + x86_debug_state_t debugState; + x86_avx_state_t avxState; + x86_exception_state exceptionState; + + CPUContext() { memset(this, 0, sizeof(CPUContext)); } + }; + #elif defined(OVR_OS_LINUX) + typedef int CPUContext; // To do. + #endif + + + // Tells if the current process appears to be running under a debugger. Does not attempt to + // detect the case of sleath debuggers (malware-related for example). + bool OVRIsDebuggerPresent(); + + // Exits the process with the given exit code. + #if !defined(OVR_NORETURN) + #if defined(OVR_CC_MSVC) + #define OVR_NORETURN __declspec(noreturn) + #else + #define OVR_NORETURN __attribute__((noreturn)) + #endif + #endif + OVR_NORETURN void ExitProcess(intptr_t processReturnValue); + + // Returns the instruction pointer of the caller for the position right after the call. + OVR_NO_INLINE void GetInstructionPointer(void*& pInstruction); + + // Returns the stack base and limit addresses for the given thread, or for the current thread if the threadHandle is default. + // The stack limit is a value less than the stack base on most platforms, as stacks usually grow downward. + // Some platforms (e.g. Microsoft) have dynamically resizing stacks, in which case the stack limit reflects the current limit. + void GetThreadStackBounds(void*& pStackBase, void*& pStackLimit, ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID); + + + // Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix. + // These are useful for when you need system-supplied memory pages. + // These are also useful for when you need to allocate memory in a way + // that doesn't affect the application heap. + void* SafeMMapAlloc(size_t size); + void SafeMMapFree(const void* memory, size_t size); + + + // OVR_MAX_PATH + // Max file path length (for most uses). + // To do: move this to OVR_File. + #if defined(OVR_OS_MS) // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + #define OVR_MAX_PATH 260 // Windows can use paths longer than this in some cases (network paths, UNC paths). + #else + #define OVR_MAX_PATH 1024 // This isn't a strict limit on all Unix-based platforms. + #endif + + + // ModuleHandle + #if defined(OVR_OS_MS) + typedef void* ModuleHandle; // from LoadLibrary() + #elif defined(OVR_OS_APPLE) || defined(OVR_OS_UNIX) + typedef void* ModuleHandle; // from dlopen() + #endif + + #define OVR_MODULEHANDLE_INVALID ((ModuleHandle*)nullptr) + + + + // Module info constants + static const ModuleHandle kMIHandleInvalid = OVR_MODULEHANDLE_INVALID; + static const uint64_t kMIAddressInvalid = 0xffffffffffffffffull; + static const uint64_t kMISizeInvalid = 0xffffffffffffffffull; + static const int32_t kMILineNumberInvalid = -1; + static const int32_t kMIFunctionOffsetInvalid = -1; + static const uint64_t kMIBaseAddressInvalid = 0xffffffffffffffffull; + static const uint64_t kMIBaseAddressUnspecified = 0xffffffffffffffffull; + + struct ModuleInfo + { + ModuleHandle handle; + uint64_t baseAddress; // The actual runtime base address of the module. May be different from the base address specified in the debug symbol file. + uint64_t size; + char filePath[OVR_MAX_PATH]; + char name[32]; + char type[8]; // Unix-specific. e.g. __TEXT + char permissions[8]; // Unix specific. e.g. "drwxr-xr-x" + + ModuleInfo() : handle(kMIHandleInvalid), baseAddress(kMIBaseAddressInvalid), size(0), filePath(), name(){} + }; + + + // Refers to symbol info for an instruction address. + // Info includes function name, source code file/line, and source code itself. + struct SymbolInfo + { + uint64_t address; + uint64_t size; + const ModuleInfo* pModuleInfo; + char filePath[OVR_MAX_PATH]; + int32_t fileLineNumber; + char function[128]; // This is a fixed size because we need to use it during application exceptions. + int32_t functionOffset; + char sourceCode[1024]; // This is a string representing the code itself and not a file path to the code. + + SymbolInfo() : address(kMIAddressInvalid), size(kMISizeInvalid), pModuleInfo(nullptr), filePath(), + fileLineNumber(kMILineNumberInvalid), function(), functionOffset(kMIFunctionOffsetInvalid), sourceCode() {} + }; + + + // Implements support for reading thread lists, module lists, backtraces, and backtrace symbols. + class SymbolLookup + { + public: + SymbolLookup(); + ~SymbolLookup(); + + void AddSourceCodeDirectory(const char* pDirectory); + + bool Initialize(); + void Shutdown(); + + // Should be disabled when within an exception handler. + void EnableMemoryAllocation(bool enabled); + + // Retrieves the backtrace (call stack) of the given thread. There may be some per-platform restrictions on this. + // Returns the number written, which will be <= addressArrayCapacity. + // This may not work on some platforms unless stack frames are enabled. + // For Microsoft platforms the platformThreadContext is CONTEXT*. + // For Apple platforms the platformThreadContext is x86_thread_state_t* or arm_thread_state_t*. + // If threadSysIdHelp is non-zero, it may be used by the implementation to help produce a better backtrace. + size_t GetBacktrace(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, void* platformThreadContext = nullptr, OVR::ThreadSysId threadSysIdHelp = OVR_THREADSYSID_INVALID); + + // Retrieves the backtrace for the given ThreadHandle. + // Returns the number written, which will be <= addressArrayCapacity. + size_t GetBacktraceFromThreadHandle(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID); + + // Retrieves the backtrace for the given ThreadSysId. + // Returns the number written, which will be <= addressArrayCapacity. + size_t GetBacktraceFromThreadSysId(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadSysId threadSysId = OVR_THREADSYSID_INVALID); + + // Gets a list of the modules (e.g. DLLs) present in the current process. + // Writes as many ModuleInfos as possible to pModuleInfoArray. + // Returns the required count of ModuleInfos, which will be > moduleInfoArrayCapacity if the capacity needs to be larger. + size_t GetModuleInfoArray(ModuleInfo* pModuleInfoArray, size_t moduleInfoArrayCapacity); + + // Retrieves a list of the current threads. Unless the process is paused the list is volatile. + // Returns the required capacity, which may be larger than threadArrayCapacity. + // Either array can be NULL to specify that it's not written to. + // For Windows the caller needs to CloseHandle the returned ThreadHandles. This can be done by calling DoneThreadList. + size_t GetThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCapacity); + + // Frees any references to thread handles or ids returned by GetThreadList; + void DoneThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCount); + + // Writes a given thread's callstack with symbols to the given output. + // It may not be safe to call this from an exception handler, as sOutput allocates memory. + bool ReportThreadCallstack(OVR::String& sOutput, size_t skipCount = 0, ThreadSysId threadSysId = OVR_THREADSYSID_INVALID); + + // Writes all thread's callstacks with symbols to the given output. + // It may not be safe to call this from an exception handler, as sOutput allocates memory. + bool ReportThreadCallstacks(OVR::String& sOutput, size_t skipCount = 0); + + // Retrieves symbol info for the given address. + bool LookupSymbol(uint64_t address, SymbolInfo& symbolInfo); + bool LookupSymbols(uint64_t* addressArray, SymbolInfo* pSymbolInfoArray, size_t arraySize); + + const ModuleInfo* GetModuleInfoForAddress(uint64_t address); // The returned ModuleInfo points to an internal structure. + + protected: + bool RefreshModuleList(); + + protected: + bool initialized; + bool allowMemoryAllocation; // True by default. If true then we allow allocating memory (and as a result provide less information). This is useful for when in an exception handler. + bool moduleListUpdated; + ModuleInfo moduleInfoArray[96]; // Cached list of modules we use. This is a fixed size because we need to use it during application exceptions. + size_t moduleInfoArraySize; + }; + + + + // ExceptionInfo + // We need to be careful to avoid data types that can allocate memory while we are + // handling an exception, as the memory system may be corrupted at that point in time. + struct ExceptionInfo + { + tm time; // GM time. + time_t timeVal; // GM time_t (seconds since 1970). + void* backtrace[64]; + size_t backtraceCount; + ThreadHandle threadHandle; // + ThreadSysId threadSysId; // + char threadName[32]; // Cannot be an allocating String object. + void* pExceptionInstructionAddress; + void* pExceptionMemoryAddress; + CPUContext cpuContext; + char exceptionDescription[1024]; // Cannot be an allocating String object. + SymbolInfo symbolInfo; // SymbolInfo for the exception location. + + #if defined(OVR_OS_MS) + EXCEPTION_RECORD exceptionRecord; // This is a Windows SDK struct. + #elif defined(OVR_OS_APPLE) + uint64_t exceptionType; // e.g. EXC_BAD_INSTRUCTION, EXC_BAD_ACCESS, etc. + uint32_t cpuExceptionId; // The x86/x64 CPU trap id. + uint32_t cpuExceptionIdError; // The x86/x64 CPU trap id extra info. + int64_t machExceptionDetail[4]; // Kernel exception code info. + int machExceptionDetailCount; // Count of valid entries. + #endif + + ExceptionInfo(); + }; + + + // Implments support for asynchronous exception handling and basic exception report generation. + // If you are implementing exception handling for a commercial application and want auto-uploading + // functionality you may want to consider using something like Google Breakpad. This exception handler + // is for in-application debug/diagnostic services, though it can write a report that has similar + // information to Breakpad or OS-provided reports such as Apple .crash files. + // + // Example usage: + // ExceptionHandler exceptionHandler; + // + // int main(int, char**) + // { + // exceptionHandler.Enable(true); + // exceptionHandler.SetExceptionListener(pSomeListener, 0); // Optional listener hook. + // } + // + class ExceptionHandler + { + public: + ExceptionHandler(); + ~ExceptionHandler(); + + bool Enable(bool enable); + + // Some report info can be considered private information of the user, such as the current process list, + // computer name, IP address or other identifying info, etc. We should not report this information for + // external users unless they agree to this. + void EnableReportPrivacy(bool enable); + + struct ExceptionListener + { + virtual ~ExceptionListener(){} + virtual int HandleException(uintptr_t userValue, ExceptionHandler* pExceptionHandler, ExceptionInfo* pExceptionInfo, const char* reportFilePath) = 0; + }; + + void SetExceptionListener(ExceptionListener* pExceptionListener, uintptr_t userValue); + + // What we do after handling the exception. + enum ExceptionResponse + { + kERContinue, // Continue execution. Will result in the exception being re-generated unless the application has fixed the cause. Similar to Windows EXCEPTION_CONTINUE_EXECUTION. + kERHandle, // Causes the OS to handle the exception as it normally would. Similar to Windows EXCEPTION_EXECUTE_HANDLER. + kERTerminate, // Exit the application. + kERThrow, // Re-throw the exception. Other handlers may catch it. Similar to Windows EXCEPTION_CONTINUE_SEARCH. + kERDefault // Usually set to kERTerminate. + }; + + void SetExceptionResponse(ExceptionResponse er) + { exceptionResponse = er; } + + // Allws you to add an arbitrary description of the current application, which will be added to exception reports. + void SetAppDescription(const char* appDescription); + + // If the report path has a "%s" in its name, then assume the path is a sprintf format and write it + // with the %s specified as a date/time string. + // The report path can be "default" to signify that you want to use the default user location. + // Example usage: + // handler.SetExceptionPaths("/Users/Current/Exceptions/Exception %s.txt"); + void SetExceptionPaths(const char* exceptionReportPath, const char* exceptionMinidumpPath = nullptr); + + // Allows you to specify base directories for code paths, which can be used to associate exception addresses to lines + // of code as opposed to just file names and line numbers, or function names plus binary offsets. + void SetCodeBaseDirectoryPaths(const char* codeBaseDirectoryPathArray[], size_t codeBaseDirectoryPathCount); + + // Given an exception report at a given file path, returns a string suitable for displaying in a message + // box or similar user interface during the handling of an exception. The returned string must be passed + // to FreeMessageBoxText when complete. + static const char* GetExceptionUIText(const char* exceptionReportPath); + static void FreeExceptionUIText(const char* messageBoxText); + + protected: + void WriteExceptionDescription(); + void WriteReport(); + void WriteReportLine(const char* pLine); + void WriteReportLineF(const char* format, ...); + void WriteThreadCallstack(ThreadHandle threadHandle, ThreadSysId threadSysId, const char* additionalInfo); + void WriteMiniDump(); + + // Runtime constants + bool enabled; + bool reportPrivacyEnabled; // Defaults to true. + ExceptionResponse exceptionResponse; // Defaults to kERHandle + ExceptionListener* exceptionListener; + uintptr_t exceptionListenerUserValue; + String appDescription; + String codeBasePathArray[6]; // 6 is arbitrary. + char reportFilePath[OVR_MAX_PATH];// May be an encoded path, in that it has "%s" in it or is named "default". See reporFiletPathActual for the runtime actual report path. + int miniDumpFlags; + char miniDumpFilePath[OVR_MAX_PATH]; + FILE* file; // Can/should we use OVR Files for this? + char scratchBuffer[4096]; + SymbolLookup symbolLookup; + + // Runtime variables + bool exceptionOccurred; + OVR::AtomicInt<uint32_t> handlingBusy; + char reportFilePathActual[OVR_MAX_PATH]; + char minidumpFilePathActual[OVR_MAX_PATH]; + int terminateReturnValue; + ExceptionInfo exceptionInfo; + + #if defined(OVR_OS_MS) + void* vectoredHandle; + LPTOP_LEVEL_EXCEPTION_FILTER previousFilter; + LPEXCEPTION_POINTERS pExceptionPointers; + + friend LONG WINAPI Win32ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers); + LONG ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers); + + #elif defined(OVR_OS_APPLE) + struct SavedExceptionPorts + { + SavedExceptionPorts() : count(0) { memset(this, 0, sizeof(SavedExceptionPorts)); } + + mach_msg_type_number_t count; + exception_mask_t masks[6]; + exception_handler_t ports[6]; + exception_behavior_t behaviors[6]; + thread_state_flavor_t flavors[6]; + }; + + friend void* ::MachHandlerThreadFunctionStatic(void*); + friend int ::catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t, + mach_exception_data_type_t*, mach_msg_type_number_t, int*, thread_state_t, + mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*); + + bool InitMachExceptionHandler(); + void ShutdownMachExceptionHandler(); + void* MachHandlerThreadFunction(); + kern_return_t HandleMachException(mach_port_t port, mach_port_t thread, mach_port_t task, exception_type_t exceptionType, + mach_exception_data_type_t* pExceptionDetail, mach_msg_type_number_t exceptionDetailCount, + int* pFlavor, thread_state_t pOldState, mach_msg_type_number_t oldStateCount, thread_state_t pNewState, + mach_msg_type_number_t* pNewStateCount); + kern_return_t ForwardMachException(mach_port_t thread, mach_port_t task, exception_type_t exceptionType, + mach_exception_data_t pExceptionDetail, mach_msg_type_number_t exceptionDetailCount); + + bool machHandlerInitialized; + mach_port_t machExceptionPort; + SavedExceptionPorts machExceptionPortsSaved; + volatile bool machThreadShouldContinue; + volatile bool machThreadExecuting; + pthread_t machThread; + + #elif defined(OVR_OS_LINUX) + // To do. + #endif + }; + + + // Identifies basic exception types for the CreateException function. + enum CreateExceptionType + { + kCETAccessViolation, // Read or write to inaccessable memory. + kCETAlignment, // Misaligned read or write. + kCETDivideByZero, // Integer divide by zero. + kCETFPU, // Floating point / VPU exception. + kCETIllegalInstruction, // Illegal opcode. + kCETStackCorruption, // Stack frame was corrupted. + kCETStackOverflow, // Stack ran out of space, often due to infinite recursion. + kCETTrap // System/OS trap (system call). + }; + + + // Creates an exception of the given type, primarily for testing. + void CreateException(CreateExceptionType exceptionType); + + + +} // namespace OVR + + +OVR_RESTORE_MSVC_WARNING() + + +#endif // Header include guard diff --git a/LibOVR/Src/Kernel/OVR_Delegates.h b/LibOVR/Src/Kernel/OVR_Delegates.h new file mode 100644 index 0000000..88948b4 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Delegates.h @@ -0,0 +1,541 @@ +/************************************************************************************ + +Filename : OVR_Delegates.h +Content : C++ Delegates +Created : June 15, 2014 +Authors : Chris Taylor + +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. + +************************************************************************************/ + +/* + Based on The Impossibly Fast C++ Delegates by Sergey Ryazanov from + http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx (2005) +*/ + +/* + Usage: + + Declare a delegate with a void (int) signature, also known as a + function that returns void and has one parameter that is an int: + typedef Delegate1<void, int> MyDelegate; + MyDelegate d; + + Point the delegate to a member function: + d.SetMember<A, &A::TestFunctionA>(&a); + d = MyDelegate::FromMember<A, &A::TestFunctionA>(&a); + + Point the delegate to a const member function: + d.SetConstMember<C, &C::TestFunctionA>(&c); + d = MyDelegate::FromConstMember<C, &C::TestFunctionA>(&c); + + Point the delegate to a free function: + d.SetFree<&FreeFunctionX>(); + d = MyDelegate::FromFree<&FreeFunctionX>(); + + Invoke the function via the delegate (works for all 3 cases): + d(1000); + + By default the delegates are uninitialized. + To clear an array of delegates quickly just zero the memory. + + This implementation is nicer than FastDelegates in my opinion + because it is simple and easy to read. It is a little slower + for virtual functions, but the size of the delegate is small, + and it will only get better as compilers improve. +*/ + +#ifndef OVR_Delegates_h +#define OVR_Delegates_h + +#include "OVR_Types.h" + +namespace OVR { + + +template <class ret_type> +class Delegate0 +{ + typedef ret_type (*StubPointer)(void *); + typedef Delegate0<ret_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate0(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)()> + static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/) + { + return (F)(); + } + + template <class T, ret_type (T::*F)()> + static OVR_FORCE_INLINE ret_type MemberStub(void *object) + { + T *p = static_cast<T*>(object); + return (p->*F)(); + } + + template <class T, ret_type (T::*F)() const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object) + { + T *p = static_cast<T*>(object); + return (p->*F)(); + } + +public: + OVR_FORCE_INLINE Delegate0() : _object(0), _stub(0){} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()() const + { + return (*_stub)(_object); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)()> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)()> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)() const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)()> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)()> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)() const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type> +class Delegate1 +{ + typedef ret_type (*StubPointer)(void *, arg1_type); + typedef Delegate1<ret_type, arg1_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate1(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1) + { + return (F)(a1); + } + + template <class T, ret_type (T::*F)(arg1_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1); + } + +public: + OVR_FORCE_INLINE Delegate1() : _object(0), _stub(0){} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1) const + { + return (*_stub)(_object, a1); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type, class arg2_type> +class Delegate2 +{ + typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type); + typedef Delegate2<ret_type, arg1_type, arg2_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate2(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2) + { + return (F)(a1, a2); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2); + } + +public: + OVR_FORCE_INLINE Delegate2() : _object(0), _stub(0){} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2) const + { + return (*_stub)(_object, a1, a2); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type, arg2_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type, class arg2_type, class arg3_type> +class Delegate3 +{ + typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type, arg3_type); + typedef Delegate3<ret_type, arg1_type, arg2_type, arg3_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate3(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void * /*object*/, arg1_type a1, arg2_type a2, arg3_type a3) + { + return (F)(a1, a2, a3); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2, a3); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2, a3); + } + +public: + OVR_FORCE_INLINE Delegate3() : _object(0), _stub(0){} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2, arg3_type a3) const + { + return (*_stub)(_object, a1, a2, a3); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + +// Add more here if needed, but keep in mind that a short, simple interface +// is rewarded by making the delegates faster... + + +} // namespace OVR + +#endif // OVR_Delegates_h diff --git a/LibOVR/Src/Kernel/OVR_Deque.h b/LibOVR/Src/Kernel/OVR_Deque.h index ca242ad..951ed84 100644 --- a/LibOVR/Src/Kernel/OVR_Deque.h +++ b/LibOVR/Src/Kernel/OVR_Deque.h @@ -5,16 +5,16 @@ Content : Deque container Created : Nov. 15, 2013 Authors : Dov Katz -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -27,9 +27,11 @@ limitations under the License. #ifndef OVR_Deque_h #define OVR_Deque_h +#include "OVR_ContainerAllocator.h" + namespace OVR{ -template <class Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > class Deque { public: @@ -48,8 +50,12 @@ public: virtual const Elem& PeekBack (int count = 0) const; // Returns count-th Item from the end virtual const Elem& PeekFront (int count = 0) const; // Returns count-th Item from the beginning - virtual inline UPInt GetSize (void) const; // Returns Number of Elements - virtual inline UPInt GetCapacity(void) const; // Returns the maximum possible number of elements + virtual inline size_t GetSize (void) const; // Returns Number of Elements + OVR_FORCE_INLINE int GetSizeI (void) const + { + return (int)GetSize(); + } + virtual inline size_t GetCapacity(void) const; // Returns the maximum possible number of elements virtual void Clear (void); // Remove all elements virtual inline bool IsEmpty () const; virtual inline bool IsFull () const; @@ -65,30 +71,34 @@ protected: int ElemCount; private: - Deque& operator= (const Deque& q) { }; // forbidden - Deque(const Deque<Elem> &OtherDeque) { }; + OVR_NON_COPYABLE(Deque); }; -template <class Elem> -class InPlaceMutableDeque : public Deque<Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > +class InPlaceMutableDeque : public Deque<Elem, Allocator> { + typedef Deque<Elem, Allocator> BaseType; + public: - InPlaceMutableDeque( int capacity = Deque<Elem>::DefaultCapacity ) : Deque<Elem>( capacity ) {} + InPlaceMutableDeque( int capacity = BaseType::DefaultCapacity ) : BaseType( capacity ) {} virtual ~InPlaceMutableDeque() {}; - using Deque<Elem>::PeekBack; - using Deque<Elem>::PeekFront; + using BaseType::PeekBack; + using BaseType::PeekFront; virtual Elem& PeekBack (int count = 0); // Returns count-th Item from the end virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning }; // Same as Deque, but allows to write more elements than maximum capacity // Old elements are lost as they are overwritten with the new ones -template <class Elem> -class CircularBuffer : public InPlaceMutableDeque<Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > +class CircularBuffer : public InPlaceMutableDeque<Elem, Allocator> { + typedef InPlaceMutableDeque<Elem, Allocator> BaseType; + public: - CircularBuffer(int MaxSize = Deque<Elem>::DefaultCapacity) : InPlaceMutableDeque<Elem>(MaxSize) { }; + CircularBuffer(int MaxSize = BaseType::DefaultCapacity) : BaseType(MaxSize) { }; + virtual ~CircularBuffer(){} // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class @@ -99,42 +109,54 @@ public: //---------------------------------------------------------------------------------- // Deque Constructor function -template <class Elem> -Deque<Elem>::Deque(int capacity) : +template <class Elem, class Allocator> +Deque<Elem, Allocator>::Deque(int capacity) : Capacity( capacity ), Beginning(0), End(0), ElemCount(0) { - Data = (Elem*) OVR_ALLOC(Capacity * sizeof(Elem)); - ConstructArray<Elem>(Data, Capacity); + Data = (Elem*) Allocator::Alloc(Capacity * sizeof(Elem)); } // Deque Destructor function -template <class Elem> -Deque<Elem>::~Deque(void) +template <class Elem, class Allocator> +Deque<Elem, Allocator>::~Deque(void) { - DestructArray<Elem>(Data, Capacity); - OVR_FREE(Data); + Clear(); + Allocator::Free(Data); } -template <class Elem> -void Deque<Elem>::Clear() +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::Clear() { + if (!IsEmpty()) + { + if (Beginning < End) + { + // no wrap-around + Allocator::DestructArray(Data + Beginning, End - Beginning); + } + else + { + // wrap-around + Allocator::DestructArray(Data + Beginning, Capacity - Beginning); + Allocator::DestructArray(Data, End); + } + } + Beginning = 0; End = 0; ElemCount = 0; - - DestructArray<Elem>(Data, Capacity); - ConstructArray<Elem>(Data, Capacity); } // Push functions -template <class Elem> -void Deque<Elem>::PushBack(const Elem &Item) +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushBack(const Elem &Item) { // Error Check: Make sure we aren't // exceeding our maximum storage space OVR_ASSERT( ElemCount < Capacity ); - Data[ End++ ] = Item; + Allocator::Construct(Data + End, Item); + ++End; ++ElemCount; // Check for wrap-around @@ -142,32 +164,31 @@ void Deque<Elem>::PushBack(const Elem &Item) End -= Capacity; } -template <class Elem> -void Deque<Elem>::PushFront(const Elem &Item) +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushFront(const Elem &Item) { // Error Check: Make sure we aren't // exceeding our maximum storage space OVR_ASSERT( ElemCount < Capacity ); - Beginning--; + --Beginning; // Check for wrap-around if (Beginning < 0) Beginning += Capacity; - Data[ Beginning ] = Item; + Allocator::Construct(Data + Beginning, Item); ++ElemCount; } // Pop functions -template <class Elem> -Elem Deque<Elem>::PopFront(void) +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopFront(void) { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > 0 ); Elem ReturnValue = Data[ Beginning ]; - Destruct<Elem>(&Data[ Beginning ]); - Construct<Elem>(&Data[ Beginning ]); + Allocator::Destruct(Data + Beginning); ++Beginning; --ElemCount; @@ -179,13 +200,13 @@ Elem Deque<Elem>::PopFront(void) return ReturnValue; } -template <class Elem> -Elem Deque<Elem>::PopBack(void) +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopBack(void) { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > 0 ); - End--; + --End; --ElemCount; // Check for wrap-around @@ -193,15 +214,14 @@ Elem Deque<Elem>::PopBack(void) End += Capacity; Elem ReturnValue = Data[ End ]; - Destruct<Elem>(&Data[ End ]); - Construct<Elem>(&Data[ End ]); + Allocator::Destruct(Data + End); return ReturnValue; } // Peek functions -template <class Elem> -const Elem& Deque<Elem>::PeekFront(int count) const +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekFront(int count) const { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > count ); @@ -212,8 +232,8 @@ const Elem& Deque<Elem>::PeekFront(int count) const return Data[ idx ]; } -template <class Elem> -const Elem& Deque<Elem>::PeekBack(int count) const +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekBack(int count) const { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > count ); @@ -225,70 +245,70 @@ const Elem& Deque<Elem>::PeekBack(int count) const } // Mutable Peek functions -template <class Elem> -Elem& InPlaceMutableDeque<Elem>::PeekFront(int count) +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekFront(int count) { // Error Check: Make sure we aren't reading from an empty Deque - OVR_ASSERT( Deque<Elem>::ElemCount > count ); + OVR_ASSERT( BaseType::ElemCount > count ); - int idx = Deque<Elem>::Beginning + count; - if (idx >= Deque<Elem>::Capacity) - idx -= Deque<Elem>::Capacity; - return Deque<Elem>::Data[ idx ]; + int idx = BaseType::Beginning + count; + if (idx >= BaseType::Capacity) + idx -= BaseType::Capacity; + return BaseType::Data[ idx ]; } -template <class Elem> -Elem& InPlaceMutableDeque<Elem>::PeekBack(int count) +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekBack(int count) { // Error Check: Make sure we aren't reading from an empty Deque - OVR_ASSERT( Deque<Elem>::ElemCount > count ); + OVR_ASSERT( BaseType::ElemCount > count ); - int idx = Deque<Elem>::End - count - 1; + int idx = BaseType::End - count - 1; if (idx < 0) - idx += Deque<Elem>::Capacity; - return Deque<Elem>::Data[ idx ]; + idx += BaseType::Capacity; + return BaseType::Data[ idx ]; } -template <class Elem> -inline UPInt Deque<Elem>::GetCapacity(void) const +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetCapacity(void) const { - return Deque<Elem>::Capacity; + return Capacity; } -template <class Elem> -inline UPInt Deque<Elem>::GetSize(void) const +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetSize(void) const { - return Deque<Elem>::ElemCount; + return ElemCount; } -template <class Elem> -inline bool Deque<Elem>::IsEmpty(void) const +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsEmpty(void) const { - return Deque<Elem>::ElemCount==0; + return ElemCount == 0; } -template <class Elem> -inline bool Deque<Elem>::IsFull(void) const +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsFull(void) const { - return Deque<Elem>::ElemCount==Deque<Elem>::Capacity; + return ElemCount == Capacity; } // ******* CircularBuffer<Elem> ******* // Push functions -template <class Elem> -void CircularBuffer<Elem>::PushBack(const Elem &Item) +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushBack(const Elem &Item) { if (this->IsFull()) this->PopFront(); - Deque<Elem>::PushBack(Item); + BaseType::PushBack(Item); } -template <class Elem> -void CircularBuffer<Elem>::PushFront(const Elem &Item) +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushFront(const Elem &Item) { if (this->IsFull()) this->PopBack(); - Deque<Elem>::PushFront(Item); + BaseType::PushFront(Item); } }; diff --git a/LibOVR/Src/Kernel/OVR_File.cpp b/LibOVR/Src/Kernel/OVR_File.cpp index 31ab516..c431928 100644 --- a/LibOVR/Src/Kernel/OVR_File.cpp +++ b/LibOVR/Src/Kernel/OVR_File.cpp @@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32) Created : April 5, 1999 Authors : Michael Antonov -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -46,7 +46,7 @@ namespace OVR { // Not supposed to be used BufferedFile::BufferedFile() : DelegatedFile(0) { - pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE); BufferMode = NoBuffer; FilePos = 0; Pos = 0; @@ -56,7 +56,7 @@ BufferedFile::BufferedFile() : DelegatedFile(0) // Takes another file as source BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) { - pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE); BufferMode = NoBuffer; FilePos = pfile->LTell(); Pos = 0; @@ -177,12 +177,12 @@ int BufferedFile::Tell() return pos; } -SInt64 BufferedFile::LTell() +int64_t BufferedFile::LTell() { if (BufferMode == ReadBuffer) return FilePos - DataSize + Pos; - SInt64 pos = pFile->LTell(); + int64_t pos = pFile->LTell(); if (pos!=-1) { OVR_ASSERT(BufferMode != ReadBuffer); @@ -204,13 +204,13 @@ int BufferedFile::GetLength() } return len; } -SInt64 BufferedFile::LGetLength() +int64_t BufferedFile::LGetLength() { - SInt64 len = pFile->LGetLength(); + int64_t len = pFile->LGetLength(); // If writing through buffer, file length may actually be bigger if ((len!=-1) && (BufferMode==WriteBuffer)) { - SInt64 currPos = pFile->LTell() + Pos; + int64_t currPos = pFile->LTell() + Pos; if (currPos>len) len = currPos; } @@ -225,7 +225,7 @@ bool BufferedFile::Stat(FileStats *pfs) { if (BufferMode==WriteBuffer) { - SInt64 currPos = pFile->LTell() + Pos; + int64_t currPos = pFile->LTell() + Pos; if (currPos > pfs->Size) { pfs->Size = currPos; @@ -239,7 +239,7 @@ bool BufferedFile::Stat(FileStats *pfs) } */ -int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) +int BufferedFile::Write(const uint8_t *psourceBuffer, int numBytes) { if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) { @@ -268,7 +268,7 @@ int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) return sz; } -int BufferedFile::Read(UByte *pdestBuffer, int numBytes) +int BufferedFile::Read(uint8_t *pdestBuffer, int numBytes) { if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) { @@ -413,7 +413,7 @@ int BufferedFile::Seek(int offset, int origin) // Lightweight buffer "Flush". We do this to avoid an extra seek // back operation which would take place if we called FlushBuffer directly. origin = Seek_Set; - OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); + OVR_ASSERT(((FilePos - DataSize + Pos) + (uint64_t)offset) < ~(uint64_t)0); offset = (int)(FilePos - DataSize + Pos) + offset; Pos = DataSize = 0; } @@ -421,7 +421,7 @@ int BufferedFile::Seek(int offset, int origin) { if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) { - OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); + OVR_ASSERT((FilePos-DataSize) < ~(uint64_t)0); Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); return offset; } @@ -461,7 +461,7 @@ int BufferedFile::Seek(int offset, int origin) return int (FilePos); } -SInt64 BufferedFile::LSeek(SInt64 offset, int origin) +int64_t BufferedFile::LSeek(int64_t offset, int origin) { if (BufferMode == ReadBuffer) { @@ -472,20 +472,20 @@ SInt64 BufferedFile::LSeek(SInt64 offset, int origin) if (((unsigned(offset) + Pos)) <= DataSize) { Pos += (unsigned)offset; - return SInt64(FilePos - DataSize + Pos); + return int64_t(FilePos - DataSize + Pos); } // Lightweight buffer "Flush". We do this to avoid an extra seek // back operation which would take place if we called FlushBuffer directly. origin = Seek_Set; - offset = (SInt64)(FilePos - DataSize + Pos) + offset; + offset = (int64_t)(FilePos - DataSize + Pos) + offset; Pos = DataSize = 0; } else if (origin == Seek_Set) { - if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) + if (((uint64_t)offset - (FilePos-DataSize)) <= DataSize) { - Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); + Pos = (unsigned)((uint64_t)offset - (FilePos-DataSize)); return offset; } Pos = DataSize = 0; @@ -508,7 +508,7 @@ SInt64 BufferedFile::LSeek(SInt64 offset, int origin) Pos += int (offset); return FilePos - DataSize + Pos; } - else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) + else if (origin == Seek_Set && offset >= int64_t(FilePos - DataSize) && offset < int64_t(FilePos)) { Pos = unsigned(offset - FilePos + DataSize); return FilePos - DataSize + Pos; @@ -526,7 +526,7 @@ int BufferedFile::CopyFromStream(File *pstream, int byteSize) // We can't rely on overridden Write() // because delegation doesn't override virtual pointers // So, just re-implement - UByte buff[0x4000]; + uint8_t* buff = new uint8_t[0x4000]; int count = 0; int szRequest, szRead, szWritten; @@ -544,6 +544,9 @@ int BufferedFile::CopyFromStream(File *pstream, int byteSize) if (szWritten < szRequest) break; } + + delete[] buff; + return count; } @@ -571,8 +574,8 @@ bool BufferedFile::Close() // Find trailing short filename in a path. const char* OVR_CDECL GetShortFilename(const char* purl) { - UPInt len = OVR_strlen(purl); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(purl); + for (size_t i=len; i>0; i--) if (purl[i]=='\\' || purl[i]=='/') return purl+i+1; return purl; diff --git a/LibOVR/Src/Kernel/OVR_File.h b/LibOVR/Src/Kernel/OVR_File.h index a8dc615..d9d3b0f 100644 --- a/LibOVR/Src/Kernel/OVR_File.h +++ b/LibOVR/Src/Kernel/OVR_File.h @@ -11,16 +11,16 @@ Notes : errno may not be preserved across use of BaseFile member functio : Directories cannot be deleted while files opened from them are in use (For the GetFullName function) -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -136,11 +136,11 @@ public: // Return position virtual int Tell() = 0; - virtual SInt64 LTell() = 0; + virtual int64_t LTell() = 0; // File size virtual int GetLength() = 0; - virtual SInt64 LGetLength() = 0; + virtual int64_t LGetLength() = 0; // Returns file stats // 0 for failure @@ -156,12 +156,12 @@ public: // Blocking write, will write in the given number of bytes to the stream // Returns : -1 for error // Otherwise number of bytes read - virtual int Write(const UByte *pbufer, int numBytes) = 0; + virtual int Write(const uint8_t *pbufer, int numBytes) = 0; // Blocking read, will read in the given number of bytes or less from the stream // Returns : -1 for error // Otherwise number of bytes read, // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed - virtual int Read(UByte *pbufer, int numBytes) = 0; + virtual int Read(uint8_t *pbufer, int numBytes) = 0; // Skips (ignores) a given # of bytes // Same return values as Read @@ -183,7 +183,7 @@ public: // Seeking // Returns new position, -1 for error virtual int Seek(int offset, int origin=Seek_Set) = 0; - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0; + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set) = 0; // Seek simplification int SeekToBegin() {return Seek(0); } int SeekToEnd() {return Seek(0,Seek_End); } @@ -203,70 +203,70 @@ public: // Read/Write helpers private: - UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; } - UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; } - UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; } - UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; } - void PWrite64(UInt64 v) { Write((UByte*)&v, 8); } - void PWrite32(UInt32 v) { Write((UByte*)&v, 4); } - void PWrite16(UInt16 v) { Write((UByte*)&v, 2); } - void PWrite8(UByte v) { Write((UByte*)&v, 1); } + uint64_t PRead64() { uint64_t v = 0; Read((uint8_t*)&v, 8); return v; } + uint32_t PRead32() { uint32_t v = 0; Read((uint8_t*)&v, 4); return v; } + uint16_t PRead16() { uint16_t v = 0; Read((uint8_t*)&v, 2); return v; } + uint8_t PRead8() { uint8_t v = 0; Read((uint8_t*)&v, 1); return v; } + void PWrite64(uint64_t v) { Write((uint8_t*)&v, 8); } + void PWrite32(uint32_t v) { Write((uint8_t*)&v, 4); } + void PWrite16(uint16_t v) { Write((uint8_t*)&v, 2); } + void PWrite8(uint8_t v) { Write((uint8_t*)&v, 1); } public: // Writing primitive types - Little Endian - inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } - inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); } + inline void WriteUByte(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSByte(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt8(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt8(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt16(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt16(int16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt32(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt32(int32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt64(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt64(int64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 4); } + inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 8); } // Writing primitive types - Big Endian - inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); } - inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); } + inline void WriteUByteBE(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSByteBE(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt8BE(uint16_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt8BE(int16_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt16BE(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt16BE(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt32BE(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt32BE(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt64BE(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt64BE(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 4); } + inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 8); } // Reading primitive types - Little Endian - inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); } - inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); } - inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); } - inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); } - inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); } - inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); } - inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } - inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } + inline uint8_t ReadUByte() { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline int8_t ReadSByte() { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline uint8_t ReadUInt8() { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline int8_t ReadSInt8() { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline uint16_t ReadUInt16() { return (uint16_t)Alg::ByteUtil::LEToSystem(PRead16()); } + inline int16_t ReadSInt16() { return (int16_t)Alg::ByteUtil::LEToSystem(PRead16()); } + inline uint32_t ReadUInt32() { return (uint32_t)Alg::ByteUtil::LEToSystem(PRead32()); } + inline int32_t ReadSInt32() { return (int32_t)Alg::ByteUtil::LEToSystem(PRead32()); } + inline uint64_t ReadUInt64() { return (uint64_t)Alg::ByteUtil::LEToSystem(PRead64()); } + inline int64_t ReadSInt64() { return (int64_t)Alg::ByteUtil::LEToSystem(PRead64()); } + inline float ReadFloat() { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } + inline double ReadDouble() { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } // Reading primitive types - Big Endian - inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); } - inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); } - inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); } - inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); } - inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); } - inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); } - inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } - inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } + inline uint8_t ReadUByteBE() { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline int8_t ReadSByteBE() { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline uint8_t ReadUInt8BE() { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline int8_t ReadSInt8BE() { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline uint16_t ReadUInt16BE() { return (uint16_t)Alg::ByteUtil::BEToSystem(PRead16()); } + inline int16_t ReadSInt16BE() { return (int16_t)Alg::ByteUtil::BEToSystem(PRead16()); } + inline uint32_t ReadUInt32BE() { return (uint32_t)Alg::ByteUtil::BEToSystem(PRead32()); } + inline int32_t ReadSInt32BE() { return (int32_t)Alg::ByteUtil::BEToSystem(PRead32()); } + inline uint64_t ReadUInt64BE() { return (uint64_t)Alg::ByteUtil::BEToSystem(PRead64()); } + inline int64_t ReadSInt64BE() { return (int64_t)Alg::ByteUtil::BEToSystem(PRead64()); } + inline float ReadFloatBE() { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } + inline double ReadDoubleBE() { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } }; @@ -294,18 +294,18 @@ public: // virtual bool IsRecoverable() { return pFile->IsRecoverable(); } virtual int Tell() { return pFile->Tell(); } - virtual SInt64 LTell() { return pFile->LTell(); } + virtual int64_t LTell() { return pFile->LTell(); } virtual int GetLength() { return pFile->GetLength(); } - virtual SInt64 LGetLength() { return pFile->LGetLength(); } + virtual int64_t LGetLength() { return pFile->LGetLength(); } //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); } virtual int GetErrorCode() { return pFile->GetErrorCode(); } // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } - virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } + virtual int Write(const uint8_t *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } + virtual int Read(uint8_t *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); } @@ -315,7 +315,7 @@ public: // Seeking virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); } - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); } @@ -342,14 +342,14 @@ protected: }; // Buffer & the mode it's in - UByte* pBuffer; + uint8_t* pBuffer; BufferModeType BufferMode; // Position in buffer unsigned Pos; // Data in buffer if reading unsigned DataSize; // Underlying file position - UInt64 FilePos; + uint64_t FilePos; // Initializes buffering to a certain mode bool SetBufferMode(BufferModeType mode); @@ -362,7 +362,8 @@ protected: // Hidden constructor BufferedFile(); - inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); } + BufferedFile(const BufferedFile &) : DelegatedFile(), pBuffer(NULL), BufferMode(NoBuffer), Pos(0), DataSize(0), FilePos(0) { } + public: // Constructor @@ -376,15 +377,15 @@ public: // We override all the functions that can possibly // require buffer mode switch, flush, or extra calculations virtual int Tell(); - virtual SInt64 LTell(); + virtual int64_t LTell(); virtual int GetLength(); - virtual SInt64 LGetLength(); + virtual int64_t LGetLength(); // virtual bool Stat(GFileStats *pfs); - virtual int Write(const UByte *pbufer, int numBytes); - virtual int Read(UByte *pbufer, int numBytes); + virtual int Write(const uint8_t *pbufer, int numBytes); + virtual int Read(uint8_t *pbufer, int numBytes); virtual int SkipBytes(int numBytes); @@ -393,7 +394,7 @@ public: virtual bool Flush(); virtual int Seek(int offset, int origin=Seek_Set); - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set); + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set); virtual int CopyFromStream(File *pstream, int byteSize); @@ -417,10 +418,10 @@ public: int GetErrorCode() { return 0; } int Tell() { return FileIndex; } - SInt64 LTell() { return (SInt64) FileIndex; } + int64_t LTell() { return (int64_t) FileIndex; } int GetLength() { return FileSize; } - SInt64 LGetLength() { return (SInt64) FileSize; } + int64_t LGetLength() { return (int64_t) FileSize; } bool Close() { @@ -433,12 +434,12 @@ public: return 0; } - int Write(const UByte *pbuffer, int numBytes) + int Write(const uint8_t *pbuffer, int numBytes) { OVR_UNUSED2(pbuffer, numBytes); return 0; } - int Read(UByte *pbufer, int numBytes) + int Read(uint8_t *pbufer, int numBytes) { if (FileIndex + numBytes > FileSize) { @@ -484,14 +485,14 @@ public: return FileIndex; } - SInt64 LSeek(SInt64 offset, int origin = Seek_Set) + int64_t LSeek(int64_t offset, int origin = Seek_Set) { - return (SInt64) Seek((int) offset, origin); + return (int64_t) Seek((int) offset, origin); } public: - MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize) + MemoryFile (const String& fileName, const uint8_t *pBuffer, int buffSize) : FilePath(fileName) { FileData = pBuffer; @@ -501,7 +502,7 @@ public: } // pfileName should be encoded as UTF-8 to support international file names. - MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize) + MemoryFile (const char* pfileName, const uint8_t *pBuffer, int buffSize) : FilePath(pfileName) { FileData = pBuffer; @@ -512,7 +513,7 @@ public: private: String FilePath; - const UByte *FileData; + const uint8_t *FileData; int FileSize; int FileIndex; bool Valid; diff --git a/LibOVR/Src/Kernel/OVR_FileFILE.cpp b/LibOVR/Src/Kernel/OVR_FileFILE.cpp index 8478086..9b2123f 100644 --- a/LibOVR/Src/Kernel/OVR_FileFILE.cpp +++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp @@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32) Created : April 5, 1999 Authors : Michael Antonov -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -60,7 +60,8 @@ static int SFerror () return FileConstants::Error_IOError; }; -#ifdef OVR_OS_WIN32 +#if defined(OVR_OS_WIN32) +#define WIN32_LEAN_AND_MEAN #include "windows.h" // A simple helper class to disable/enable system error mode, if necessary // Disabling happens conditionally only if a drive name is involved @@ -73,16 +74,20 @@ public: { if (pfileName && (pfileName[0]!=0) && pfileName[1]==':') { - Disabled = 1; + Disabled = TRUE; OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS); } else + { Disabled = 0; + OldMode = 0; + } } ~SysErrorModeDisabler() { - if (Disabled) ::SetErrorMode(OldMode); + if (Disabled) + ::SetErrorMode(OldMode); } }; #else @@ -121,25 +126,31 @@ protected: int LastOp; #ifdef OVR_FILE_VERIFY_SEEK_ERRORS - UByte* pFileTestBuffer; + uint8_t* pFileTestBuffer; unsigned FileTestLength; unsigned TestPos; // File pointer position during tests. #endif public: - FILEFile() + FILEFile() : + FileName(), + Opened(false), + fs(NULL), + OpenFlags(0), + ErrorCode(0), + LastOp(0) + #ifdef OVR_FILE_VERIFY_SEEK_ERRORS + ,pFileTestBuffer(NULL) + ,FileTestLength(0) + ,TestPos(0) + #endif { - Opened = 0; FileName = ""; - -#ifdef OVR_FILE_VERIFY_SEEK_ERRORS - pFileTestBuffer =0; - FileTestLength =0; - TestPos =0; -#endif } + // Initialize file by opening it FILEFile(const String& fileName, int flags, int Mode); + // The 'pfileName' should be encoded as UTF-8 to support international file names. FILEFile(const char* pfileName, int flags, int Mode); @@ -157,21 +168,21 @@ public: // Return position / file size virtual int Tell(); - virtual SInt64 LTell(); + virtual int64_t LTell(); virtual int GetLength(); - virtual SInt64 LGetLength(); + virtual int64_t LGetLength(); // virtual bool Stat(FileStats *pfs); virtual int GetErrorCode(); // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes); - virtual int Read(UByte *pbuffer, int numBytes); + virtual int Write(const uint8_t *pbuffer, int numBytes); + virtual int Read(uint8_t *pbuffer, int numBytes); virtual int SkipBytes(int numBytes); virtual int BytesAvailable(); virtual bool Flush(); virtual int Seek(int offset, int origin); - virtual SInt64 LSeek(SInt64 offset, int origin); + virtual int64_t LSeek(int64_t offset, int origin); virtual int CopyFromStream(File *pStream, int byteSize); virtual bool Close(); @@ -218,7 +229,7 @@ void FILEFile::init() else if (OpenFlags & Open_Write) omode = "r+b"; -#ifdef OVR_OS_WIN32 +#if defined(OVR_OS_MS) SysErrorModeDisabler disabler(FileName.ToCStr()); #endif @@ -248,7 +259,7 @@ void FILEFile::init() fseek(fs, 0, SEEK_END); FileTestLength = ftell(fs); fseek(fs, 0, SEEK_SET); - pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength); + pFileTestBuffer = (uint8_t*)OVR_ALLOC(FileTestLength); if (pFileTestBuffer) { OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength)); @@ -293,9 +304,9 @@ int FILEFile::Tell() return pos; } -SInt64 FILEFile::LTell() +int64_t FILEFile::LTell() { - SInt64 pos = ftell(fs); + int64_t pos = ftell(fs); if (pos < 0) ErrorCode = SFerror(); return pos; @@ -313,13 +324,13 @@ int FILEFile::GetLength() } return -1; } -SInt64 FILEFile::LGetLength() +int64_t FILEFile::LGetLength() { - SInt64 pos = LTell(); + int64_t pos = LTell(); if (pos >= 0) { LSeek (0, Seek_End); - SInt64 size = LTell(); + int64_t size = LTell(); LSeek (pos, Seek_Set); return size; } @@ -332,7 +343,7 @@ int FILEFile::GetErrorCode() } // ** Stream implementation & I/O -int FILEFile::Write(const UByte *pbuffer, int numBytes) +int FILEFile::Write(const uint8_t *pbuffer, int numBytes) { if (LastOp && LastOp != Open_Write) fflush(fs); @@ -349,7 +360,7 @@ int FILEFile::Write(const UByte *pbuffer, int numBytes) return written; } -int FILEFile::Read(UByte *pbuffer, int numBytes) +int FILEFile::Read(uint8_t *pbuffer, int numBytes) { if (LastOp && LastOp != Open_Read) fflush(fs); @@ -362,7 +373,7 @@ int FILEFile::Read(UByte *pbuffer, int numBytes) if (read > 0) { // Read-in data must match our pre-loaded buffer data! - UByte* pcompareBuffer = pFileTestBuffer + TestPos; + uint8_t* pcompareBuffer = pFileTestBuffer + TestPos; for (int i=0; i< read; i++) { OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]); @@ -380,8 +391,8 @@ int FILEFile::Read(UByte *pbuffer, int numBytes) // Seeks ahead to skip bytes int FILEFile::SkipBytes(int numBytes) { - SInt64 pos = LTell(); - SInt64 newPos = LSeek(numBytes, Seek_Cur); + int64_t pos = LTell(); + int64_t newPos = LSeek(numBytes, Seek_Cur); // Return -1 for major error if ((pos==-1) || (newPos==-1)) @@ -396,8 +407,8 @@ int FILEFile::SkipBytes(int numBytes) // Return # of bytes till EOF int FILEFile::BytesAvailable() { - SInt64 pos = LTell(); - SInt64 endPos = LGetLength(); + int64_t pos = LTell(); + int64_t endPos = LGetLength(); // Return -1 for major error if ((pos==-1) || (endPos==-1)) @@ -452,14 +463,14 @@ int FILEFile::Seek(int offset, int origin) return (int)Tell(); } -SInt64 FILEFile::LSeek(SInt64 offset, int origin) +int64_t FILEFile::LSeek(int64_t offset, int origin) { return Seek((int)offset,origin); } int FILEFile::CopyFromStream(File *pstream, int byteSize) { - UByte buff[0x4000]; + uint8_t* buff = new uint8_t[0x4000]; int count = 0; int szRequest, szRead, szWritten; @@ -477,6 +488,9 @@ int FILEFile::CopyFromStream(File *pstream, int byteSize) if (szWritten < szRequest) break; } + + delete[] buff; + return count; } @@ -570,7 +584,7 @@ Ptr<File> FileFILEOpen(const String& path, int flags, int mode) // Helper function: obtain file information time. bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) // 64-bit implementation on Windows. struct __stat64 fileStat; // Stat returns 0 for success. diff --git a/LibOVR/Src/Kernel/OVR_Hash.h b/LibOVR/Src/Kernel/OVR_Hash.h index 04c4db8..3316d1e 100644 --- a/LibOVR/Src/Kernel/OVR_Hash.h +++ b/LibOVR/Src/Kernel/OVR_Hash.h @@ -6,16 +6,16 @@ Content : Template hash-table/set implementation Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -71,8 +71,8 @@ template<class C> class IdentityHash { public: - UPInt operator()(const C& data) const - { return (UPInt) data; } + size_t operator()(const C& data) const + { return (size_t) data; } }; // Computes a hash of an object's representation. @@ -84,22 +84,23 @@ public: // above, http::/www.cs.yorku.ca/~oz/hash.html // This is somewhat slower then Bernstein, but it works way better than the above // hash function for hashing large numbers of 32-bit ints. - static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381) + static OVR_FORCE_INLINE size_t SDBM_Hash(const void* data_in, size_t size, size_t seed = 5381) { - const UByte* data = (const UByte*) data_in; - UPInt h = seed; - while (size > 0) + const uint8_t* data = (const uint8_t*) data_in; + size_t h = seed; + while (size-- > 0) { - size--; - h = (h << 16) + (h << 6) - h + (UPInt)data[size]; + #ifndef __clang_analyzer__ // It mistakenly thinks data is garbage. + h = (h << 16) + (h << 6) - h + (size_t)data[size]; + #endif } return h; } - UPInt operator()(const C& data) const + size_t operator()(const C& data) const { - unsigned char* p = (unsigned char*) &data; - int size = sizeof(C); + const unsigned char* p = (const unsigned char*) &data; + const size_t size = sizeof(C); return SDBM_Hash(p, size); } @@ -116,14 +117,14 @@ class HashsetEntry { public: // Internal chaining for collisions. - SPInt NextInChain; + intptr_t NextInChain; C Value; HashsetEntry() : NextInChain(-2) { } HashsetEntry(const HashsetEntry& e) : NextInChain(e.NextInChain), Value(e.Value) { } - HashsetEntry(const C& key, SPInt next) + HashsetEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } bool IsEmpty() const { return NextInChain == -2; } @@ -131,8 +132,8 @@ public: // Cached hash value access - can be optimized bu storing hash locally. // Mask value only needs to be used if SetCachedHash is not implemented. - UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } - void SetCachedHash(UPInt) {} + size_t GetCachedHash(size_t maskValue) const { return HashF()(Value) & maskValue; } + void SetCachedHash(size_t) {} void Clear() { @@ -151,15 +152,15 @@ class HashsetCachedEntry { public: // Internal chaining for collisions. - SPInt NextInChain; - UPInt HashValue; + intptr_t NextInChain; + size_t HashValue; C Value; HashsetCachedEntry() : NextInChain(-2) { } HashsetCachedEntry(const HashsetCachedEntry& e) : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } - HashsetCachedEntry(const C& key, SPInt next) + HashsetCachedEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } bool IsEmpty() const { return NextInChain == -2; } @@ -167,8 +168,8 @@ public: // Cached hash value access - can be optimized bu storing hash locally. // Mask value only needs to be used if SetCachedHash is not implemented. - UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } - void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } + size_t GetCachedHash(size_t maskValue) const { OVR_UNUSED(maskValue); return HashValue; } + void SetCachedHash(size_t hashValue) { HashValue = hashValue; } void Clear() { @@ -210,7 +211,7 @@ public: if (pTable) { // Delete the entries. - for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) + for (size_t i = 0, n = pTable->SizeMask; i <= n; i++) { Entry* e = &E(i); if (!e->IsEmpty()) @@ -244,7 +245,7 @@ public: if (pTable) { // Delete the entries. - for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) + for (size_t i = 0, n = pTable->SizeMask; i <= n; i++) { Entry* e = &E(i); if (!e->IsEmpty()) @@ -269,8 +270,8 @@ public: template<class CRef> void Set(const CRef& key) { - UPInt hashValue = HashF()(key); - SPInt index = (SPInt)-1; + size_t hashValue = HashF()(key); + intptr_t index = (intptr_t)-1; if (pTable != NULL) index = findIndexCore(key, hashValue & pTable->SizeMask); @@ -289,7 +290,7 @@ public: template<class CRef> inline void Add(const CRef& key) { - UPInt hashValue = HashF()(key); + size_t hashValue = HashF()(key); add(key, hashValue); } @@ -300,20 +301,20 @@ public: if (pTable == NULL) return; - UPInt hashValue = AltHashF()(key); - SPInt index = hashValue & pTable->SizeMask; + size_t hashValue = AltHashF()(key); + intptr_t index = hashValue & pTable->SizeMask; Entry* e = &E(index); // If empty node or occupied by collider, we have nothing to remove. - if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index)) + if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (size_t)index)) return; // Save index - SPInt naturalIndex = index; - SPInt prevIndex = -1; + intptr_t naturalIndex = index; + intptr_t prevIndex = -1; - while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) + while ((e->GetCachedHash(pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key)) { // Keep looking through the chain. prevIndex = index; @@ -361,7 +362,7 @@ public: template<class K> C* Get(const K& key) { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return &E(index).Value; return 0; @@ -370,7 +371,7 @@ public: template<class K> const C* Get(const K& key) const { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return &E(index).Value; return 0; @@ -380,7 +381,7 @@ public: template<class K> const C* GetAlt(const K& key) const { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return &E(index).Value; return 0; @@ -389,7 +390,7 @@ public: template<class K> C* GetAlt(const K& key) { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return &E(index).Value; return 0; @@ -398,7 +399,7 @@ public: template<class K> bool GetAlt(const K& key, C* pval) const { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) { if (pval) @@ -409,10 +410,11 @@ public: } - UPInt GetSize() const + size_t GetSize() const { - return pTable == NULL ? 0 : (UPInt)pTable->EntryCount; + return pTable == NULL ? 0 : (size_t)pTable->EntryCount; } + int GetSizeI() const { return (int)GetSize(); } // Resize the HashSet table to fit one more Entry. Often this @@ -432,7 +434,7 @@ public: } // Hint the bucket count to >= n. - void Resize(UPInt n) + void Resize(size_t n) { // Not really sure what this means in relation to // STLport's hash_map... they say they "increase the @@ -446,9 +448,9 @@ public: // Size the HashSet so that it can comfortably contain the given // number of elements. If the HashSet already contains more // elements than newSize, then this may be a no-op. - void SetCapacity(UPInt newSize) + void SetCapacity(size_t newSize) { - UPInt newRawSize = (newSize * 5) / 4; + size_t newRawSize = (newSize * 5) / 4; if (newRawSize <= GetSize()) return; setRawCapacity(newRawSize); @@ -466,23 +468,23 @@ public: { const C& operator * () const { - OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); + OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask); return pHash->E(Index).Value; } const C* operator -> () const { - OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); + OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask); return &pHash->E(Index).Value; } void operator ++ () { // Find next non-empty Entry. - if (Index <= (SPInt)pHash->pTable->SizeMask) + if (Index <= (intptr_t)pHash->pTable->SizeMask) { Index++; - while ((UPInt)Index <= pHash->pTable->SizeMask && + while ((size_t)Index <= pHash->pTable->SizeMask && pHash->E(Index).IsEmpty()) { Index++; @@ -512,7 +514,7 @@ public: { return (pHash == NULL) || (pHash->pTable == NULL) || - (Index > (SPInt)pHash->pTable->SizeMask); + (Index > (intptr_t)pHash->pTable->SizeMask); } ConstIterator() @@ -522,7 +524,7 @@ public: public: // Constructor was intentionally made public to allow create // iterator with arbitrary index. - ConstIterator(const SelfType* h, SPInt index) + ConstIterator(const SelfType* h, intptr_t index) : pHash(h), Index(index) { } @@ -530,7 +532,7 @@ public: { return pHash; } - SPInt GetIndex() const + intptr_t GetIndex() const { return Index; } @@ -539,7 +541,7 @@ public: friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; const SelfType* pHash; - SPInt Index; + intptr_t Index; }; friend struct ConstIterator; @@ -551,7 +553,7 @@ public: // Allow non-const access to entries. C& operator*() const { - OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask); + OVR_ASSERT((ConstIterator::pHash) && ConstIterator::pHash->pTable && (ConstIterator::Index >= 0) && (ConstIterator::Index <= (intptr_t)ConstIterator::pHash->pTable->SizeMask)); return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value; } @@ -577,20 +579,20 @@ public: //Entry* ee = &phash->E(ConstIterator::Index); //const C& key = ee->Value; - UPInt hashValue = AltHashF()(key); - SPInt index = hashValue & phash->pTable->SizeMask; + size_t hashValue = AltHashF()(key); + intptr_t index = hashValue & phash->pTable->SizeMask; Entry* e = &phash->E(index); // If empty node or occupied by collider, we have nothing to remove. - if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index)) + if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (size_t)index)) return; // Save index - SPInt naturalIndex = index; - SPInt prevIndex = -1; + intptr_t naturalIndex = index; + intptr_t prevIndex = -1; - while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) + while ((e->GetCachedHash(phash->pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key)) { // Keep looking through the chain. prevIndex = index; @@ -600,7 +602,7 @@ public: e = &phash->E(index); } - if (index == (SPInt)ConstIterator::Index) + if (index == (intptr_t)ConstIterator::Index) { // Found it - our item is at index if (naturalIndex == index) @@ -633,7 +635,7 @@ public: private: friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; - Iterator(SelfType* h, SPInt i0) + Iterator(SelfType* h, intptr_t i0) : ConstIterator(h, i0) { } }; @@ -646,7 +648,7 @@ public: return Iterator(NULL, 0); // Scan till we hit the First valid Entry. - UPInt i0 = 0; + size_t i0 = 0; while (i0 <= pTable->SizeMask && E(i0).IsEmpty()) { i0++; @@ -661,7 +663,7 @@ public: template<class K> Iterator Find(const K& key) { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return Iterator(this, index); return Iterator(NULL, 0); @@ -670,7 +672,7 @@ public: template<class K> Iterator FindAlt(const K& key) { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return Iterator(this, index); return Iterator(NULL, 0); @@ -685,33 +687,33 @@ public: private: // Find the index of the matching Entry. If no match, then return -1. template<class K> - SPInt findIndex(const K& key) const + intptr_t findIndex(const K& key) const { if (pTable == NULL) return -1; - UPInt hashValue = HashF()(key) & pTable->SizeMask; + size_t hashValue = HashF()(key) & pTable->SizeMask; return findIndexCore(key, hashValue); } template<class K> - SPInt findIndexAlt(const K& key) const + intptr_t findIndexAlt(const K& key) const { if (pTable == NULL) return -1; - UPInt hashValue = AltHashF()(key) & pTable->SizeMask; + size_t hashValue = AltHashF()(key) & pTable->SizeMask; return findIndexCore(key, hashValue); } // Find the index of the matching Entry. If no match, then return -1. template<class K> - SPInt findIndexCore(const K& key, UPInt hashValue) const + intptr_t findIndexCore(const K& key, size_t hashValue) const { // Table must exist. OVR_ASSERT(pTable != 0); // Hash key must be 'and-ed' by the caller. OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0); - UPInt index = hashValue; + size_t index = hashValue; const Entry* e = &E(index); // If empty or occupied by a collider, not found. @@ -733,7 +735,7 @@ private: // Keep looking through the chain. index = e->NextInChain; - if (index == (UPInt)-1) + if (index == (size_t)-1) break; // end of chain e = &E(index); @@ -745,14 +747,14 @@ private: // Add a new value to the HashSet table, under the specified key. template<class CRef> - void add(const CRef& key, UPInt hashValue) + void add(const CRef& key, size_t hashValue) { CheckExpand(); hashValue &= pTable->SizeMask; pTable->EntryCount++; - SPInt index = hashValue; + intptr_t index = hashValue; Entry* naturalEntry = &(E(index)); if (naturalEntry->IsEmpty()) @@ -763,14 +765,14 @@ private: else { // Find a blank spot. - SPInt blankIndex = index; + intptr_t blankIndex = index; do { blankIndex = (blankIndex + 1) & pTable->SizeMask; } while(!E(blankIndex).IsEmpty()); Entry* blankEntry = &E(blankIndex); - if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index) + if (naturalEntry->GetCachedHash(pTable->SizeMask) == (size_t)index) { // Collision. Link into this chain. @@ -788,8 +790,8 @@ private: // Entry must be moved. // Find natural location of collided element (i.e. root of chain) - SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); - OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); + intptr_t collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask); for (;;) { Entry* e = &E(collidedIndex); @@ -801,7 +803,7 @@ private: break; } collidedIndex = e->NextInChain; - OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask); } // Put the new data in the natural Entry. @@ -815,13 +817,13 @@ private: } // Index access helpers. - Entry& E(UPInt index) + Entry& E(size_t index) { // Must have pTable and access needs to be within bounds. OVR_ASSERT(index <= pTable->SizeMask); return *(((Entry*) (pTable + 1)) + index); } - const Entry& E(UPInt index) const + const Entry& E(size_t index) const { OVR_ASSERT(index <= pTable->SizeMask); return *(((Entry*) (pTable + 1)) + index); @@ -832,7 +834,7 @@ private: // contents of the current table). The arg is the number of // HashSet table entries, not the number of elements we should // actually contain (which will be less than this). - void setRawCapacity(UPInt newSize) + void setRawCapacity(size_t newSize) { if (newSize == 0) { @@ -850,8 +852,8 @@ private: { // Force newSize to be a power of two. int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1); - OVR_ASSERT((UPInt(1) << bits) >= newSize); - newSize = UPInt(1) << bits; + OVR_ASSERT((size_t(1) << bits) >= newSize); + newSize = size_t(1) << bits; } SelfType newHash; @@ -863,7 +865,7 @@ private: newHash.pTable->EntryCount = 0; newHash.pTable->SizeMask = newSize - 1; - UPInt i, n; + size_t i, n; // Mark all entries as empty. for (i = 0; i < newSize; i++) @@ -895,8 +897,8 @@ private: struct TableType { - UPInt EntryCount; - UPInt SizeMask; + size_t EntryCount; + size_t SizeMask; // Entry array follows this structure // in memory. }; @@ -939,7 +941,7 @@ public: } // Hint the bucket count to >= n. - void Resize(UPInt n) + void Resize(size_t n) { BaseType::SetCapacity(n); } @@ -947,7 +949,7 @@ public: // Size the HashSet so that it can comfortably contain the given // number of elements. If the HashSet already contains more // elements than newSize, then this may be a no-op. - void SetCapacity(UPInt newSize) + void SetCapacity(size_t newSize) { BaseType::SetCapacity(newSize); } @@ -1004,7 +1006,7 @@ struct HashNode NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { } // Enable computation of ghash_node_hashf. - inline UPInt GetHash() const { return HashF()(*pFirst); } + inline size_t GetHash() const { return HashF()(*pFirst); } // Necessary conversion to allow HashNode::operator == to work. operator const C& () const { return *pFirst; } }; @@ -1018,20 +1020,20 @@ struct HashNode bool operator == (const K& src) const { return (First == src); } template<class K> - static UPInt CalcHash(const K& data) { return HashF()(data); } - inline UPInt GetHash() const { return HashF()(First); } + static size_t CalcHash(const K& data) { return HashF()(data); } + inline size_t GetHash() const { return HashF()(First); } // Hash functors used with this node. A separate functor is used for alternative // key lookup so that it does not need to access the '.First' element. struct NodeHashF { template<class K> - UPInt operator()(const K& data) const { return data.GetHash(); } + size_t operator()(const K& data) const { return data.GetHash(); } }; struct NodeAltHashF { template<class K> - UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } + size_t operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } }; }; @@ -1050,22 +1052,22 @@ class HashsetNodeEntry { public: // Internal chaining for collisions. - SPInt NextInChain; + intptr_t NextInChain; C Value; HashsetNodeEntry() : NextInChain(-2) { } HashsetNodeEntry(const HashsetNodeEntry& e) : NextInChain(e.NextInChain), Value(e.Value) { } - HashsetNodeEntry(const C& key, SPInt next) + HashsetNodeEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } - HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next) + HashsetNodeEntry(const typename C::NodeRef& keyRef, intptr_t next) : NextInChain(next), Value(keyRef) { } bool IsEmpty() const { return NextInChain == -2; } bool IsEndOfChain() const { return NextInChain == -1; } - UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } - void SetCachedHash(UPInt hashValue) { OVR_UNUSED(hashValue); } + size_t GetCachedHash(size_t maskValue) const { return HashF()(Value) & maskValue; } + void SetCachedHash(size_t hashValue) { OVR_UNUSED(hashValue); } void Clear() { @@ -1084,23 +1086,23 @@ class HashsetCachedNodeEntry { public: // Internal chaining for collisions. - SPInt NextInChain; - UPInt HashValue; + intptr_t NextInChain; + size_t HashValue; C Value; HashsetCachedNodeEntry() : NextInChain(-2) { } HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e) : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } - HashsetCachedNodeEntry(const C& key, SPInt next) + HashsetCachedNodeEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } - HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next) + HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, intptr_t next) : NextInChain(next), Value(keyRef) { } bool IsEmpty() const { return NextInChain == -2; } bool IsEndOfChain() const { return NextInChain == -1; } - UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } - void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } + size_t GetCachedHash(size_t maskValue) const { OVR_UNUSED(maskValue); return HashValue; } + void SetCachedHash(size_t hashValue) { HashValue = hashValue; } void Clear() { @@ -1227,9 +1229,10 @@ public: } // Sizing methods - delegate to Hash. - inline UPInt GetSize() const { return mHash.GetSize(); } - inline void Resize(UPInt n) { mHash.Resize(n); } - inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); } + inline size_t GetSize() const { return mHash.GetSize(); } + inline int GetSizeI() const { return (int)GetSize(); } + inline void Resize(size_t n) { mHash.Resize(n); } + inline void SetCapacity(size_t newSize) { mHash.SetCapacity(newSize); } // Iterator API, like STL. typedef typename Container::ConstIterator ConstIterator; diff --git a/LibOVR/Src/Kernel/OVR_KeyCodes.h b/LibOVR/Src/Kernel/OVR_KeyCodes.h index b5c5930..8ecdc8b 100644 --- a/LibOVR/Src/Kernel/OVR_KeyCodes.h +++ b/LibOVR/Src/Kernel/OVR_KeyCodes.h @@ -1,20 +1,20 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_KeyCodes.h Content : Common keyboard constants Created : September 19, 2012 -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, diff --git a/LibOVR/Src/Kernel/OVR_List.h b/LibOVR/Src/Kernel/OVR_List.h index 6b49f37..7e90af3 100644 --- a/LibOVR/Src/Kernel/OVR_List.h +++ b/LibOVR/Src/Kernel/OVR_List.h @@ -6,16 +6,16 @@ Content : Template implementation for doubly-connected linked List Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -55,6 +55,12 @@ struct ListNode void* pVoidNext; }; + ListNode() + { + pPrev = NULL; + pNext = NULL; + } + void RemoveNode() { pPrev->pNext = pNext; diff --git a/LibOVR/Src/Kernel/OVR_Lockless.cpp b/LibOVR/Src/Kernel/OVR_Lockless.cpp index 0f25805..6a5ec6b 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.cpp +++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp @@ -1,21 +1,20 @@ /************************************************************************************ -PublicHeader: OVR.h Filename : OVR_Lockless.cpp Content : Test logic for lock-less classes Created : December 27, 2013 Authors : Michael Antonov -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -33,13 +32,12 @@ limitations under the License. #include "OVR_Timer.h" #include "OVR_Log.h" - namespace OVR { namespace LocklessTest { const int TestIterations = 10000000; -// Use volatile dummys to force compiler to do spinning. +// Use volatile dummies to force compiler to do spinning. volatile int Dummy1; int Unused1[32]; volatile int Dummy2; @@ -91,7 +89,7 @@ struct TestData volatile bool FirstItemWritten = false; -LocklessUpdater<TestData> TestDataUpdater; +LocklessUpdater<TestData, TestData> TestDataUpdater; // Use this lock to verify that testing algorithm is otherwise correct... Lock TestLock; @@ -108,7 +106,6 @@ class Consumer : public Thread { LogText("LocklessTest::Consumer::Run started.\n"); - while (!FirstItemWritten) { // spin until producer wrote first value... @@ -216,13 +213,10 @@ void StartLocklessTest() producerThread->Start(); consumerThread->Start(); - /* while (!producerThread->IsFinished() && consumerThread->IsFinished()) { Thread::MSleep(500); - } */ - - // TBD: Cleanup + } } diff --git a/LibOVR/Src/Kernel/OVR_Lockless.h b/LibOVR/Src/Kernel/OVR_Lockless.h index a12f824..4d5b87e 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.h +++ b/LibOVR/Src/Kernel/OVR_Lockless.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Lockless.h Content : Lock-less classes for producer/consumer communication Created : November 9, 2013 Authors : John Carmack -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -42,14 +42,24 @@ namespace OVR { // necessarily getting every one that happens (vsync timing, SensorFusion updates). // // This is multiple consumer safe, but is currently only used with a single consumer. +// +// The SlotType can be the same as T, but should probably be a larger fixed size. +// This allows for forward compatibility when the updater is shared between processes. + +// FIXME: ExchangeAdd_Sync() should be replaced with a portable read-only primitive, +// so that the lockless pose state can be read-only on remote processes and to reduce +// false sharing between processes and improve performance. -template<class T> +template<class T, class SlotType> class LocklessUpdater { public: - LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) {} + LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) + { + OVR_COMPILER_ASSERT(sizeof(T) <= sizeof(SlotType)); + } - T GetState() const + T GetState() const { // Copy the state out, then retry with the alternate slot // if we determine that our copy may have been partially @@ -61,9 +71,9 @@ public: { // We are adding 0, only using these as atomic memory barriers, so it // is ok to cast off the const, allowing GetState() to remain const. - end = UpdateEnd.ExchangeAdd_Sync(0); + end = UpdateEnd.Load_Acquire(); state = Slots[ end & 1 ]; - begin = UpdateBegin.ExchangeAdd_Sync(0); + begin = UpdateBegin.Load_Acquire(); if ( begin == end ) { break; } @@ -71,7 +81,7 @@ public: // The producer is potentially blocked while only having partially // written the update, so copy out the other slot. state = Slots[ (begin & 1) ^ 1 ]; - final = UpdateBegin.ExchangeAdd_NoSync(0); + final = UpdateBegin.Load_Acquire(); if ( final == begin ) { break; } @@ -82,7 +92,7 @@ public: return state; } - void SetState( T state ) + void SetState( const T& state ) { const int slot = UpdateBegin.ExchangeAdd_Sync(1) & 1; // Write to (slot ^ 1) because ExchangeAdd returns 'previous' value before add. @@ -90,9 +100,9 @@ public: UpdateEnd.ExchangeAdd_Sync(1); } - mutable AtomicInt<int> UpdateBegin; - mutable AtomicInt<int> UpdateEnd; - T Slots[2]; + AtomicInt<int> UpdateBegin; + AtomicInt<int> UpdateEnd; + SlotType Slots[2]; }; diff --git a/LibOVR/Src/Kernel/OVR_Log.cpp b/LibOVR/Src/Kernel/OVR_Log.cpp index d5f8a68..2631879 100644 --- a/LibOVR/Src/Kernel/OVR_Log.cpp +++ b/LibOVR/Src/Kernel/OVR_Log.cpp @@ -5,16 +5,16 @@ Content : Logging support Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -28,23 +28,83 @@ limitations under the License. #include "OVR_Std.h" #include <stdarg.h> #include <stdio.h> +#include <time.h> +#include "../Kernel/OVR_System.h" +#include "../Kernel/OVR_DebugHelp.h" +#include "../Util/Util_SystemGUI.h" -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE) +#define WIN32_LEAN_AND_MEAN #include <windows.h> #elif defined(OVR_OS_ANDROID) #include <android/log.h> +#elif defined(OVR_OS_LINUX) || defined(OVR_OS_MAC) || defined(OVR_OS_UNIX) +#include <syslog.h> #endif + +class LogSubject : public OVR::SystemSingletonBase<LogSubject> +{ + static bool isShuttingDown; + +public: + + LogSubject(){ + isShuttingDown = false; + // Must be at end of function + PushDestroyCallbacks(); + } + + virtual ~LogSubject(){} // Required because we use delete this below. + + virtual void OnThreadDestroy() + { + isShuttingDown = true; + } + + virtual void OnSystemDestroy() + { + delete this; + } + + static bool IsValid() { + return isShuttingDown == false; + } + + OVR::Lock logSubjectLock; + OVR::ObserverScope<OVR::Log::LogHandler> logSubject; +}; + +bool LogSubject::isShuttingDown; + +OVR_DEFINE_SINGLETON(LogSubject); + namespace OVR { -// Global Log pointer. -Log* volatile OVR_GlobalLog = 0; + // Global Log pointer. + Log* volatile OVR_GlobalLog = 0; //----------------------------------------------------------------------------------- // ***** Log Implementation +Log::Log(unsigned logMask) : + LoggingMask(logMask) +{ +#ifdef OVR_OS_WIN32 + hEventSource = RegisterEventSourceA(NULL, "OculusVR"); + OVR_ASSERT(hEventSource != NULL); +#endif +} + Log::~Log() { +#ifdef OVR_OS_WIN32 + if (hEventSource) + { + DeregisterEventSource(hEventSource); + } +#endif + // Clear out global log if (this == OVR_GlobalLog) { @@ -52,6 +112,49 @@ Log::~Log() OVR_GlobalLog = 0; } } +void Log::AddLogObserver(ObserverScope<LogHandler> *logObserver) +{ + if (OVR::System::IsInitialized() && LogSubject::GetInstance()->IsValid()) + { + Lock::Locker locker(&LogSubject::GetInstance()->logSubjectLock); + logObserver->GetPtr()->Observe(LogSubject::GetInstance()->logSubject); + } +} +void Log::LogMessageVargInt(LogMessageType messageType, const char* fmt, va_list argList) +{ + if (OVR::System::IsInitialized() && LogSubject::GetInstance()->IsValid()) + { + // Invoke subject + char buffer[MaxLogBufferMessageSize]; + char* pBuffer = buffer; + char* pAllocated = NULL; + + #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list. + va_list argListSaved; + va_copy(argListSaved, argList); + #endif + + int result = FormatLog(pBuffer, MaxLogBufferMessageSize, Log_Text, fmt, argList); + + if(result >= MaxLogBufferMessageSize) // If there was insufficient capacity... + { + pAllocated = (char*)OVR_ALLOC(result + 1); // We assume C++ exceptions are disabled. FormatLog will handle the case that pAllocated is NULL. + pBuffer = pAllocated; + + #if !defined(OVR_CC_MSVC) + va_end(argList); // The caller owns argList and will call va_end on it. + va_copy(argList, argListSaved); + #endif + + FormatLog(pBuffer, (size_t)result + 1, Log_Text, fmt, argList); + } + + Lock::Locker locker(&LogSubject::GetInstance()->logSubjectLock); + LogSubject::GetInstance()->logSubject.GetPtr()->Call(pBuffer, messageType); + + delete[] pAllocated; + } +} void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList) { @@ -62,9 +165,32 @@ void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list ar return; #endif - char buffer[MaxLogBufferMessageSize]; - FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList); - DefaultLogOutput(buffer, IsDebugMessage(messageType)); + char buffer[MaxLogBufferMessageSize]; + char* pBuffer = buffer; + char* pAllocated = NULL; + + #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list. + va_list argListSaved; + va_copy(argListSaved, argList); + #endif + + int result = FormatLog(pBuffer, MaxLogBufferMessageSize, messageType, fmt, argList); + + if(result >= MaxLogBufferMessageSize) // If there was insufficient capacity... + { + pAllocated = (char*)OVR_ALLOC(result + 1); // We assume C++ exceptions are disabled. FormatLog will handle the case that pAllocated is NULL. + pBuffer = pAllocated; + + #if !defined(OVR_CC_MSVC) + va_end(argList); // The caller owns argList and will call va_end on it. + va_copy(argList, argListSaved); + #endif + + FormatLog(pBuffer, (size_t)result + 1, messageType, fmt, argList); + } + + DefaultLogOutput(pBuffer, messageType, result); + delete[] pAllocated; } void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...) @@ -76,35 +202,60 @@ void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...) } -void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, +// Return behavior is the same as ISO C vsnprintf: returns the required strlen of buffer (which will +// be >= bufferSize if bufferSize is insufficient) or returns a negative value because the input was bad. +int Log::FormatLog(char* buffer, size_t bufferSize, LogMessageType messageType, const char* fmt, va_list argList) -{ - bool addNewline = true; +{ + OVR_ASSERT(buffer && (bufferSize >= 10)); // Need to be able to at least print "Assert: \n" to it. + if(!buffer || (bufferSize < 10)) + return -1; + + int addNewline = 1; + int prefixLength = 0; switch(messageType) { - case Log_Error: OVR_strcpy(buffer, bufferSize, "Error: "); break; - case Log_Debug: OVR_strcpy(buffer, bufferSize, "Debug: "); break; - case Log_Assert: OVR_strcpy(buffer, bufferSize, "Assert: "); break; - case Log_Text: buffer[0] = 0; addNewline = false; break; - case Log_DebugText: buffer[0] = 0; addNewline = false; break; - default: - buffer[0] = 0; - addNewline = false; - break; + case Log_Error: OVR_strcpy(buffer, bufferSize, "Error: "); prefixLength = 7; break; + case Log_Debug: OVR_strcpy(buffer, bufferSize, "Debug: "); prefixLength = 7; break; + case Log_Assert: OVR_strcpy(buffer, bufferSize, "Assert: "); prefixLength = 8; break; + case Log_Text: buffer[0] = 0; addNewline = 0; break; + case Log_DebugText: buffer[0] = 0; addNewline = 0; break; + default: buffer[0] = 0; addNewline = 0; break; } - UPInt prefixLength = OVR_strlen(buffer); - char *buffer2 = buffer + prefixLength; - OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList); + char* buffer2 = buffer + prefixLength; + size_t size2 = bufferSize - (size_t)prefixLength; + int messageLength = OVR_vsnprintf(buffer2, size2, fmt, argList); if (addNewline) - OVR_strcat(buffer, bufferSize, "\n"); -} + { + if (messageLength < 0) // If there was a format error... + { + // To consider: append <format error> to the buffer here. + buffer2[0] = '\n'; // We are guaranteed to have capacity for this. + buffer2[1] = '\0'; + } + else + { + // If the printed string used all of the capacity or required more than the capacity, + // Chop the output by one character so we can append the \n safely. + int messageEnd = (messageLength >= (int)(size2 - 1)) ? (int)(size2 - 2) : messageLength; + buffer2[messageEnd + 0] = '\n'; + buffer2[messageEnd + 1] = '\0'; + } + } + + if (messageLength >= 0) // If the format was OK... + return prefixLength + messageLength + addNewline; // Return the required strlen of buffer. + return messageLength; // Else we cannot know what the required strlen is and return the error to the caller. +} -void Log::DefaultLogOutput(const char* formattedText, bool debug) +void Log::DefaultLogOutput(const char* formattedText, LogMessageType messageType, int bufferSize) { + bool debug = IsDebugMessage(messageType); + OVR_UNUSED(bufferSize); #if defined(OVR_OS_WIN32) // Under Win32, output regular messages to console if it exists; debug window otherwise. @@ -116,12 +267,15 @@ void Log::DefaultLogOutput(const char* formattedText, bool debug) { ::OutputDebugStringA(formattedText); } - else - { - fputs(formattedText, stdout); - } + + fputs(formattedText, stdout); + +#elif defined(OVR_OS_MS) // Any other Microsoft OSs + + ::OutputDebugStringA(formattedText); #elif defined(OVR_OS_ANDROID) + // To do: use bufferSize to deal with the case that Android has a limited output length. __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText); #else @@ -129,6 +283,24 @@ void Log::DefaultLogOutput(const char* formattedText, bool debug) #endif + if (messageType == Log_Error) + { +#if defined(OVR_OS_WIN32) + if (!ReportEventA(hEventSource, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, &formattedText, NULL)) + { + OVR_ASSERT(false); + } +#elif defined(OVR_OS_MS) // Any other Microsoft OSs + // TBD +#elif defined(OVR_OS_ANDROID) + // TBD +#elif defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) + syslog(LOG_ERR, "%s", formattedText); +#else + // TBD +#endif + } + // Just in case. OVR_UNUSED2(formattedText, debug); } @@ -161,16 +333,37 @@ Log* Log::GetDefaultLog() //----------------------------------------------------------------------------------- // ***** Global Logging functions +#if !defined(OVR_CC_MSVC) +// The reason for va_copy is because you can't use va_start twice on Linux +#define OVR_LOG_FUNCTION_IMPL(Name) \ + void Log##Name(const char* fmt, ...) \ + { \ + if (OVR_GlobalLog) \ + { \ + va_list argList1; \ + va_start(argList1, fmt); \ + va_list argList2; \ + va_copy(argList2, argList1); \ + OVR_GlobalLog->LogMessageVargInt(Log_##Name, fmt, argList2); \ + va_end(argList2); \ + OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList1); \ + va_end(argList1); \ + } \ + } +#else #define OVR_LOG_FUNCTION_IMPL(Name) \ void Log##Name(const char* fmt, ...) \ { \ if (OVR_GlobalLog) \ { \ - va_list argList; va_start(argList, fmt); \ - OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList); \ - va_end(argList); \ + va_list argList1; \ + va_start(argList1, fmt); \ + OVR_GlobalLog->LogMessageVargInt(Log_##Name, fmt, argList1); \ + OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList1); \ + va_end(argList1); \ } \ } +#endif // #if !defined(OVR_OS_WIN32) OVR_LOG_FUNCTION_IMPL(Text) OVR_LOG_FUNCTION_IMPL(Error) @@ -181,4 +374,59 @@ OVR_LOG_FUNCTION_IMPL(Debug) OVR_LOG_FUNCTION_IMPL(Assert) #endif + + +// Assertion handler support +// To consider: Move this to an OVR_Types.cpp or OVR_Assert.cpp source file. + +static OVRAssertionHandler sOVRAssertionHandler = OVR::DefaultAssertionHandler; +static intptr_t sOVRAssertionHandlerUserParameter = 0; + +OVRAssertionHandler GetAssertionHandler(intptr_t* userParameter) +{ + if(userParameter) + *userParameter = sOVRAssertionHandlerUserParameter; + return sOVRAssertionHandler; +} + +void SetAssertionHandler(OVRAssertionHandler assertionHandler, intptr_t userParameter) +{ + sOVRAssertionHandler = assertionHandler; + sOVRAssertionHandlerUserParameter = userParameter; +} + +intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message) +{ + if(OVRIsDebuggerPresent()) + { + OVR_DEBUG_BREAK; + } + else + { + #if defined(OVR_BUILD_DEBUG) + // Print a stack trace of all threads. + OVR::String s; + OVR::String threadListOutput; + static OVR::SymbolLookup symbolLookup; + + s = "Failure: "; + s += message; + + if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only. + { + s += "\r\n\r\n"; + s += threadListOutput; + } + + OVR::Util::DisplayMessageBox(title, s.ToCStr()); + #else + OVR::Util::DisplayMessageBox(title, message); + #endif + } + + return 0; +} + + + } // OVR diff --git a/LibOVR/Src/Kernel/OVR_Log.h b/LibOVR/Src/Kernel/OVR_Log.h index 4d9acc1..5982395 100644 --- a/LibOVR/Src/Kernel/OVR_Log.h +++ b/LibOVR/Src/Kernel/OVR_Log.h @@ -6,16 +6,16 @@ Content : Logging support Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -29,6 +29,8 @@ limitations under the License. #define OVR_Log_h #include "OVR_Types.h" +#include "../Kernel/OVR_Delegates.h" +#include "../Kernel//OVR_Observer.h" #include <stdarg.h> namespace OVR { @@ -92,7 +94,6 @@ enum LogMessageType # define OVR_LOG_VAARG_ATTRIBUTE(a,b) #endif - //----------------------------------------------------------------------------------- // ***** Log @@ -102,21 +103,34 @@ enum LogMessageType class Log { - friend class System; + friend class System; + +#ifdef OVR_OS_WIN32 + void* hEventSource; +#endif + public: - Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { } + Log(unsigned logMask = LogMask_Debug); virtual ~Log(); - // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated. + typedef Delegate2<void, const char*, LogMessageType> LogHandler; + + // The following is deprecated, as there is no longer a max log buffer message size. enum { MaxLogBufferMessageSize = 4096 }; unsigned GetLoggingMask() const { return LoggingMask; } void SetLoggingMask(unsigned logMask) { LoggingMask = logMask; } + // Internal + // Invokes observers, then calls LogMessageVarg() + static void LogMessageVargInt(LogMessageType messageType, const char* fmt, va_list argList); + // This virtual function receives all the messages, // developers should override this function in order to do custom logging virtual void LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList); + static void AddLogObserver(ObserverScope<LogHandler> *logObserver); + // Call the logging function with specific message type, with no type filtering. void LogMessage(LogMessageType messageType, const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4); @@ -124,14 +138,16 @@ public: // Helper used by LogMessageVarg to format the log message, writing the resulting // string into buffer. It formats text based on fmt and appends prefix/new line - // based on LogMessageType. - static void FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, + // based on LogMessageType. Return behavior is the same as ISO C vsnprintf: returns the + // required strlen of buffer (which will be >= bufferSize if bufferSize is insufficient) + // or returns a negative value because the input was bad. + static int FormatLog(char* buffer, size_t bufferSize, LogMessageType messageType, const char* fmt, va_list argList); // Default log output implementation used by by LogMessageVarg. // Debug flag may be used to re-direct output on some platforms, but doesn't // necessarily disable it in release builds; that is the job of the called. - static void DefaultLogOutput(const char* textBuffer, bool debug); + void DefaultLogOutput(const char* textBuffer, LogMessageType messageType, int bufferSize = -1); // Determines if the specified message type is for debugging only. static bool IsDebugMessage(LogMessageType messageType) @@ -184,18 +200,25 @@ void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); // Macro to do debug logging, printf-style. // An extra set of set of parenthesis must be used around arguments, - // as in: OVR_LOG_DEBUG(("Value %d", 2)). + // as in: OVR_DEBUG_LOG(("Value %d", 2)). #define OVR_DEBUG_LOG(args) do { OVR::LogDebug args; } while(0) #define OVR_DEBUG_LOG_TEXT(args) do { OVR::LogDebugText args; } while(0) - #define OVR_ASSERT_LOG(c, args) do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0) + // Conditional logging. It logs when the condition 'c' is true. + #define OVR_DEBUG_LOG_COND(c, args) do { if ((c)) { OVR::LogDebug args; } } while(0) + #define OVR_DEBUG_LOG_TEXT_COND(c, args) do { if ((c)) { OVR::LogDebugText args; } } while(0) + + // Conditional logging & asserting. It asserts/logs when the condition 'c' is NOT true. + #define OVR_ASSERT_LOG(c, args) do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0) #else // If not in debug build, macros do nothing. - #define OVR_DEBUG_LOG(args) ((void)0) - #define OVR_DEBUG_LOG_TEXT(args) ((void)0) - #define OVR_ASSERT_LOG(c, args) ((void)0) + #define OVR_DEBUG_LOG(args) ((void)0) + #define OVR_DEBUG_LOG_TEXT(args) ((void)0) + #define OVR_DEBUG_LOG_COND(c, args) ((void)0) + #define OVR_DEBUG_LOG_TEXT_COND(args) ((void)0) + #define OVR_ASSERT_LOG(c, args) ((void)0) #endif diff --git a/LibOVR/Src/Kernel/OVR_Math.cpp b/LibOVR/Src/Kernel/OVR_Math.cpp index 396d3ff..52977ed 100644 --- a/LibOVR/Src/Kernel/OVR_Math.cpp +++ b/LibOVR/Src/Kernel/OVR_Math.cpp @@ -5,16 +5,16 @@ Content : Implementation of 3D primitives such as vectors, matrices. Created : September 4, 2012 Authors : Andrew Reisse, Michael Antonov, Anna Yershova -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -34,45 +34,13 @@ namespace OVR { //------------------------------------------------------------------------------------- -// ***** Math - - -// Single-precision Math constants class. -const float Math<float>::Pi = 3.1415926f; -const float Math<float>::TwoPi = 3.1415926f * 2; -const float Math<float>::PiOver2 = 3.1415926f / 2.0f; -const float Math<float>::PiOver4 = 3.1415926f / 4.0f; -const float Math<float>::E = 2.7182818f; - -const float Math<float>::MaxValue = FLT_MAX; -const float Math<float>::MinPositiveValue = FLT_MIN; - -const float Math<float>::RadToDegreeFactor = 360.0f / Math<float>::TwoPi; -const float Math<float>::DegreeToRadFactor = Math<float>::TwoPi / 360.0f; - -const float Math<float>::Tolerance = 0.00001f; -const float Math<float>::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems - -// Double-precision Math constants class. -const double Math<double>::Pi = 3.14159265358979; -const double Math<double>::TwoPi = 3.14159265358979 * 2; -const double Math<double>::PiOver2 = 3.14159265358979 / 2.0; -const double Math<double>::PiOver4 = 3.14159265358979 / 4.0; -const double Math<double>::E = 2.71828182845905; - -const double Math<double>::MaxValue = DBL_MAX; -const double Math<double>::MinPositiveValue = DBL_MIN; - -const double Math<double>::RadToDegreeFactor = 360.0 / Math<double>::TwoPi; -const double Math<double>::DegreeToRadFactor = Math<double>::TwoPi / 360.0; - -const double Math<double>::Tolerance = 0.00001; -const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems - +// ***** Constants +template<> +const Vector3<float> Vector3<float>::ZERO = Vector3<float>(); -//------------------------------------------------------------------------------------- -// ***** Matrix4 +template<> +const Vector3<double> Vector3<double>::ZERO = Vector3<double>(); template<> const Matrix4<float> Matrix4<float>::IdentityValue = Matrix4<float>(1.0f, 0.0f, 0.0f, 0.0f, @@ -87,5 +55,4 @@ const Matrix4<double> Matrix4<double>::IdentityValue = Matrix4<double>(1.0, 0.0, 0.0, 0.0, 0.0, 1.0); - } // Namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_Math.h b/LibOVR/Src/Kernel/OVR_Math.h index 4aa42b0..c187cda 100644 --- a/LibOVR/Src/Kernel/OVR_Math.h +++ b/LibOVR/Src/Kernel/OVR_Math.h @@ -1,22 +1,22 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Math.h Content : Implementation of 3D primitives such as vectors, matrices. Created : September 4, 2012 Authors : Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova, Max Katsev, Dov Katz -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -125,7 +125,7 @@ template<class T> class Vector2; template<class T> class Vector3; template<class T> class Matrix3; template<class T> class Matrix4; -template<class T> class Transform; +template<class T> class Pose; template<class T> class PoseState; // CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class. @@ -134,7 +134,7 @@ struct CompatibleTypes { // Declaration here seems necessary for MSVC; specializations are // used instead. - typedef float Type; + typedef struct {} Type; }; // Specializations providing CompatibleTypes::Type value. @@ -150,11 +150,8 @@ template<> struct CompatibleTypes<Vector2<float> > { typedef ovrVector2f Type; template<> struct CompatibleTypes<Vector3<float> > { typedef ovrVector3f Type; }; template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; }; -template<> struct CompatibleTypes<Transform<float> > { typedef ovrPosef Type; }; -template<> struct CompatibleTypes<PoseState<float> > { typedef ovrPoseStatef Type; }; - -template<> struct CompatibleTypes<Transform<double> > { typedef ovrPosed Type; }; -template<> struct CompatibleTypes<PoseState<double> > { typedef ovrPoseStated Type; }; +template<> struct CompatibleTypes<Pose<float> > { typedef ovrPosef Type; }; +template<> struct CompatibleTypes<Pose<double> > { typedef ovrPosed Type; }; //------------------------------------------------------------------------------------// // ***** Math @@ -170,28 +167,40 @@ public: typedef float OtherFloatType; }; + +#define MATH_FLOAT_PI (3.1415926f) +#define MATH_FLOAT_TWOPI (2.0f *MATH_FLOAT_PI) +#define MATH_FLOAT_PIOVER2 (0.5f *MATH_FLOAT_PI) +#define MATH_FLOAT_PIOVER4 (0.25f*MATH_FLOAT_PI) +#define MATH_FLOAT_E (2.7182818f) +#define MATH_FLOAT_MAXVALUE (FLT_MAX) +#define MATH_FLOAT MINPOSITIVEVALUE (FLT_MIN) +#define MATH_FLOAT_RADTODEGREEFACTOR (360.0f / MATH_FLOAT_TWOPI) +#define MATH_FLOAT_DEGREETORADFACTOR (MATH_FLOAT_TWOPI / 360.0f) +#define MATH_FLOAT_TOLERANCE (0.00001f) +#define MATH_FLOAT_SINGULARITYRADIUS (0.0000001f) // Use for Gimbal lock numerical problems + +#define MATH_DOUBLE_PI (3.14159265358979) +#define MATH_DOUBLE_TWOPI (2.0f *MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER2 (0.5f *MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER4 (0.25f*MATH_DOUBLE_PI) +#define MATH_DOUBLE_E (2.71828182845905) +#define MATH_DOUBLE_MAXVALUE (DBL_MAX) +#define MATH_DOUBLE MINPOSITIVEVALUE (DBL_MIN) +#define MATH_DOUBLE_RADTODEGREEFACTOR (360.0f / MATH_DOUBLE_TWOPI) +#define MATH_DOUBLE_DEGREETORADFACTOR (MATH_DOUBLE_TWOPI / 360.0f) +#define MATH_DOUBLE_TOLERANCE (0.00001) +#define MATH_DOUBLE_SINGULARITYRADIUS (0.000000000001) // Use for Gimbal lock numerical problems + + + + // Single-precision Math constants class. template<> class Math<float> { public: - static const float Pi; - static const float TwoPi; - static const float PiOver2; - static const float PiOver4; - static const float E; - - static const float MaxValue; // Largest positive float Value - static const float MinPositiveValue; // Smallest possible positive value - - static const float RadToDegreeFactor; - static const float DegreeToRadFactor; - - static const float Tolerance; // 0.00001f; - static const float SingularityRadius; // 0.0000001f for Gimbal lock numerical problems - - // Used to support direct conversions in template classes. - typedef double OtherFloatType; + typedef double OtherFloatType; }; // Double-precision Math constants class. @@ -199,21 +208,6 @@ template<> class Math<double> { public: - static const double Pi; - static const double TwoPi; - static const double PiOver2; - static const double PiOver4; - static const double E; - - static const double MaxValue; // Largest positive double Value - static const double MinPositiveValue; // Smallest possible positive value - - static const double RadToDegreeFactor; - static const double DegreeToRadFactor; - - static const double Tolerance; // 0.00001; - static const double SingularityRadius; // 0.000000000001 for Gimbal lock numerical problems - typedef float OtherFloatType; }; @@ -223,23 +217,23 @@ typedef Math<double> Mathd; // Conversion functions between degrees and radians template<class T> -T RadToDegree(T rads) { return rads * Math<T>::RadToDegreeFactor; } +T RadToDegree(T rads) { return rads * ((T)MATH_DOUBLE_RADTODEGREEFACTOR); } template<class T> -T DegreeToRad(T rads) { return rads * Math<T>::DegreeToRadFactor; } +T DegreeToRad(T rads) { return rads * ((T)MATH_DOUBLE_DEGREETORADFACTOR); } // Numerically stable acos function template<class T> T Acos(T val) { if (val > T(1)) return T(0); - else if (val < T(-1)) return Math<T>::Pi; + else if (val < T(-1)) return ((T)MATH_DOUBLE_PI); else return acos(val); }; // Numerically stable asin function template<class T> T Asin(T val) { - if (val > T(1)) return Math<T>::PiOver2; - else if (val < T(-1)) return Math<T>::PiOver2 * T(3); + if (val > T(1)) return ((T)MATH_DOUBLE_PIOVER2); + else if (val < T(-1)) return ((T)MATH_DOUBLE_PIOVER2) * T(3); else return asin(val); }; @@ -277,7 +271,7 @@ public: operator const CompatibleType& () const { - OVR_COMPILER_ASSERT(sizeof(Vector2<T>) == sizeof(CompatibleType)); + static_assert(sizeof(Vector2<T>) == sizeof(CompatibleType), "sizeof(Vector2<T>) failure"); return reinterpret_cast<const CompatibleType&>(*this); } @@ -307,12 +301,24 @@ public: (a.y > b.y) ? a.y : b.y); } // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. - bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) + bool Compare(const Vector2&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); } - // Entrywise product of two vectors + // Access element by index + T& operator[] (int idx) + { + OVR_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + const T& operator[] (int idx) const + { + OVR_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + + // Entry-wise product of two vectors Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);} @@ -341,13 +347,13 @@ public: T Length() const { return sqrt(LengthSq()); } // Returns squared distance between two points represented by vectors. - T DistanceSq(Vector2& b) const { return (*this - b).LengthSq(); } + T DistanceSq(const Vector2& b) const { return (*this - b).LengthSq(); } // Returns distance between two points represented by vectors. - T Distance(Vector2& b) const { return (*this - b).Length(); } + T Distance(const Vector2& b) const { return (*this - b).Length(); } // Determine if this a unit vector. - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } // Normalize, convention vector length to 1. void Normalize() @@ -383,6 +389,10 @@ typedef Vector2<float> Vector2f; typedef Vector2<double> Vector2d; typedef Vector2<int> Vector2i; +typedef Vector2<float> Point2f; +typedef Vector2<double> Point2d; +typedef Vector2<int> Point2i; + //------------------------------------------------------------------------------------- // ***** Vector3<> - 3D vector of {x, y, z} @@ -396,12 +406,16 @@ class Vector3 public: T x, y, z; + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. Vector3() : x(0), y(0), z(0) { } Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { } explicit Vector3(T s) : x(s), y(s), z(s) { } explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src) : x((T)src.x), y((T)src.y), z((T)src.z) { } + static const Vector3 ZERO; // C-interop support. typedef typename CompatibleTypes<Vector3<T> >::Type CompatibleType; @@ -410,7 +424,7 @@ public: operator const CompatibleType& () const { - OVR_COMPILER_ASSERT(sizeof(Vector3<T>) == sizeof(CompatibleType)); + static_assert(sizeof(Vector3<T>) == sizeof(CompatibleType), "sizeof(Vector3<T>) failure"); return reinterpret_cast<const CompatibleType&>(*this); } @@ -447,7 +461,7 @@ public: } // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. - bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) + bool Compare(const Vector3&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && @@ -515,7 +529,7 @@ public: T Distance(Vector3 const& b) const { return (*this - b).Length(); } // Determine if this a unit vector. - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } // Normalize, convention vector length to 1. void Normalize() @@ -550,27 +564,208 @@ public: Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); } }; - typedef Vector3<float> Vector3f; typedef Vector3<double> Vector3d; -typedef Vector3<SInt32> Vector3i; +typedef Vector3<int32_t> Vector3i; + +static_assert((sizeof(Vector3f) == 3*sizeof(float)), "sizeof(Vector3f) failure"); +static_assert((sizeof(Vector3d) == 3*sizeof(double)), "sizeof(Vector3d) failure"); +static_assert((sizeof(Vector3i) == 3*sizeof(int32_t)), "sizeof(Vector3i) failure"); + +typedef Vector3<float> Point3f; +typedef Vector3<double> Point3d; +typedef Vector3<int32_t> Point3i; -// JDC: this was defined in Render_Device.h, I moved it here, but it -// needs to be fleshed out like the other Vector types. +//------------------------------------------------------------------------------------- +// ***** Vector4<> - 4D vector of {x, y, z, w} + // -// A vector with a dummy w component for alignment in uniform buffers (and for float colors). -// The w component is not used in any calculations. +// Vector4f (Vector4d) represents a 3-dimensional vector or point in space, +// consisting of coordinates x, y, z and w. + +template<class T> +class Vector4 +{ +public: + T x, y, z, w; + + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. + Vector4() : x(0), y(0), z(0), w(0) { } + Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { } + explicit Vector4(T s) : x(s), y(s), z(s), w(s) { } + explicit Vector4(const Vector3<T>& v, const float w_=1) : x(v.x), y(v.y), z(v.z), w(w_) { } + explicit Vector4(const Vector4<typename Math<T>::OtherFloatType> &src) + : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { } + + static const Vector4 ZERO; + + // C-interop support. + typedef typename CompatibleTypes< Vector4<T> >::Type CompatibleType; + + Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + + operator const CompatibleType& () const + { + static_assert(sizeof(Vector4<T>) == sizeof(CompatibleType), "sizeof(Vector4<T>) failure"); + return reinterpret_cast<const CompatibleType&>(*this); + } + + Vector4& operator= (const Vector3<T>& other) { x=other.x; y=other.y; z=other.z; w=1; return *this; } + bool operator== (const Vector4& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } + bool operator!= (const Vector4& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } + + Vector4 operator+ (const Vector4& b) const { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); } + Vector4& operator+= (const Vector4& b) { x += b.x; y += b.y; z += b.z; w += b.w; return *this; } + Vector4 operator- (const Vector4& b) const { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); } + Vector4& operator-= (const Vector4& b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; } + Vector4 operator- () const { return Vector4(-x, -y, -z, -w); } + + // Scalar multiplication/division scales vector. + Vector4 operator* (T s) const { return Vector4(x*s, y*s, z*s, w*s); } + Vector4& operator*= (T s) { x *= s; y *= s; z *= s; w *= s;return *this; } + + Vector4 operator/ (T s) const { T rcp = T(1)/s; + return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); } + Vector4& operator/= (T s) { T rcp = T(1)/s; + x *= rcp; y *= rcp; z *= rcp; w *= rcp; + return *this; } + + static Vector4 Min(const Vector4& a, const Vector4& b) + { + return Vector4((a.x < b.x) ? a.x : b.x, + (a.y < b.y) ? a.y : b.y, + (a.z < b.z) ? a.z : b.z, + (a.w < b.w) ? a.w : b.w); + } + static Vector4 Max(const Vector4& a, const Vector4& b) + { + return Vector4((a.x > b.x) ? a.x : b.x, + (a.y > b.y) ? a.y : b.y, + (a.z > b.z) ? a.z : b.z, + (a.w > b.w) ? a.w : b.w); + } + + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. + bool Compare(const Vector4&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) + { + return (fabs(b.x-x) < tolerance) && + (fabs(b.y-y) < tolerance) && + (fabs(b.z-z) < tolerance) && + (fabs(b.w-w) < tolerance); + } + + T& operator[] (int idx) + { + OVR_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + const T& operator[] (int idx) const + { + OVR_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + // Entry wise product of two vectors + Vector4 EntrywiseMultiply(const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z);} + + // Multiply and divide operators do entry-wise math + Vector4 operator* (const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z, + w * b.w); } + + Vector4 operator/ (const Vector4& b) const { return Vector4(x / b.x, + y / b.y, + z / b.z, + w / b.w); } + + + // Dot product + T Dot(const Vector4& b) const { return x*b.x + y*b.y + z*b.z + w*b.w; } + + // Return Length of the vector squared. + T LengthSq() const { return (x * x + y * y + z * z + w * w); } + + // Return vector length. + T Length() const { return sqrt(LengthSq()); } + + // Determine if this a unit vector. + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + + // Normalize, convention vector length to 1. + void Normalize() + { + T l = Length(); + OVR_ASSERT(l != T(0)); + *this /= l; + } + + // Returns normalized (unit) version of the vector without modifying itself. + Vector4 Normalized() const + { + T l = Length(); + OVR_ASSERT(l != T(0)); + return *this / l; + } +}; + +typedef Vector4<float> Vector4f; +typedef Vector4<double> Vector4d; +typedef Vector4<int> Vector4i; + -struct Vector4f : public Vector3f +//------------------------------------------------------------------------------------- +// ***** Bounds3 + +// Bounds class used to describe a 3D axis aligned bounding box. + +template<class T> +class Bounds3 { - float w; +public: + Vector3<T> b[2]; + + Bounds3() + { + } + + Bounds3( const Vector3<T> & mins, const Vector3<T> & maxs ) +{ + b[0] = mins; + b[1] = maxs; + } - Vector4f() : w(1) {} - Vector4f(const Vector3f& v) : Vector3f(v), w(1) {} - Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {} + void Clear() + { + b[0].x = b[0].y = b[0].z = Math<T>::MaxValue; + b[1].x = b[1].y = b[1].z = -Math<T>::MaxValue; + } + + void AddPoint( const Vector3<T> & v ) + { + b[0].x = Alg::Min( b[0].x, v.x ); + b[0].y = Alg::Min( b[0].y, v.y ); + b[0].z = Alg::Min( b[0].z, v.z ); + b[1].x = Alg::Max( b[1].x, v.x ); + b[1].y = Alg::Max( b[1].y, v.y ); + b[1].z = Alg::Max( b[1].z, v.z ); + } + + const Vector3<T> & GetMins() const { return b[0]; } + const Vector3<T> & GetMaxs() const { return b[1]; } + + Vector3<T> & GetMins() { return b[0]; } + Vector3<T> & GetMaxs() { return b[1]; } }; +typedef Bounds3<float> Bounds3f; +typedef Bounds3<double> Bounds3d; //------------------------------------------------------------------------------------- @@ -598,7 +793,7 @@ public: operator const CompatibleType& () const { - OVR_COMPILER_ASSERT(sizeof(Size<T>) == sizeof(CompatibleType)); + static_assert(sizeof(Size<T>) == sizeof(CompatibleType), "sizeof(Size<T>) failure"); return reinterpret_cast<const CompatibleType&>(*this); } @@ -626,7 +821,6 @@ public: static Size Max(const Size& a, const Size& b) { return Size((a.w > b.w) ? a.w : b.w, (a.h > b.h) ? a.h : b.h); } - T Area() const { return w * h; } inline Vector2<T> ToVector() const { return Vector2<T>(w, h); } @@ -663,7 +857,7 @@ public: operator const CompatibleType& () const { - OVR_COMPILER_ASSERT(sizeof(Rect<T>) == sizeof(CompatibleType)); + static_assert(sizeof(Rect<T>) == sizeof(CompatibleType), "sizeof(Rect<T>) failure"); return reinterpret_cast<const CompatibleType&>(*this); } @@ -702,12 +896,14 @@ public: explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src) : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { } + typedef typename CompatibleTypes<Quat<T> >::Type CompatibleType; + // C-interop support. - Quat(const typename CompatibleTypes<Quat<T> >::Type& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + Quat(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } - operator typename CompatibleTypes<Quat<T> >::Type () const + operator CompatibleType () const { - typename CompatibleTypes<Quat<T> >::Type result; + CompatibleType result; result.x = x; result.y = y; result.z = z; @@ -753,12 +949,12 @@ public: // Compute axis and angle from quaternion void GetAxisAngle(Vector3<T>* axis, T* angle) const { - if ( x*x + y*y + z*z > Math<T>::Tolerance * Math<T>::Tolerance ) { + if ( x*x + y*y + z*z > ((T)MATH_DOUBLE_TOLERANCE) * ((T)MATH_DOUBLE_TOLERANCE) ) { *axis = Vector3<T>(x, y, z).Normalized(); *angle = 2 * Acos(w); - if (*angle > Math<T>::Pi) // Reduce the magnitude of the angle, if necessary + if (*angle > ((T)MATH_DOUBLE_PI)) // Reduce the magnitude of the angle, if necessary { - *angle = Math<T>::TwoPi - *angle; + *angle = ((T)MATH_DOUBLE_TWOPI) - *angle; *axis = *axis * (-1); } } @@ -903,7 +1099,7 @@ public: } // Normalize - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } void Normalize() { @@ -973,10 +1169,10 @@ public: // is followed by rotation b around axis A2 // is followed by rotation c around axis A3 // rotations are CCW or CW (D) in LH or RH coordinate system (S) - template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> - void GetEulerAngles(T *a, T *b, T *c) const + template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> + void GetEulerAngles(T *a, T *b, T *c) const { - OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); + static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)"); T Q[3] = { x, y, z }; //Quaternion components x,y,z @@ -992,17 +1188,17 @@ public: T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]); - if (s2 < T(-1) + Math<T>::SingularityRadius) + if (s2 < T(-1) + ((T)MATH_DOUBLE_SINGULARITYRADIUS)) { // South pole singularity *a = T(0); - *b = -S*D*Math<T>::PiOver2; + *b = -S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33 ); } - else if (s2 > T(1) - Math<T>::SingularityRadius) + else if (s2 > T(1) - ((T)MATH_DOUBLE_SINGULARITYRADIUS)) { // North pole singularity *a = T(0); - *b = S*D*Math<T>::PiOver2; + *b = S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33); } @@ -1025,7 +1221,6 @@ public: void GetEulerAngles(T *a, T *b, T *c) const { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); } - // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of // axis rotations and the specified coordinate system. Right-handed coordinate system // is the default, with CCW rotations while looking in the negative axis direction. @@ -1037,7 +1232,7 @@ public: template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> void GetEulerAnglesABA(T *a, T *b, T *c) const { - OVR_COMPILER_ASSERT(A1 != A2); + static_assert(A1 != A2, "A1 != A2"); T Q[3] = {x, y, z}; // Quaternion components @@ -1059,7 +1254,7 @@ public: if (c2 < T(-1) + Math<T>::SingularityRadius) { // South pole singularity *a = T(0); - *b = S*D*Math<T>::Pi; + *b = S*D*((T)MATH_DOUBLE_PI); *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]), ww + Q22 - Q11 - Qmm); } @@ -1085,31 +1280,33 @@ public: typedef Quat<float> Quatf; typedef Quat<double> Quatd; +static_assert((sizeof(Quatf) == 4*sizeof(float)), "sizeof(Quatf) failure"); +static_assert((sizeof(Quatd) == 4*sizeof(double)), "sizeof(Quatd) failure"); + //------------------------------------------------------------------------------------- // ***** Pose // Position and orientation combined. template<class T> -class Transform +class Pose { public: + typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType; - typedef typename CompatibleTypes<Transform<T> >::Type CompatibleType; - - Transform() { } - Transform(const Quat<T>& orientation, const Vector3<T>& pos) + Pose() { } + Pose(const Quat<T>& orientation, const Vector3<T>& pos) : Rotation(orientation), Translation(pos) { } - Transform(const Transform& s) + Pose(const Pose& s) : Rotation(s.Rotation), Translation(s.Translation) { } - Transform(const CompatibleType& s) + Pose(const CompatibleType& s) : Rotation(s.Orientation), Translation(s.Position) { } - explicit Transform(const Transform<typename Math<T>::OtherFloatType> &s) + explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s) : Rotation(s.Rotation), Translation(s.Translation) { } - operator typename CompatibleTypes<Transform<T> >::Type () const + operator typename CompatibleTypes<Pose<T> >::Type () const { - typename CompatibleTypes<Transform<T> >::Type result; + typename CompatibleTypes<Pose<T> >::Type result; result.Orientation = Rotation; result.Position = Translation; return result; @@ -1117,6 +1314,21 @@ public: Quat<T> Rotation; Vector3<T> Translation; + + static_assert((sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float)), "(sizeof(T) == sizeof(double) || sizeof(T) == sizeof(float))"); + + void ToArray(T* arr) const + { + T temp[7] = { Rotation.x, Rotation.y, Rotation.z, Rotation.w, Translation.x, Translation.y, Translation.z }; + for (int i = 0; i < 7; i++) arr[i] = temp[i]; + } + + static Pose<T> FromArray(const T* v) + { + Quat<T> rotation(v[0], v[1], v[2], v[3]); + Vector3<T> translation(v[4], v[5], v[6]); + return Pose<T>(rotation, translation); + } Vector3<T> Rotate(const Vector3<T>& v) const { @@ -1133,32 +1345,24 @@ public: return Translate(Rotate(v)); } - Transform operator*(const Transform& other) const - { - return Transform(Rotation * other.Rotation, Apply(other.Translation)); - } - - PoseState<T> operator*(const PoseState<T>& poseState) const + Pose operator*(const Pose& other) const { - PoseState<T> result; - result.Pose = (*this) * poseState.Pose; - result.LinearVelocity = this->Rotate(poseState.LinearVelocity); - result.LinearAcceleration = this->Rotate(poseState.LinearAcceleration); - result.AngularVelocity = this->Rotate(poseState.AngularVelocity); - result.AngularAcceleration = this->Rotate(poseState.AngularAcceleration); - return result; + return Pose(Rotation * other.Rotation, Apply(other.Translation)); } - Transform Inverted() const + Pose Inverted() const { Quat<T> inv = Rotation.Inverted(); - return Transform(inv, inv.Rotate(-Translation)); + return Pose(inv, inv.Rotate(-Translation)); } }; -typedef Transform<float> Transformf; -typedef Transform<double> Transformd; +typedef Pose<float> Posef; +typedef Pose<double> Posed; +static_assert((sizeof(Posed) == sizeof(Quatd) + sizeof(Vector3d)), "sizeof(Posed) failure"); +static_assert((sizeof(Posef) == sizeof(Quatf) + sizeof(Vector3f)), "sizeof(Posef) failure"); + //------------------------------------------------------------------------------------- // ***** Matrix4 @@ -1241,7 +1445,7 @@ public: M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1; } - explicit Matrix4(const Transform<T>& p) + explicit Matrix4(const Pose<T>& p) { Matrix4 result(p.Rotation); result.SetTranslation(p.Translation); @@ -1259,21 +1463,21 @@ public: // C-interop support. Matrix4(const typename CompatibleTypes<Matrix4<T> >::Type& s) { - OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix4)); + static_assert(sizeof(s) == sizeof(Matrix4), "sizeof(s) == sizeof(Matrix4)"); memcpy(M, s.M, sizeof(M)); } operator typename CompatibleTypes<Matrix4<T> >::Type () const { typename CompatibleTypes<Matrix4<T> >::Type result; - OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix4)); + static_assert(sizeof(result) == sizeof(Matrix4), "sizeof(result) == sizeof(Matrix4)"); memcpy(result.M, M, sizeof(M)); return result; } - void ToString(char* dest, UPInt destsize) const + void ToString(char* dest, size_t destsize) const { - UPInt pos = 0; + size_t pos = 0; for (int r=0; r<4; r++) for (int c=0; c<4; c++) pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); @@ -1282,15 +1486,24 @@ public: static Matrix4 FromString(const char* src) { Matrix4 result; + if (src) + { for (int r=0; r<4; r++) + { for (int c=0; c<4; c++) { result.M[r][c] = (T)atof(src); while (src && *src != ' ') + { src++; + } while (src && *src == ' ') + { src++; } + } + } + } return result; } @@ -1304,6 +1517,39 @@ public: M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0; } + void SetXBasis(const Vector3f & v) + { + M[0][0] = v.x; + M[1][0] = v.y; + M[2][0] = v.z; + } + Vector3f GetXBasis() const + { + return Vector3f(M[0][0], M[1][0], M[2][0]); + } + + void SetYBasis(const Vector3f & v) + { + M[0][1] = v.x; + M[1][1] = v.y; + M[2][1] = v.z; + } + Vector3f GetYBasis() const + { + return Vector3f(M[0][1], M[1][1], M[2][1]); + } + + void SetZBasis(const Vector3f & v) + { + M[0][2] = v.x; + M[1][2] = v.y; + M[2][2] = v.z; + } + Vector3f GetZBasis() const + { + return Vector3f(M[0][2], M[1][2], M[2][2]); + } + bool operator== (const Matrix4& b) const { bool isEqual = true; @@ -1404,9 +1650,18 @@ public: Vector3<T> Transform(const Vector3<T>& v) const { - return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3], - M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3], - M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]); + const T rcpW = 1.0f / (M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3]); + return Vector3<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3]) * rcpW, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3]) * rcpW, + (M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]) * rcpW); + } + + Vector4<T> Transform(const Vector4<T>& v) const + { + return Vector4<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3] * v.w, + M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3] * v.w, + M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3] * v.w, + M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3] * v.w); } Matrix4 Transposed() const @@ -1423,16 +1678,16 @@ public: } - T SubDet (const UPInt* rows, const UPInt* cols) const + T SubDet (const size_t* rows, const size_t* cols) const { return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]); } - T Cofactor(UPInt I, UPInt J) const + T Cofactor(size_t I, size_t J) const { - const UPInt indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; + const size_t indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); } @@ -1488,9 +1743,9 @@ public: // is followed by rotation c around axis A3 // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> - void ToEulerAngles(T *a, T *b, T *c) + void ToEulerAngles(T *a, T *b, T *c) const { - OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); + static_assert((A1 != A2) && (A2 != A3) && (A1 != A3), "(A1 != A2) && (A2 != A3) && (A1 != A3)"); T psign = -1; if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation @@ -1500,13 +1755,13 @@ public: if (pm < -1.0f + Math<T>::SingularityRadius) { // South pole singularity *a = 0; - *b = -S*D*Math<T>::PiOver2; + *b = -S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); } else if (pm > 1.0f - Math<T>::SingularityRadius) { // North pole singularity *a = 0; - *b = S*D*Math<T>::PiOver2; + *b = S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); } else @@ -1526,9 +1781,9 @@ public: // is followed by rotation c around axis A1 // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> - void ToEulerAnglesABA(T *a, T *b, T *c) + void ToEulerAnglesABA(T *a, T *b, T *c) const { - OVR_COMPILER_ASSERT(A1 != A2); + static_assert(A1 != A2, "A1 != A2"); // Determine the axis that was not supplied int m = 3 - A1 - A2; @@ -1541,7 +1796,7 @@ public: if (c2 < -1 + Math<T>::SingularityRadius) { // South pole singularity *a = 0; - *b = S*D*Math<T>::Pi; + *b = S*D*((T)MATH_DOUBLE_PI); *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); } else if (c2 > 1.0f - Math<T>::SingularityRadius) @@ -1781,19 +2036,20 @@ public: Matrix4 m; T tanHalfFov = tan(yfov * 0.5f); - m.M[0][0] = 1 / (aspect * tanHalfFov); - m.M[1][1] = 1 / tanHalfFov; - m.M[2][2] = zfar / (zfar - znear); - m.M[3][2] = 1; + m.M[0][0] = 1. / (aspect * tanHalfFov); + m.M[1][1] = 1. / tanHalfFov; + m.M[2][2] = zfar / (znear - zfar); + m.M[3][2] = -1.; m.M[2][3] = (zfar * znear) / (znear - zfar); - m.M[3][3] = 0; + m.M[3][3] = 0.; // Note: Post-projection matrix result assumes Left-Handed coordinate system, // with Y up, X right and Z forward. This supports positive z-buffer values. + // This is the case even for RHS coordinate input. return m; } - // PerspectiveRH creates a left-handed perspective projection matrix that can be + // PerspectiveLH creates a left-handed perspective projection matrix that can be // used with the Oculus sample renderer. // yfov - Specifies vertical field of view in radians. // aspect - Screen aspect ration, which is usually width/height for square pixels. @@ -1805,17 +2061,17 @@ public: Matrix4 m; T tanHalfFov = tan(yfov * 0.5f); - m.M[0][0] = 1.0 / (aspect * tanHalfFov); - m.M[1][1] = 1.0 / tanHalfFov; - m.M[2][2] = zfar / (znear - zfar); - // m.M[2][2] = zfar / (zfar - znear); - m.M[3][2] = -1.0; + m.M[0][0] = 1. / (aspect * tanHalfFov); + m.M[1][1] = 1. / tanHalfFov; + //m.M[2][2] = zfar / (znear - zfar); + m.M[2][2] = zfar / (zfar - znear); + m.M[3][2] = -1.; m.M[2][3] = (zfar * znear) / (znear - zfar); - m.M[3][3] = 0.0; + m.M[3][3] = 0.; // Note: Post-projection matrix result assumes Left-Handed coordinate system, // with Y up, X right and Z forward. This supports positive z-buffer values. - // This is the case even for RHS cooridnate input. + // This is the case even for RHS coordinate input. return m; } @@ -1916,7 +2172,7 @@ public: M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0; } - explicit Matrix3(const Transform<T>& p) + explicit Matrix3(const Pose<T>& p) { Matrix3 result(p.Rotation); result.SetTranslation(p.Translation); @@ -1934,21 +2190,21 @@ public: // C-interop support. Matrix3(const typename CompatibleTypes<Matrix3<T> >::Type& s) { - OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix3)); + static_assert(sizeof(s) == sizeof(Matrix3), "sizeof(s) == sizeof(Matrix3)"); memcpy(M, s.M, sizeof(M)); } - operator typename CompatibleTypes<Matrix3<T> >::Type () const + operator const typename CompatibleTypes<Matrix3<T> >::Type () const { typename CompatibleTypes<Matrix3<T> >::Type result; - OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix3)); + static_assert(sizeof(result) == sizeof(Matrix3), "sizeof(result) == sizeof(Matrix3)"); memcpy(result.M, M, sizeof(M)); return result; } - void ToString(char* dest, UPInt destsize) const + void ToString(char* dest, size_t destsize) const { - UPInt pos = 0; + size_t pos = 0; for (int r=0; r<3; r++) for (int c=0; c<3; c++) pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); @@ -2108,6 +2364,13 @@ public: return *this; } + Vector2<T> Transform(const Vector2<T>& v) const + { + const float rcpZ = 1.0f / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]); + return Vector2<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2]) * rcpZ, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2]) * rcpZ); + } + Vector3<T> Transform(const Vector3<T>& v) const { return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z, @@ -2128,7 +2391,7 @@ public: } - T SubDet (const UPInt* rows, const UPInt* cols) const + T SubDet (const size_t* rows, const size_t* cols) const { return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) @@ -2415,10 +2678,10 @@ public: Angle() : a(0) {} // Fix the range to be between -Pi and Pi - Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); } + Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*((T)MATH_DOUBLE_DEGREETORADFACTOR)) { FixRange(); } - T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; } - void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); } + T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*((T)MATH_DOUBLE_RADTODEGREEFACTOR); } + void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*((T)MATH_DOUBLE_DEGREETORADFACTOR); FixRange(); } int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } T Abs() const { return (a > 0) ? a : -a; } @@ -2440,7 +2703,7 @@ public: Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; } Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; } - T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; } + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= ((T)MATH_DOUBLE_PI)) ? c : ((T)MATH_DOUBLE_TWOPI) - c; } private: @@ -2450,23 +2713,23 @@ private: // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side inline void FastFixRange() { - if (a < -Math<T>::Pi) - a += Math<T>::TwoPi; - else if (a > Math<T>::Pi) - a -= Math<T>::TwoPi; + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); } // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method inline void FixRange() { // do nothing if the value is already in the correct range, since fmod call is expensive - if (a >= -Math<T>::Pi && a <= Math<T>::Pi) + if (a >= -((T)MATH_DOUBLE_PI) && a <= ((T)MATH_DOUBLE_PI)) return; - a = fmod(a,Math<T>::TwoPi); - if (a < -Math<T>::Pi) - a += Math<T>::TwoPi; - else if (a > Math<T>::Pi) - a -= Math<T>::TwoPi; + a = fmod(a,((T)MATH_DOUBLE_TWOPI)); + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); } }; @@ -2481,7 +2744,7 @@ typedef Angle<double> Angled; // Consists of a normal vector and distance from the origin where the plane is located. template<class T> -class Plane : public RefCountBase<Plane<T> > +class Plane { public: Vector3<T> N; @@ -2520,6 +2783,8 @@ public: }; typedef Plane<float> Planef; +typedef Plane<double> Planed; + } // Namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_Nullptr.h b/LibOVR/Src/Kernel/OVR_Nullptr.h new file mode 100644 index 0000000..a09f446 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Nullptr.h @@ -0,0 +1,150 @@ +/************************************************************************************ + +PublicHeader: OVR_Kernel.h +Filename : OVR_Nullptr.h +Content : Implements C++11 nullptr for the case that the compiler doesn't. +Created : June 19, 2014 +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. + +************************************************************************************/ + +#ifndef OVR_Nullptr_h +#define OVR_Nullptr_h + +#pragma once + +#include "OVR_Types.h" + + +//----------------------------------------------------------------------------------- +// ***** OVR_HAVE_std_nullptr_t +// +// Identifies if <cstddef.h> includes std::nullptr_t. +// +#if !defined(OVR_HAVE_std_nullptr_t) && defined(OVR_CPP11_ENABLED) + #if defined(OVR_STDLIB_LIBCPP) + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(OVR_STDLIB_LIBSTDCPP) + #if (__GLIBCXX__ >= 20110325) && (__GLIBCXX__ != 20110428) && (__GLIBCXX__ != 20120702) + #define OVR_HAVE_std_nullptr_t 1 + #endif + #elif defined(_MSC_VER) && (_MSC_VER >= 1600) // VS2010+ + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(__clang__) + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(OVR_CPP_GNUC) && (OVR_CC_VERSION >= 406) // GCC 4.6+ + #define OVR_HAVE_std_nullptr_t 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** nullptr / std::nullptr_t +// +// Declares and defines nullptr and related types. +// +#if defined(OVR_CPP_NO_NULLPTR) + namespace std + { + class nullptr_t + { + public: + template <typename T> + operator T*() const + { return 0; } + + template <typename C, typename T> + operator T C::*() const + { return 0; } + + #if OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS + typedef void* (nullptr_t::*bool_)() const; // 4.12,p1. We can't portably use operator bool(){ return false; } because bool + operator bool_() const // is convertable to int which breaks other required functionality. + { return false; } + #else + operator bool() const + { return false; } + #endif + + private: + void operator&() const; // 5.2.10,p9 + }; + + inline nullptr_t nullptr_get() + { + nullptr_t n = { }; + return n; + } + + #if !defined(nullptr) + #define nullptr nullptr_get() + #endif + + } // namespace std + + + // 5.9,p2 p4 + // 13.6, p13 + template <typename T> + inline bool operator==(T* pT, const std::nullptr_t) + { return pT == 0; } + + template <typename T> + inline bool operator==(const std::nullptr_t, T* pT) + { return pT == 0; } + + template <typename T, typename U> + inline bool operator==(const std::nullptr_t, T U::* pU) + { return pU == 0; } + + template <typename T, typename U> + inline bool operator==(T U::* pTU, const std::nullptr_t) + { return pTU == 0; } + + inline bool operator==(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator!=(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator>(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator>=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + using std::nullptr_t; + using std::nullptr_get; + +// Some compilers natively support C++11 nullptr but the standard library being used +// doesn't declare std::nullptr_t, in which case we provide one ourselves. +#elif !defined(OVR_HAVE_std_nullptr_t) && !defined(OVR_CPP_NO_DECLTYPE) + namespace std { typedef decltype(nullptr) nullptr_t; } +#endif + + +#endif + diff --git a/LibOVR/Src/Kernel/OVR_Observer.h b/LibOVR/Src/Kernel/OVR_Observer.h new file mode 100644 index 0000000..76b4be6 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Observer.h @@ -0,0 +1,457 @@ +/************************************************************************************ + +PublicHeader: Kernel +Filename : OVR_Observer.h +Content : Observer pattern +Created : June 20, 2014 +Author : Chris Taylor + +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. + +************************************************************************************/ + +#ifndef OVR_Observer_h +#define OVR_Observer_h + +#include "OVR_Types.h" +#include "OVR_Atomic.h" +#include "OVR_RefCount.h" +#include "OVR_Delegates.h" +#include "OVR_Array.h" +#include "OVR_String.h" +#include "OVR_Hash.h" + +namespace OVR { + +template<class DelegateT> class Observer; +template<class DelegateT> class ObserverScope; +template<class DelegateT> class ObserverHash; + + +//----------------------------------------------------------------------------- +// Observer pattern + +// An Observer will observe a Subject. The Subject can emit callbacks that get +// serviced by the Observers. + +// The trickiest part of this is the shutdown code. +// To simplify shutdown, the Observer is a reference-counted object divorced +// from the handler that is called. To avoid misuse, the ObserverScope object +// is provided to ensure that the Shutdown() method is called when it goes out +// of scope. + +// The Observer<> class doubles as the subject class. +// To avoid misuse, assertions are added if a subject tries to observe, or if +// an observer tries to be watched. + +/* + Usage example: + + Say we want to invoke a handler with the signature: + + void MyHandler(int i, bool b); + + The corresponding delegate type is: + + typedef Delegate2<void, int, bool> Handler; + + Note: The return value will be ignored for the Observer pattern. + + For this example there are two classes, one that emits events and another + that listens for events: +*/ + +/* + Event emitter example: + + class MyEmitter + { + ObserverScope<Handler> TheSubject; + + public: + void ClearAllListeners() + { + TheSubject.ReleaseAll(); + } + + void CallListeners(int x, bool y) + { + TheSubject->Call(x, y); + } + + Observer<Handler>* GetSubject() + { + return TheSubject; + } + }; +*/ + +/* + Event listener example: + + class MyListener + { + ObserverScope<Handler> TheObserver; + + void OnEvent(int x, bool y) + { + // Handle event here + } + + public: + MyListener() + { + TheObserver.SetHandler( + Handler::FromMember<MyListener, &MyListener::OnEvent>(this) + ); + } + + void ClearListener() + { + TheObserver.ReleaseAll(); + } + + void ListenTo(Observer<Handler>* emitter) + { + TheObserver->Observe(emitter); + } + }; +*/ + +/* + Usage example: + + MyListener listener; + MyEmitter emitter; + + // To listen to an emitter, + listener.ListenTo(emitter.GetSubject()); + + // To call the listeners, + emitter.CallListeners(22, true); +*/ + +template<class DelegateT> +class Observer : public RefCountBase< Observer<DelegateT> > +{ + friend class ObserverScope<DelegateT>; + friend class ObserverHash<DelegateT>; + +public: + typedef Observer<DelegateT> ThisType; + typedef DelegateT Handler; + +protected: + bool IsShutdown; // Flag to indicate that the object went out of scope + mutable Lock TheLock; // Lock to synchronize calls and shutdown + Array< Ptr< ThisType > > References; // List of observed or observing objects + Handler TheHandler; // Observer-only: Handler for callbacks + + Observer() : + IsShutdown(false) + { + TheHandler.Invalidate(); + } + Observer(Handler handler) : + IsShutdown(false), + TheHandler(handler) + { + } + ~Observer() + { + OVR_ASSERT(References.GetSizeI() == 0); + } + +public: + void SetHandler(Handler handler) + { + OVR_ASSERT(References.GetSizeI() == 0); + TheHandler = handler; + } + + // Release references and prevent further actions + void Shutdown() + { + Lock::Locker locker(&TheLock); + IsShutdown = true; + References.ClearAndRelease(); + } + + // Get count of references held + int GetSizeI() const + { + Lock::Locker locker(&TheLock); + return References.GetSizeI(); + } + + // Observe a subject + bool Observe(ThisType *subject) + { + OVR_ASSERT(TheHandler.IsValid()); + + if (!subject) + { + return false; + } + + Lock::Locker locker(&TheLock); + + if (IsShutdown) + { + return false; + } + + if (!subject->SubjectAddObserver(this)) + { + return false; + } + + References.PushBack(subject); + return true; + } + +protected: + // Subject function: AddObserver() + // Returns true if the observer was added + bool SubjectAddObserver(ThisType* observer) + { + OVR_ASSERT(!TheHandler.IsValid()); + + if (!observer) + { + return true; + } + + Lock::Locker locker(&TheLock); + + if (IsShutdown) + { + return false; + } + + const int count = References.GetSizeI(); + for (int i = 0; i < count; ++i) + { + if (References[i] == observer) + { + // Already watched + return true; + } + } + + References.PushBack(observer); + + return true; + } + +public: + // Subject function: Call() +#define OVR_OBSERVER_CALL_BODY(params) \ + bool callSuccess = false; \ + Lock::Locker locker(&TheLock); \ + int count = References.GetSizeI(); \ + for (int i = 0; i < count; ++i) \ + { \ + if (!References[i]->IsShutdown) \ + { \ + OVR_ASSERT(References[i]->TheHandler.IsValid()); \ + References[i]->TheHandler params; \ + callSuccess = true; \ + } \ + if (References[i]->IsShutdown) \ + { \ + References.RemoveAt(i); \ + --i; --count; \ + } \ + } \ + return callSuccess; + + // Call: Various parameter counts + // Returns true if a call was made + bool Call() + { + OVR_OBSERVER_CALL_BODY(()) + } + template<class Param1> + bool Call(Param1& p1) + { + OVR_OBSERVER_CALL_BODY((p1)) + } + template<class Param1> + bool Call(Param1* p1) + { + OVR_OBSERVER_CALL_BODY((p1)) + } + template<class Param1, class Param2> + bool Call(Param1& p1, Param2& p2) + { + OVR_OBSERVER_CALL_BODY((p1, p2)) + } + template<class Param1, class Param2> + bool Call(Param1* p1, Param2* p2) + { + OVR_OBSERVER_CALL_BODY((p1, p2)) + } + template<class Param1, class Param2, class Param3> + bool Call(Param1& p1, Param2& p2, Param3& p3) + { + OVR_OBSERVER_CALL_BODY((p1, p2, p3)) + } + template<class Param1, class Param2, class Param3> + bool Call(Param1* p1, Param2* p2, Param3* p3) + { + OVR_OBSERVER_CALL_BODY((p1, p2, p3)) + } + +#undef OVR_OBSERVER_CALL_BODY +}; + + +//----------------------------------------------------------------------------- +// ObserverScope + +// Scoped shutdown of the Observer object +template<class DelegateT> +class ObserverScope : public NewOverrideBase +{ + Ptr< Observer<DelegateT> > TheObserver; + DelegateT TheHandler; + + void Shutdown() + { + if (TheObserver) + { + TheObserver->Shutdown(); + TheObserver.Clear(); + } + } + +public: + ObserverScope() + { + TheObserver = *new Observer<DelegateT>; + } + ~ObserverScope() + { + Shutdown(); + } + + // Release all references and recreate it + void ReleaseAll() + { + Shutdown(); + TheObserver = *new Observer<DelegateT>; + if (TheHandler.IsValid()) + { + TheObserver->SetHandler(TheHandler); + } + } + + void SetHandler(DelegateT handler) + { + TheHandler = handler; + TheObserver->SetHandler(handler); + } + + Observer<DelegateT>* GetPtr() + { + return TheObserver.GetPtr(); + } + Observer<DelegateT>* operator->() + { + return TheObserver.GetPtr(); + } + const Observer<DelegateT>* operator->() const + { + return TheObserver.GetPtr(); + } + operator Observer<DelegateT>*() + { + return TheObserver.GetPtr(); + } +}; + + +//----------------------------------------------------------------------------- +// ObserverHash + +// A hash containing Observers +template<class DelegateT> +class ObserverHash : public NewOverrideBase +{ +public: + ObserverHash() {} + ~ObserverHash() {Clear();} + void Clear() + { + Lock::Locker locker(&TheLock); + typename OVR::Hash< String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor >::Iterator it = _Hash.Begin(); + for( it = _Hash.Begin(); it != _Hash.End(); ++it ) + { + Ptr<Observer<DelegateT> > o = it->Second; + o->Shutdown(); + } + } + + Ptr<Observer<DelegateT> > GetSubject(OVR::String key) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *o = _Hash.Get(key); + if (o) + return (*o); + return NULL; + } + + // Add handler to new observer with implicit creation of subject. + void AddObserverToSubject(OVR::String key, Observer<DelegateT> *observer) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); + + if (subjectPtr==NULL) + { + Ptr<Observer<DelegateT> > subject = *new Observer<DelegateT>(); + _Hash.Add(key, subject); + observer->Observe(subject); + } + else + { + observer->Observe(*subjectPtr); + } + } + + void RemoveSubject(OVR::String key) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); + if (subjectPtr!=NULL) + { + (*subjectPtr)->Shutdown(); + _Hash.Remove(key); + } + } + +protected: + OVR::Hash< OVR::String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor > _Hash; + Lock TheLock; // Lock to synchronize calls and shutdown +}; + + +} // namespace OVR + +#endif // OVR_Observer_h diff --git a/LibOVR/Src/Kernel/OVR_RefCount.cpp b/LibOVR/Src/Kernel/OVR_RefCount.cpp index c6301ed..f761811 100644 --- a/LibOVR/Src/Kernel/OVR_RefCount.cpp +++ b/LibOVR/Src/Kernel/OVR_RefCount.cpp @@ -5,16 +5,16 @@ Content : Reference counting implementation Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, diff --git a/LibOVR/Src/Kernel/OVR_RefCount.h b/LibOVR/Src/Kernel/OVR_RefCount.h index 775e24c..33c6f37 100644 --- a/LibOVR/Src/Kernel/OVR_RefCount.h +++ b/LibOVR/Src/Kernel/OVR_RefCount.h @@ -6,16 +6,16 @@ Content : Reference counting implementation headers Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -413,6 +413,7 @@ public: template<class R> OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src) { + // By design we don't check for src == pObject, as we don't expect that to be the case the large majority of the time. if (src) src->AddRef(); if (pObject) pObject->Release(); pObject = src; diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.cpp b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp new file mode 100644 index 0000000..1a6ccd9 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp @@ -0,0 +1,691 @@ +/************************************************************************************ + +Filename : OVR_SharedMemory.cpp +Content : Inter-process shared memory subsystem +Created : June 1, 2014 +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_SharedMemory.h" +#include "OVR_Atomic.h" +#include "OVR_Log.h" +#include "OVR_String.h" +#include "OVR_Array.h" + +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) +#include <Sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor +#endif // OVR_OS_WIN32 + +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) +#include <sys/mman.h> // shm_open(), mmap() +#include <errno.h> // error results for mmap +#include <sys/stat.h> // mode constants +#include <fcntl.h> // O_ constants +#include <unistd.h> // close() +#endif // OVR_OS_LINUX + +OVR_DEFINE_SINGLETON(OVR::SharedMemoryFactory); + +namespace OVR { + + + //// Fake version + +#if defined(OVR_FAKE_SHAREDMEMORY) + + class FakeMemoryBlock : public RefCountBase<FakeMemoryBlock> + { + String Name; + char* Data; + int SizeBytes; + int References; + + public: + FakeMemoryBlock(const String& name, int size) : + Name(name), + Data(NULL), + SizeBytes(size), + References(1) + { + Data = new char[SizeBytes]; + } + ~FakeMemoryBlock() + { + delete[] Data; + } + + bool IsNamed(const String& name) + { + return Name.CompareNoCase(name) == 0; + } + void* GetData() + { + return Data; + } + int GetSizeI() + { + return SizeBytes; + } + void IncrementReferences() + { + ++References; + } + bool DecrementReferences() + { + return --References <= 0; + } + }; + + class SharedMemoryInternal : public NewOverrideBase + { + public: + void* FileView; + Ptr<FakeMemoryBlock> Block; + + void Close(); + + SharedMemoryInternal(FakeMemoryBlock* block) : + Block(block) + { + FileView = Block->GetData(); + } + ~SharedMemoryInternal() + { + Close(); + } + + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); + }; + + + //// FakeMemoryManager + + class FakeMemoryManager : public NewOverrideBase, public SystemSingletonBase<FakeMemoryManager> + { + OVR_DECLARE_SINGLETON(FakeMemoryManager); + + Lock FakeLock; + Array< Ptr<FakeMemoryBlock> > FakeArray; + + public: + SharedMemoryInternal* Open(const char *name, int bytes, bool openOnly) + { + Lock::Locker locker(&FakeLock); + + const int count = FakeArray.GetSizeI(); + for (int ii = 0; ii < count; ++ii) + { + if (FakeArray[ii]->IsNamed(name)) + { + FakeArray[ii]->IncrementReferences(); + return new SharedMemoryInternal(FakeArray[ii]); + } + } + + if (openOnly) + { + return NULL; + } + + Ptr<FakeMemoryBlock> data = *new FakeMemoryBlock(name, bytes); + FakeArray.PushBack(data); + return new SharedMemoryInternal(data); + } + + void Free(FakeMemoryBlock* block) + { + Lock::Locker locker(&FakeLock); + + const int count = FakeArray.GetSizeI(); + for (int ii = 0; ii < count; ++ii) + { + if (FakeArray[ii].GetPtr() == block) + { + // If the reference count hit zero, + if (FakeArray[ii]->DecrementReferences()) + { + // Toast + FakeArray.RemoveAtUnordered(ii); + } + break; + } + } + } + }; + + FakeMemoryManager::FakeMemoryManager() + { + PushDestroyCallbacks(); + } + + FakeMemoryManager::~FakeMemoryManager() + { + OVR_ASSERT(FakeArray.GetSizeI() == 0); + } + + void FakeMemoryManager::OnSystemDestroy() + { + delete this; + } + + +} // namespace OVR + +OVR_DEFINE_SINGLETON(FakeMemoryManager); + +namespace OVR { + + +void SharedMemoryInternal::Close() +{ + FakeMemoryManager::GetInstance()->Free(Block); + Block.Clear(); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + return FakeMemoryManager::GetInstance()->Open(params.globalName, params.minSizeBytes, params.openMode == SharedMemory::OpenMode_OpenOnly); +} + +#endif + + +//// Windows version + +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) + +#pragma comment(lib, "advapi32.lib") + +// Hidden implementation class for OS-specific behavior +class SharedMemoryInternal : public NewOverrideBase +{ +public: + HANDLE FileMapping; + void* FileView; + + SharedMemoryInternal(HANDLE fileMapping, void* fileView) : + FileMapping(fileMapping), + FileView(fileView) + { + } + + ~SharedMemoryInternal() + { + // If file view is set, + if (FileView) + { + UnmapViewOfFile(FileView); + FileView = NULL; + } + + // If file mapping is set, + if (FileMapping != NULL) + { + CloseHandle(FileMapping); + FileMapping = NULL; + } + } + + static SharedMemoryInternal* DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize); + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); +}; + +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize) +{ + // Interpret the access mode as a map desired access code + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; + + // Map view of the file to this process + void* pFileView = MapViewOfFile(hFileMapping, mapDesiredAccess, 0, 0, minSize); + + // If mapping could not be created, + if (!pFileView) + { + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, GetLastError())); + OVR_UNUSED(fileName); + return NULL; + } + + // Create internal representation + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView); + + // If memory allocation fails, + if (!pimple) + { + UnmapViewOfFile(pFileView); + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); + return NULL; + } + + return pimple; +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) +{ + // Interpret the access mode as a map desired access code + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; + + // Open file mapping + HANDLE hFileMapping = OpenFileMappingA(mapDesiredAccess, TRUE, fileName); + + // If file was mapped unsuccessfully, + if (NULL == hFileMapping) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, GetLastError())); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) +{ + // Prepare a SECURITY_ATTRIBUTES object + SECURITY_ATTRIBUTES security; + ZeroMemory(&security, sizeof(security)); + security.nLength = sizeof(security); + + // Security descriptor by DACL strings: + // ACE strings grant Allow(A), Object/Contains Inheritance (OICI) of: + // + Grant All (GA) to System (SY) + // + Grant All (GA) to Built-in Administrators (BA) + // + Grant Read-Only (GR) or Read-Write (GWGR) to Interactive Users (IU) - ie. games + static const char* DACLString_ReadOnly = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)"; + static const char* DACLString_ReadWrite = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)"; + + // Select the remote process access mode + const char* remoteAccessString = + allowRemoteWrite ? DACLString_ReadWrite : DACLString_ReadOnly; + + // Attempt to convert access string to security attributes + // Note: This will allocate the security descriptor with LocalAlloc() and must be freed later + BOOL bConvertOkay = ConvertStringSecurityDescriptorToSecurityDescriptorA( + remoteAccessString, SDDL_REVISION_1, &security.lpSecurityDescriptor, NULL); + + // If conversion fails, + if (!bConvertOkay) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to convert access string, error code = %d", GetLastError())); + return NULL; + } + + // Interpret the access mode as a page protection code + int pageProtectCode = openReadOnly ? PAGE_READONLY : PAGE_READWRITE; + + // Attempt to create a file mapping + HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, // From page file + &security, // Security attributes + pageProtectCode, // Read-only? + 0, // High word for size = 0 + minSize, // Low word for size + fileName); // Name of global shared memory file + + // Free the security descriptor buffer + LocalFree(security.lpSecurityDescriptor); + + // If mapping could not be created, + if (NULL == hFileMapping) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, GetLastError())); + return NULL; + } + +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS + // If the file mapping already exists, + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: File mapping at %s already exists", fileName)); + return NULL; + } +#endif + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + SharedMemoryInternal* retval = NULL; + + // Construct the file mapping name in a Windows-specific way + OVR::String fileMappingName = params.globalName; + const char *fileName = fileMappingName.ToCStr(); + + // Is being opened read-only? + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); + + // Try up to 3 times to reduce low-probability failures: + static const int ATTEMPTS_MAX = 3; + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) + { + // If opening should be attempted first, + if (params.openMode != SharedMemory::OpenMode_CreateOnly) + { + // Attempt to open a shared memory map + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); + + // If successful, + if (retval) + { + // Done! + break; + } + } + + // If creating the shared memory is also acceptable, + if (params.openMode != SharedMemory::OpenMode_OpenOnly) + { + // Interpret create mode + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); + + // Attempt to create a shared memory map + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); + + // If successful, + if (retval) + { + // Done! + break; + } + } + } // Re-attempt create/open + + // Note: On Windows the initial contents of the region are guaranteed to be zero. + return retval; +} + +#endif // OVR_OS_WIN32 + + +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) + +// Hidden implementation class for OS-specific behavior +class SharedMemoryInternal +{ +public: + int FileMapping; + void* FileView; + int FileSize; + + SharedMemoryInternal(int fileMapping, void* fileView, int fileSize) : + FileMapping(fileMapping), + FileView(fileView), + FileSize(fileSize) + { + } + + ~SharedMemoryInternal() + { + // If file view is set, + if (FileView) + { + munmap(FileView, FileSize); + FileView = MAP_FAILED; + } + + // If file mapping is set, + if (FileMapping >= 0) + { + close(FileMapping); + FileMapping = -1; + } + } + + static SharedMemoryInternal* DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize); + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); +}; + +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize) +{ + // Calculate the required flags based on read/write mode + int prot = openReadOnly ? PROT_READ : (PROT_READ|PROT_WRITE); + + // Map the file view + void* pFileView = mmap(NULL, minSize, prot, MAP_SHARED, hFileMapping, 0); + + if (pFileView == MAP_FAILED) + { + close(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, errno)); + OVR_UNUSED(fileName); + return NULL; + } + + // Create internal representation + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView, minSize); + + // If memory allocation fails, + if (!pimple) + { + munmap(pFileView, minSize); + close(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); + return NULL; + } + + return pimple; +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) +{ + // Calculate permissions and flags based on read/write mode + int flags = openReadOnly ? O_RDONLY : O_RDWR; + int perms = openReadOnly ? S_IRUSR : (S_IRUSR | S_IWUSR); + + // Attempt to open the shared memory file + int hFileMapping = shm_open(fileName, flags, perms); + + // If file was not opened successfully, + if (hFileMapping < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, errno)); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) +{ + // Create mode + // Note: Cannot create the shared memory file read-only because then ftruncate() will fail. + int flags = O_CREAT | O_RDWR; + +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS + // Require exclusive access when creating (seems like a good idea without trying it yet..) + if (shm_unlink(fileName) < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to unlink shared memory file %s error code = %d", fileName, errno)); + } + flags |= O_EXCL; +#endif + + // Set own read/write permissions + int perms = openReadOnly ? S_IRUSR : (S_IRUSR|S_IWUSR); + + // Allow other users to read/write the shared memory file + perms |= allowRemoteWrite ? (S_IWGRP|S_IWOTH|S_IRGRP|S_IROTH) : (S_IRGRP|S_IROTH); + + // Attempt to open the shared memory file + int hFileMapping = shm_open(fileName, flags, perms); + + // If file was not opened successfully, + if (hFileMapping < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, errno)); + return NULL; + } + + int truncRes = ftruncate(hFileMapping, minSize); + + // If file was not opened successfully, + if (truncRes < 0) + { + close(hFileMapping); + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to truncate file for %s to %d error code = %d", fileName, minSize, errno)); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + SharedMemoryInternal* retval = NULL; + + // Construct the file mapping name in a Linux-specific way + OVR::String fileMappingName = "/"; + fileMappingName += params.globalName; + const char *fileName = fileMappingName.ToCStr(); + + // Is being opened read-only? + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); + + // Try up to 3 times to reduce low-probability failures: + static const int ATTEMPTS_MAX = 3; + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) + { + // If opening should be attempted first, + if (params.openMode != SharedMemory::OpenMode_CreateOnly) + { + // Attempt to open a shared memory map + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); + + // If successful, + if (retval) + { + // Done! + break; + } + } + + // If creating the shared memory is also acceptable, + if (params.openMode != SharedMemory::OpenMode_OpenOnly) + { + // Interpret create mode + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); + + // Attempt to create a shared memory map + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); + + // If successful, + if (retval) + { + // Done! + break; + } + } + } // Re-attempt create/open + + // Note: On Windows the initial contents of the region are guaranteed to be zero. + return retval; +} + +#endif // OVR_OS_LINUX + + +//// SharedMemory + +SharedMemory::SharedMemory(int size, void* data, SharedMemoryInternal* pInternal) : + Size(size), + Data(data), + Internal(pInternal) +{ +} +// Call close when it goes out of scope +SharedMemory::~SharedMemory() +{ + Close(); + delete Internal; +} + +void SharedMemory::Close() +{ + if (Internal) + { + delete Internal; + Internal = NULL; + } +} + + +//// SharedMemoryFactory + +Ptr<SharedMemory> SharedMemoryFactory::Open(const SharedMemory::OpenParameters& params) +{ + Ptr<SharedMemory> retval; + + // If no name specified or no size requested, + if (!params.globalName || (params.minSizeBytes <= 0)) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Invalid parameters to Create()")); + return NULL; + } + + OVR_DEBUG_LOG(("[SharedMemory] Creating shared memory region: %s > %d bytes", + params.globalName, params.minSizeBytes)); + + // Attempt to create a shared memory region from the parameters + SharedMemoryInternal* pInternal = SharedMemoryInternal::CreateSharedMemory(params); + + if (pInternal) + { + // Create the wrapper object + retval = *new SharedMemory(params.minSizeBytes, pInternal->FileView, pInternal); + } + + return retval; +} + +SharedMemoryFactory::SharedMemoryFactory() +{ + OVR_DEBUG_LOG(("[SharedMemory] Creating factory")); + + PushDestroyCallbacks(); +} + +SharedMemoryFactory::~SharedMemoryFactory() +{ + OVR_DEBUG_LOG(("[SharedMemory] Destroying factory")); +} + +void SharedMemoryFactory::OnSystemDestroy() +{ + delete this; +} + + +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.h b/LibOVR/Src/Kernel/OVR_SharedMemory.h new file mode 100644 index 0000000..2cc8b04 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.h @@ -0,0 +1,240 @@ +/************************************************************************************ + +PublicHeader: OVR +Filename : OVR_SharedMemory.h +Content : Inter-process shared memory subsystem +Created : June 1, 2014 +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. + +************************************************************************************/ + +#ifndef OVR_SharedMemory_h +#define OVR_SharedMemory_h + +#include "OVR_Types.h" +#include "OVR_RefCount.h" +#include "OVR_Allocator.h" +#include "OVR_System.h" + +#ifdef OVR_SINGLE_PROCESS /* Everything running in one process usually for debugging */ +#define OVR_FAKE_SHAREDMEMORY /* Single-process version to avoid admin privs */ +#endif + +namespace OVR { + +class SharedMemoryInternal; // Opaque + + +// SharedMemory +// Note: Safe when used between 32-bit and 64-bit processes +class SharedMemory : public RefCountBase<SharedMemory> +{ + friend class SharedMemoryFactory; + + OVR_NON_COPYABLE(SharedMemory); + +public: + // Only constructed by the SharedMemory Factory + SharedMemory(int size, void* data, SharedMemoryInternal* pInternal); + // Call close when it goes out of scope + ~SharedMemory(); + + // Modes for opening a new shared memory region + enum OpenMode + { + // Note: On Windows, Create* requires Administrator priviledges or running as a Service. + OpenMode_CreateOnly, // Must not already exist + OpenMode_OpenOnly, // Must already exist + OpenMode_CreateOrOpen // May exist or not + }; + + // Local access restrictions + enum AccessMode + { + AccessMode_ReadOnly, // Acquire read-only access + AccessMode_ReadWrite, // Acquire read or write access + }; + + // Remote access restrictions + enum RemoteMode + { + RemoteMode_ReadOnly, // Other processes will need to open in read-only mode + RemoteMode_ReadWrite // Other processes can open in read-write mode + }; + + // Modes for opening a new shared memory region + struct OpenParameters + { + OpenParameters() : + globalName(NULL), + minSizeBytes(0), + openMode(SharedMemory::OpenMode_CreateOrOpen), + remoteMode(SharedMemory::RemoteMode_ReadWrite), + accessMode(SharedMemory::AccessMode_ReadWrite) + { + } + + // Creation parameters + const char* globalName; // Name of the shared memory region + int minSizeBytes; // Minimum number of bytes to request + SharedMemory::OpenMode openMode; // Creating the file or opening the file? + SharedMemory::RemoteMode remoteMode; // When creating, what access should other processes get? + SharedMemory::AccessMode accessMode; // When opening/creating, what access should this process get? + }; + +public: + // Returns the size of the shared memory region + int GetSizeI() const + { + return Size; + } + + // Returns the process-local pointer to the shared memory region + // Note: This may be different on different processes + void* GetData() const + { + return Data; + } + +protected: + int Size; // How many shared bytes are shared at the pointer address? + void* Data; // Pointer to the shared memory region. + + // Hidden implementation class for OS-specific behavior + SharedMemoryInternal* Internal; + + // Close and cleanup the shared memory region + // Note: This is called on destruction + void Close(); +}; + + +// SharedMemoryFactory +class SharedMemoryFactory : public NewOverrideBase, public SystemSingletonBase<SharedMemoryFactory> +{ + OVR_DECLARE_SINGLETON(SharedMemoryFactory); + +public: + // Construct a SharedMemory object. + // Note: The new object is reference-counted so it should be stored with Ptr<>. Initial reference count is 1. + Ptr<SharedMemory> Open(const SharedMemory::OpenParameters&); +}; + + +// A shared object +// Its constructor will be called when creating a writer +// Its destructor will not be called +template<class SharedType> +class ISharedObject : public NewOverrideBase +{ +public: + static const int RegionSize = (int)sizeof(SharedType); + +protected: + Ptr<SharedMemory> pSharedMemory; + + bool Open(const char* name, bool readOnly) + { + // Configure open parameters based on read-only mode + SharedMemory::OpenParameters params; + + // FIXME: This is a hack. We currently need to allow clients to open this for read-write even + // though they only need read-only access. This is because in the first 0.4 release the + // LocklessUpdater class technically writes to it (increments by 0) to read from the space. + // This was quickly corrected in 0.4.1 and we are waiting for the right time to disallow write + // access when everyone upgrades to 0.4.1+. + //params.remoteMode = SharedMemory::RemoteMode_ReadOnly; + params.remoteMode = SharedMemory::RemoteMode_ReadWrite; + + params.globalName = name; + params.accessMode = readOnly ? SharedMemory::AccessMode_ReadOnly : SharedMemory::AccessMode_ReadWrite; + params.minSizeBytes = RegionSize; + params.openMode = readOnly ? SharedMemory::OpenMode_OpenOnly : SharedMemory::OpenMode_CreateOrOpen; + + // Attempt to open the shared memory file + pSharedMemory = SharedMemoryFactory::GetInstance()->Open(params); + + // If it was not able to be opened, + if (pSharedMemory && pSharedMemory->GetSizeI() >= RegionSize && pSharedMemory->GetData()) + { + // If writing, + if (!readOnly) + { + // Construct the object also + Construct<SharedType>(pSharedMemory->GetData()); + } + + return true; + } + + return false; + } + + SharedType* Get() const + { + if (!pSharedMemory) + { + return NULL; + } + + void* data = pSharedMemory->GetData(); + if (!data) + { + return NULL; + } + + return reinterpret_cast<SharedType*>(data); + } +}; + +// Writer specialized shared object: Ctor will be called on Open() +template<class SharedType> +class SharedObjectWriter : public ISharedObject<SharedType> +{ +public: + OVR_FORCE_INLINE bool Open(const char* name) + { + return ISharedObject<SharedType>::Open(name, false); + } + OVR_FORCE_INLINE SharedType* Get() + { + return ISharedObject<SharedType>::Get(); + } +}; + +// Reader specialized shared object: Ctor will not be called +template<class SharedType> +class SharedObjectReader : public ISharedObject<SharedType> +{ +public: + OVR_FORCE_INLINE bool Open(const char* name) + { + return ISharedObject<SharedType>::Open(name, true); + } + OVR_FORCE_INLINE const SharedType* Get() const + { + return ISharedObject<SharedType>::Get(); + } +}; + + +} // namespace OVR + +#endif // OVR_SharedMemory_h diff --git a/LibOVR/Src/Kernel/OVR_Std.cpp b/LibOVR/Src/Kernel/OVR_Std.cpp index 6b5be18..fc5ad04 100644 --- a/LibOVR/Src/Kernel/OVR_Std.cpp +++ b/LibOVR/Src/Kernel/OVR_Std.cpp @@ -5,16 +5,16 @@ Content : Standard C function implementation Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -34,10 +34,58 @@ namespace OVR { // Source for functions not available on all platforms is included here. +size_t OVR_CDECL OVR_strlcpy(char* dest, const char* src, size_t destsize) +{ + const char* s = src; + size_t n = destsize; + + if(n && --n) + { + do{ + if((*dest++ = *s++) == 0) + break; + } while(--n); + } + + if(!n) + { + if(destsize) + *dest = 0; + while(*s++) + { } + } + + return (size_t)((s - src) - 1); +} + + +size_t OVR_CDECL OVR_strlcat(char* dest, const char* src, size_t destsize) +{ + const size_t d = destsize ? OVR_strlen(dest) : 0; + const size_t s = OVR_strlen(src); + const size_t t = s + d; + + OVR_ASSERT((destsize == 0) || (d < destsize)); + + if(t < destsize) + memcpy(dest + d, src, (s + 1) * sizeof(*src)); + else + { + if(destsize) + { + memcpy(dest + d, src, ((destsize - d) - 1) * sizeof(*src)); + dest[destsize - 1] = 0; + } + } + + return t; +} + + // Case insensitive compare implemented in platform-specific way. int OVR_CDECL OVR_stricmp(const char* a, const char* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_stricmp(a, b); #else @@ -49,50 +97,50 @@ int OVR_CDECL OVR_stricmp(const char* a, const char* b) #endif } -int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count) +int OVR_CDECL OVR_strnicmp(const char* a, const char* b, size_t count) { -#if defined(OVR_OS_WIN32) -#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) - return ::_strnicmp(a, b, count); -#else - return ::strnicmp(a, b, count); -#endif +#if defined(OVR_OS_MS) + #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) + return ::_strnicmp(a, b, count); + #else + return ::strnicmp(a, b, count); + #endif #else return strncasecmp(a, b, count); #endif } -wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src) +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src) { #if defined(OVR_MSVC_SAFESTRING) wcscpy_s(dest, destsize, src); return dest; -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_MS) OVR_UNUSED(destsize); wcscpy(dest, src); return dest; #else - UPInt l = OVR_wcslen(src) + 1; // incl term null + size_t l = OVR_wcslen(src) + 1; // incl term null l = (l < destsize) ? l : destsize; memcpy(dest, src, l * sizeof(wchar_t)); return dest; #endif } -wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count) +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count) { #if defined(OVR_MSVC_SAFESTRING) wcsncpy_s(dest, destsize, src, count); return dest; #else - UPInt srclen = OVR_wcslen(src); - UPInt l = Alg::Min(srclen, count); + size_t srclen = OVR_wcslen(src); + size_t l = Alg::Min(srclen, count); l = (l < destsize) ? l : destsize; memcpy(dest, src, l * sizeof(wchar_t)); if (count > srclen) { - UPInt remLen = Alg::Min(destsize - l, (count - srclen)); + size_t remLen = Alg::Min(destsize - l, (count - srclen)); memset(&dest[l], 0, sizeof(wchar_t)*remLen); } else if (l < destsize) @@ -102,30 +150,30 @@ wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src } -wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src) +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src) { #if defined(OVR_MSVC_SAFESTRING) wcscat_s(dest, destsize, src); return dest; -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_MS) OVR_UNUSED(destsize); wcscat(dest, src); return dest; #else - UPInt dstlen = OVR_wcslen(dest); // do not incl term null - UPInt srclen = OVR_wcslen(src) + 1; // incl term null - UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; + size_t dstlen = OVR_wcslen(dest); // do not incl term null + size_t srclen = OVR_wcslen(src) + 1; // incl term null + size_t copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; memcpy(dest + dstlen, src, copylen * sizeof(wchar_t)); return dest; #endif } -UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) +size_t OVR_CDECL OVR_wcslen(const wchar_t* str) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) return wcslen(str); #else - UPInt i = 0; + size_t i = 0; while(str[i] != '\0') ++i; return i; @@ -134,7 +182,7 @@ UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_MS) || defined(OVR_OS_LINUX) return wcscmp(a, b); #else // not supported, use custom implementation @@ -161,12 +209,12 @@ int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) -#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) - return ::_wcsicmp(a, b); -#else - return ::wcsicmp(a, b); -#endif +#if defined(OVR_OS_MS) + #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) + return ::_wcsicmp(a, b); + #else + return ::wcsicmp(a, b); + #endif #elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE) // not supported, use custom implementation const wchar_t *pa = a, *pb = b; @@ -193,16 +241,19 @@ int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) } // This function is not inline because of dependency on <locale.h> -double OVR_CDECL OVR_strtod(const char* string, char** tailptr) +double OVR_CDECL OVR_strtod(const char* str, char** tailptr) { -#if !defined(OVR_OS_ANDROID) +#if !defined(OVR_OS_ANDROID) // The Android C library doesn't have localeconv. const char s = *localeconv()->decimal_point; - if (s != '.') + if (s != '.') // If the C library is using a locale that is not using '.' as a decimal point, we convert the input str's '.' chars to the char that the C library expects (e.g. ',' or ' '). { char buffer[347 + 1]; - OVR_strcpy(buffer, sizeof(buffer), string); + OVR_strcpy(buffer, sizeof(buffer), str); + + // Ensure null-termination of string + buffer[sizeof(buffer)-1] = '\0'; for (char* c = buffer; *c != '\0'; ++c) { @@ -213,11 +264,21 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) } } - return strtod(buffer, tailptr); + char *nextPtr = NULL; + double retval = strtod(buffer, &nextPtr); + + // If a tail pointer is requested, + if (tailptr) + { + // Return a tail pointer that points to the same offset as nextPtr, in the orig string + *tailptr = !nextPtr ? NULL : (char*)str + (int)(nextPtr - buffer); + } + + return retval; } #endif - return strtod(string, tailptr); + return strtod(str, tailptr); } @@ -254,7 +315,7 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) // if (isNull(i)) Offsets[i] = 0; // else // if (isFull(i)) Offsets[i] = 1; -// else Offsets[i] = UInt16(offsetCount++ * 16 + 256); +// else Offsets[i] = uint16_t(offsetCount++ * 16 + 256); // } // for(i = 0; i < 16; ++i) // { @@ -280,7 +341,7 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) //private: // bool isNull(unsigned n) const // { -// const UInt16* p = Bits[n]; +// const uint16_t* p = Bits[n]; // for(unsigned i = 0; i < 16; ++i) // if (p[i] != 0) return false; // return true; @@ -288,18 +349,18 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) // // bool isFull(unsigned n) const // { -// const UInt16* p = Bits[n]; +// const uint16_t* p = Bits[n]; // for(unsigned i = 0; i < 16; ++i) // if (p[i] != 0xFFFF) return false; // return true; // } // -// UInt16 Offsets[256]; -// UInt16 Bits[256][16]; +// uint16_t Offsets[256]; +// uint16_t Bits[256][16]; //}; -const UInt16 UnicodeAlnumBits[] = { +const uint16_t UnicodeAlnumBits[] = { 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -354,7 +415,7 @@ const UInt16 UnicodeAlnumBits[] = { 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; -const UInt16 UnicodeAlphaBits[] = { +const uint16_t UnicodeAlphaBits[] = { 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -409,7 +470,7 @@ const UInt16 UnicodeAlphaBits[] = { 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; -const UInt16 UnicodeDigitBits[] = { +const uint16_t UnicodeDigitBits[] = { 256, 0, 0, 0, 0, 0, 272, 0, 0, 288, 304, 320, 336, 352, 368, 384, 400, 0, 0, 416, 0, 0, 0, 432, 448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -441,7 +502,7 @@ const UInt16 UnicodeDigitBits[] = { 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const UInt16 UnicodeSpaceBits[] = { +const uint16_t UnicodeSpaceBits[] = { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -463,7 +524,7 @@ const UInt16 UnicodeSpaceBits[] = { 4095, 0,33536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const UInt16 UnicodeXDigitBits[] = { +const uint16_t UnicodeXDigitBits[] = { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -484,7 +545,7 @@ const UInt16 UnicodeXDigitBits[] = { 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Uncomment if necessary -//const UInt16 UnicodeCntrlBits[] = { +//const uint16_t UnicodeCntrlBits[] = { // 256, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, // 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -508,7 +569,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32768, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3584}; // -//const UInt16 UnicodeGraphBits[] = { +//const uint16_t UnicodeGraphBits[] = { // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -564,7 +625,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191, //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; // -//const UInt16 UnicodePrintBits[] = { +//const uint16_t UnicodePrintBits[] = { // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -620,7 +681,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959, //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; // -//const UInt16 UnicodePunctBits[] = { +//const uint16_t UnicodePunctBits[] = { // 256, 0, 0, 272, 0, 288, 304, 320, 0, 336, 0, 0, 0, 352, 368, 384, // 400, 0, 0, 416, 0, 0, 432, 448, 464, 0, 0, 0, 0, 0, 0, 0, // 480, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -658,7 +719,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339, 0, 0, 0, 0, 0, 0, 0, 0, 0, //63470,35840, 1,47104, 0,10240, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // -//const UInt16 UnicodeLowerBits[] = { +//const uint16_t UnicodeLowerBits[] = { // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, // 384, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -688,7 +749,7 @@ const UInt16 UnicodeXDigitBits[] = { // 127, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // -//const UInt16 UnicodeUpperBits[] = { +//const uint16_t UnicodeUpperBits[] = { // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, // 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -734,7 +795,7 @@ const UInt16 UnicodeXDigitBits[] = { // they match AS3. -static const UInt16 UnicodeToUpperBits[] = { +static const uint16_t UnicodeToUpperBits[] = { 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 0, 384, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -763,7 +824,7 @@ static const UInt16 UnicodeToUpperBits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535, 1023, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static const UInt16 UnicodeToLowerBits[] = { +static const uint16_t UnicodeToLowerBits[] = { 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 0, 400, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -795,10 +856,10 @@ static const UInt16 UnicodeToLowerBits[] = { struct GUnicodePairType { - UInt16 Key, Value; + uint16_t Key, Value; }; -static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key) +static inline bool CmpUnicodeKey(const GUnicodePairType& a, uint16_t key) { return a.Key < key; } @@ -1002,11 +1063,11 @@ int OVR_CDECL OVR_towupper(wchar_t charCode) { // To protect from memory overrun in case the character is not found // we use one extra fake element in the table {65536, 0}. - UPInt idx = Alg::LowerBoundSliced( + size_t idx = Alg::LowerBoundSliced( UnicodeToUpperTable, 0, sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1, - (UInt16)charCode, + (uint16_t)charCode, CmpUnicodeKey); return UnicodeToUpperTable[idx].Value; } @@ -1020,11 +1081,11 @@ int OVR_CDECL OVR_towlower(wchar_t charCode) { // To protect from memory overrun in case the character is not found // we use one extra fake element in the table {65536, 0}. - UPInt idx = Alg::LowerBoundSliced( + size_t idx = Alg::LowerBoundSliced( UnicodeToLowerTable, 0, sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1, - (UInt16)charCode, + (uint16_t)charCode, CmpUnicodeKey); return UnicodeToLowerTable[idx].Value; } diff --git a/LibOVR/Src/Kernel/OVR_Std.h b/LibOVR/Src/Kernel/OVR_Std.h index c11f853..6a14231 100644 --- a/LibOVR/Src/Kernel/OVR_Std.h +++ b/LibOVR/Src/Kernel/OVR_Std.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Std.h Content : Standard C function interface Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -35,7 +35,7 @@ limitations under the License. #include <stdlib.h> #include <ctype.h> -#if !defined(OVR_OS_WINCE) && defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) #define OVR_MSVC_SAFESTRING #include <errno.h> #endif @@ -46,8 +46,10 @@ limitations under the License. namespace OVR { -#if defined(OVR_OS_WIN32) -inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix) +// Has the same behavior as itoa aside from also having a dest size argument. +// Return value: Pointer to the resulting null-terminated string, same as parameter str. +#if defined(OVR_OS_MS) +inline char* OVR_CDECL OVR_itoa(int val, char *dest, size_t destsize, int radix) { #if defined(OVR_MSVC_SAFESTRING) _itoa_s(val, dest, destsize, radix); @@ -57,8 +59,8 @@ inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix) return itoa(val, dest, radix); #endif } -#else // OVR_OS_WIN32 -inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) +#else // OVR_OS_MS +inline char* OVR_itoa(int val, char* dest, size_t len, int radix) { if (val == 0) { @@ -67,12 +69,15 @@ inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) dest[0] = '0'; dest[1] = '\0'; } + else if(len > 0) + dest[0] = '\0'; return dest; } + // FIXME: Fix the following code to avoid memory write overruns when len is in sufficient. int cur = val; - unsigned int i = 0; - unsigned int sign = 0; + size_t i = 0; + size_t sign = 0; if (val < 0) { @@ -124,7 +129,7 @@ inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) dest[i++] = '-'; } - for (unsigned int j = 0; j < i / 2; ++j) + for (size_t j = 0; j < i / 2; ++j) { char tmp = dest[j]; dest[j] = dest[i - 1 - j]; @@ -140,39 +145,78 @@ inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) // String functions -inline UPInt OVR_CDECL OVR_strlen(const char* str) +inline size_t OVR_CDECL OVR_strlen(const char* str) { return strlen(str); } -inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src) +inline char* OVR_CDECL OVR_strcpy(char* dest, size_t destsize, const char* src) { #if defined(OVR_MSVC_SAFESTRING) strcpy_s(dest, destsize, src); return dest; #else + // FIXME: This should be a safer implementation OVR_UNUSED(destsize); return strcpy(dest, src); #endif } -inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count) + +// Acts the same as the strlcpy function. +// Copies src to dest, 0-terminating even if it involves truncating the write. +// Returns the required strlen of dest (which is one less than the required size of dest). +// strlcpy is a safer alternative to strcpy and strncpy and provides size information. +// However, it still may result in an incomplete copy. +// +// Example usage: +// char buffer[256]; +// if(OVR_strlcpy(buffer, "hello world", sizeof(buffer)) < sizeof(buffer)) +// { there was enough space } +// else +// { need a larger buffer } +// +size_t OVR_CDECL OVR_strlcpy(char* dest, const char* src, size_t destsize); + +// Acts the same as the strlcat function. +// Appends src to dest, 0-terminating even if it involves an incomplete write. +// Doesn't 0-terminate in the case that destsize is 0. +// Returns the required strlen of dest (which is one less than the required size of dest). +// The terminating 0 char of dest is overwritten by the first +// character of src, and a new 0 char is appended to dest. The required capacity +// of the destination is (strlen(src) + strlen(dest) + 1). +// strlcat is a safer alternative to strcat and provides size information. +// However, it still may result in an incomplete copy. +// +// Example usage: +// char buffer[256] = "hello "; +// if(OVR_strlcat(buffer, "world", sizeof(buffer)) < sizeof(buffer)) +// { there was enough space } +// else +// { need a larger buffer } +// +size_t OVR_CDECL OVR_strlcat(char* dest, const char* src, size_t destsize); + + +inline char* OVR_CDECL OVR_strncpy(char* dest, size_t destsize, const char* src, size_t count) { #if defined(OVR_MSVC_SAFESTRING) strncpy_s(dest, destsize, src, count); return dest; #else + // FIXME: This should be a safer implementation OVR_UNUSED(destsize); return strncpy(dest, src, count); #endif } -inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src) +inline char * OVR_CDECL OVR_strcat(char* dest, size_t destsize, const char* src) { #if defined(OVR_MSVC_SAFESTRING) strcat_s(dest, destsize, src); return dest; #else + // FIXME: This should be a safer implementation OVR_UNUSED(destsize); return strcat(dest, src); #endif @@ -195,16 +239,16 @@ inline char* OVR_CDECL OVR_strchr(char* str, char c) inline const char* OVR_strrchr(const char* str, char c) { - UPInt len = OVR_strlen(str); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(str); + for (size_t i=len; i>0; i--) if (str[i]==c) return str+i; return 0; } -inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) +inline const uint8_t* OVR_CDECL OVR_memrchr(const uint8_t* str, size_t size, uint8_t c) { - for (SPInt i = (SPInt)size - 1; i >= 0; i--) + for (intptr_t i = (intptr_t)size - 1; i >= 0; i--) { if (str[i] == c) return str + i; @@ -214,8 +258,8 @@ inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) inline char* OVR_CDECL OVR_strrchr(char* str, char c) { - UPInt len = OVR_strlen(str); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(str); + for (size_t i=len; i>0; i--) if (str[i]==c) return str+i; return 0; @@ -234,23 +278,23 @@ inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix) return strtoul(string, tailptr, radix); } -inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size) +inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, size_t size) { return strncmp(ws1, ws2, size); } -inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) +inline uint64_t OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) { -#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) +#if defined(OVR_CC_MSVC) return _strtoui64(nptr, endptr, base); #else return strtoull(nptr, endptr, base); #endif } -inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) +inline int64_t OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) { -#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) +#if defined(OVR_CC_MSVC) return _strtoi64(nptr, endptr, base); #else return strtoll(nptr, endptr, base); @@ -258,30 +302,34 @@ inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) } -inline SInt64 OVR_CDECL OVR_atoq(const char* string) +inline int64_t OVR_CDECL OVR_atoq(const char* string) { -#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) +#if defined(OVR_CC_MSVC) return _atoi64(string); #else return atoll(string); #endif } -inline UInt64 OVR_CDECL OVR_atouq(const char* string) +inline uint64_t OVR_CDECL OVR_atouq(const char* string) { return OVR_strtouq(string, NULL, 10); } -// Implemented in GStd.cpp in platform-specific manner. +// Implemented in OVR_Std.cpp in platform-specific manner. int OVR_CDECL OVR_stricmp(const char* dest, const char* src); -int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count); +int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, size_t count); + -inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...) +// This is like sprintf but with a destination buffer size argument. However, the behavior is different +// from vsnprintf in that the return value semantics are like sprintf (which returns -1 on capacity overflow) and +// not like snprintf (which returns intended strlen on capacity overflow). +inline size_t OVR_CDECL OVR_sprintf(char *dest, size_t destsize, const char* format, ...) { va_list argList; va_start(argList,format); - UPInt ret; + size_t ret; #if defined(OVR_CC_MSVC) #if defined(OVR_MSVC_SAFESTRING) ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); @@ -301,9 +349,16 @@ inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* forma return ret; } -inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList) + +// This is like vsprintf but with a destination buffer size argument. However, the behavior is different +// from vsnprintf in that the return value semantics are like vsprintf (which returns -1 on capacity overflow) and +// not like vsnprintf (which returns intended strlen on capacity overflow). +// Return value: +// On success, the total number of characters written is returned. +// On failure, a negative number is returned. +inline size_t OVR_CDECL OVR_vsprintf(char *dest, size_t destsize, const char * format, va_list argList) { - UPInt ret; + size_t ret; #if defined(OVR_CC_MSVC) #if defined(OVR_MSVC_SAFESTRING) dest[0] = '\0'; @@ -314,50 +369,119 @@ inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * for ret = destsize - 1; } else - ret = (UPInt)rv; + ret = (size_t)rv; #else OVR_UNUSED(destsize); int rv = _vsnprintf(dest, destsize - 1, format, argList); OVR_ASSERT(rv != -1); - ret = (UPInt)rv; + ret = (size_t)rv; dest[destsize-1] = 0; #endif #else + // FIXME: This should be a safer implementation OVR_UNUSED(destsize); - ret = (UPInt)vsprintf(dest, format, argList); + ret = (size_t)vsprintf(dest, format, argList); OVR_ASSERT(ret < destsize); #endif return ret; } -// Returns the number of characters in the formatted string. -inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList) +// Same behavior as ISO C99 vsnprintf. +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid. +// destsize specifies the capacity of the input buffer. +// +// Example usage: +// void Log(char *dest, size_t destsize, const char * format, ...) +// { +// char buffer[1024]; +// va_list argList; +// va_start(argList,format); +// int result = OVR_vsnprintf(dest, destsize, format, argList); +// assert(result < destsize); // Else we'd have to retry with a dynamically allocated buffer (of size=result+1) and new argList copy. +// va_end(argList); +// } + +inline int OVR_CDECL OVR_vsnprintf(char *dest, size_t destsize, const char * format, va_list argList) +{ + int ret; +#if defined(OVR_CC_MSVC) + OVR_DISABLE_MSVC_WARNING(4996) // 'vsnprintf': This function or variable may be unsafe. + ret = vsnprintf(dest, destsize, format, argList); // Microsoft vsnprintf is non-conforming; it returns -1 if destsize is insufficient. + if (ret < 0) // If there was a format error or if destsize was insufficient... + { + ret = _vscprintf(format, argList); // Get the expected dest strlen. If the return value is still -1 then there was a format error. + + if (destsize) // If we can 0-terminate the output... + { + if (ret < 0) + dest[0] = 0; + else + dest[destsize-1] = 0; + } + } + // Else the string was written OK and ret is its strlen. + OVR_RESTORE_MSVC_WARNING() +#else + ret = vsnprintf(dest, destsize, format, argList); +#endif + return ret; +} + + +// Same behavior as ISO C99 snprintf. +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid. +// destsize specifies the capacity of the input buffer. +// +// Example usage: +// char buffer[16]; +// int result = OVR_snprintf(buffer, sizeof(buffer), "%d", 37); +// if (result >= sizeof(buffer)) // If there was insufficient capacity... +// { +// char* p = new char[result + 1]; // Or char* p = (char*)OVR_ALLOC(result + 1); +// OVR_snprintf(p, (size_t)result, "%d", 37); +// delete[] p; +// } +// +inline int OVR_CDECL OVR_snprintf(char *dest, size_t destsize, const char * format, ...) +{ + va_list argList; + va_start(argList,format); + int ret = OVR_vsnprintf(dest, destsize, format, argList); + va_end(argList); + return ret; +} + + +// Returns the strlen of the resulting formatted string, or a negative value if the format is invalid. +// Note: If you are planning on printing a string then it's more efficient to just use OVR_vsnprintf and +// look at the return value and handle the uncommon case that there wasn't enough space. +inline int OVR_CDECL OVR_vscprintf(const char * format, va_list argList) { - UPInt ret; + int ret; #if defined(OVR_CC_MSVC) - ret = (UPInt) _vscprintf(format, argList); + ret = _vscprintf(format, argList); #else - ret = (UPInt) vsnprintf(NULL, 0, format, argList); + ret = vsnprintf(NULL, 0, format, argList); #endif return ret; } -wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src); -wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count); -wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src); -UPInt OVR_CDECL OVR_wcslen(const wchar_t* str); +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src); +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count); +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src); +size_t OVR_CDECL OVR_wcslen(const wchar_t* str); int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b); int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b); inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) -#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) - return ::_wcsicoll(a, b); -#else - return ::wcsicoll(a, b); -#endif +#if defined(OVR_OS_MS) + #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) + return ::_wcsicoll(a, b); + #else + return ::wcsicoll(a, b); + #endif #else // not supported, use regular wcsicmp return OVR_wcsicmp(a, b); @@ -366,7 +490,7 @@ inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_MS) || defined(OVR_OS_LINUX) return wcscoll(a, b); #else // not supported, use regular wcscmp @@ -376,7 +500,7 @@ inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) #ifndef OVR_NO_WCTYPE -inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) +inline int OVR_CDECL UnicodeCharIs(const uint16_t* table, wchar_t charCode) { unsigned offset = table[charCode >> 8]; if (offset == 0) return 0; @@ -384,19 +508,19 @@ inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0; } -extern const UInt16 UnicodeAlnumBits[]; -extern const UInt16 UnicodeAlphaBits[]; -extern const UInt16 UnicodeDigitBits[]; -extern const UInt16 UnicodeSpaceBits[]; -extern const UInt16 UnicodeXDigitBits[]; +extern const uint16_t UnicodeAlnumBits[]; +extern const uint16_t UnicodeAlphaBits[]; +extern const uint16_t UnicodeDigitBits[]; +extern const uint16_t UnicodeSpaceBits[]; +extern const uint16_t UnicodeXDigitBits[]; // Uncomment if necessary -//extern const UInt16 UnicodeCntrlBits[]; -//extern const UInt16 UnicodeGraphBits[]; -//extern const UInt16 UnicodeLowerBits[]; -//extern const UInt16 UnicodePrintBits[]; -//extern const UInt16 UnicodePunctBits[]; -//extern const UInt16 UnicodeUpperBits[]; +//extern const uint16_t UnicodeCntrlBits[]; +//extern const uint16_t UnicodeGraphBits[]; +//extern const uint16_t UnicodeLowerBits[]; +//extern const uint16_t UnicodePrintBits[]; +//extern const uint16_t UnicodePunctBits[]; +//extern const uint16_t UnicodeUpperBits[]; inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits, charCode); } inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits, charCode); } @@ -473,10 +597,10 @@ inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr) OVR_UNUSED(tailptr); char buffer[64]; char* tp = NULL; - UPInt max = OVR_wcslen(string); + size_t max = OVR_wcslen(string); if (max > 63) max = 63; unsigned char c = 0; - for (UPInt i=0; i < max; i++) + for (size_t i=0; i < max; i++) { c = (unsigned char)string[i]; buffer[i] = ((c) < 128 ? (char)c : '!'); @@ -494,10 +618,10 @@ inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int r OVR_UNUSED(tailptr); char buffer[64]; char* tp = NULL; - UPInt max = OVR_wcslen(string); + size_t max = OVR_wcslen(string); if (max > 63) max = 63; unsigned char c = 0; - for (UPInt i=0; i < max; i++) + for (size_t i=0; i < max; i++) { c = (unsigned char)string[i]; buffer[i] = ((c) < 128 ? (char)c : '!'); diff --git a/LibOVR/Src/Kernel/OVR_String.cpp b/LibOVR/Src/Kernel/OVR_String.cpp index 75b7c0e..a539992 100644 --- a/LibOVR/Src/Kernel/OVR_String.cpp +++ b/LibOVR/Src/Kernel/OVR_String.cpp @@ -6,16 +6,16 @@ Content : String UTF8 string implementation with copy-on-write semantics Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -36,7 +36,7 @@ limitations under the License. namespace OVR { -#define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift) +#define String_LengthIsSize (size_t(1) << String::Flag_LengthIsSizeShift) String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} }; @@ -50,16 +50,16 @@ String::String() String::String(const char* pdata) { // Obtain length in bytes; it doesn't matter if _data is UTF8. - UPInt size = pdata ? OVR_strlen(pdata) : 0; + size_t size = pdata ? OVR_strlen(pdata) : 0; pData = AllocDataCopy1(size, 0, pdata, size); }; String::String(const char* pdata1, const char* pdata2, const char* pdata3) { // Obtain length in bytes; it doesn't matter if _data is UTF8. - UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; - UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; - UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; + size_t size1 = pdata1 ? OVR_strlen(pdata1) : 0; + size_t size2 = pdata2 ? OVR_strlen(pdata2) : 0; + size_t size3 = pdata3 ? OVR_strlen(pdata3) : 0; DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0, pdata1, size1, pdata2, size2); @@ -67,14 +67,14 @@ String::String(const char* pdata1, const char* pdata2, const char* pdata3) pData = pdataDesc; } -String::String(const char* pdata, UPInt size) +String::String(const char* pdata, size_t size) { OVR_ASSERT((size == 0) || (pdata != 0)); pData = AllocDataCopy1(size, 0, pdata, size); }; -String::String(const InitStruct& src, UPInt size) +String::String(const InitStruct& src, size_t size) { pData = AllocData(size, 0); src.InitString(GetData()->Data, size); @@ -101,7 +101,7 @@ String::String(const wchar_t* data) } -String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) +String::DataDesc* String::AllocData(size_t size, size_t lengthIsSize) { String::DataDesc* pdesc; @@ -120,17 +120,17 @@ String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) } -String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize, - const char* pdata, UPInt copySize) +String::DataDesc* String::AllocDataCopy1(size_t size, size_t lengthIsSize, + const char* pdata, size_t copySize) { String::DataDesc* pdesc = AllocData(size, lengthIsSize); memcpy(pdesc->Data, pdata, copySize); return pdesc; } -String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, - const char* pdata1, UPInt copySize1, - const char* pdata2, UPInt copySize2) +String::DataDesc* String::AllocDataCopy2(size_t size, size_t lengthIsSize, + const char* pdata1, size_t copySize1, + const char* pdata2, size_t copySize2) { String::DataDesc* pdesc = AllocData(size, lengthIsSize); memcpy(pdesc->Data, pdata1, copySize1); @@ -139,16 +139,16 @@ String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, } -UPInt String::GetLength() const +size_t String::GetLength() const { // Optimize length accesses for non-UTF8 character strings. DataDesc* pdata = GetData(); - UPInt length, size = pdata->GetSize(); + size_t length, size = pdata->GetSize(); if (pdata->LengthIsSize()) return size; - length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size); + length = (size_t)UTF8Util::GetLength(pdata->Data, (size_t)size); if (length == size) pdata->Size |= String_LengthIsSize; @@ -157,15 +157,15 @@ UPInt String::GetLength() const } -//static UInt32 String_CharSearch(const char* buf, ) +//static uint32_t String_CharSearch(const char* buf, ) -UInt32 String::GetCharAt(UPInt index) const +uint32_t String::GetCharAt(size_t index) const { - SPInt i = (SPInt) index; + intptr_t i = (intptr_t) index; DataDesc* pdata = GetData(); const char* buf = pdata->Data; - UInt32 c; + uint32_t c; if (pdata->LengthIsSize()) { @@ -178,13 +178,13 @@ UInt32 String::GetCharAt(UPInt index) const return c; } -UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const +uint32_t String::GetFirstCharAt(size_t index, const char** offset) const { DataDesc* pdata = GetData(); - SPInt i = (SPInt) index; + intptr_t i = (intptr_t) index; const char* buf = pdata->Data; const char* end = buf + pdata->GetSize(); - UInt32 c; + uint32_t c; do { @@ -204,40 +204,40 @@ UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const return c; } -UInt32 String::GetNextChar(const char** offset) const +uint32_t String::GetNextChar(const char** offset) const { return UTF8Util::DecodeNextChar(offset); } -void String::AppendChar(UInt32 ch) +void String::AppendChar(uint32_t ch) { DataDesc* pdata = GetData(); - UPInt size = pdata->GetSize(); + size_t size = pdata->GetSize(); char buff[8]; - SPInt encodeSize = 0; + intptr_t encodeSize = 0; // Converts ch into UTF8 string and fills it into buff. UTF8Util::EncodeChar(buff, &encodeSize, ch); OVR_ASSERT(encodeSize >= 0); - SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0, - pdata->Data, size, buff, (UPInt)encodeSize)); + SetData(AllocDataCopy2(size + (size_t)encodeSize, 0, + pdata->Data, size, buff, (size_t)encodeSize)); pdata->Release(); } -void String::AppendString(const wchar_t* pstr, SPInt len) +void String::AppendString(const wchar_t* pstr, intptr_t len) { if (!pstr) return; DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); - UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len); + size_t oldSize = pdata->GetSize(); + size_t encodeSize = (size_t)UTF8Util::GetEncodeStringSize(pstr, len); - DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0, + DataDesc* pnewData = AllocDataCopy1(oldSize + (size_t)encodeSize, 0, pdata->Data, oldSize); UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len); @@ -246,22 +246,22 @@ void String::AppendString(const wchar_t* pstr, SPInt len) } -void String::AppendString(const char* putf8str, SPInt utf8StrSz) +void String::AppendString(const char* putf8str, intptr_t utf8StrSz) { if (!putf8str || !utf8StrSz) return; if (utf8StrSz == -1) - utf8StrSz = (SPInt)OVR_strlen(putf8str); + utf8StrSz = (intptr_t)OVR_strlen(putf8str); DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); + size_t oldSize = pdata->GetSize(); - SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0, - pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz)); + SetData(AllocDataCopy2(oldSize + (size_t)utf8StrSz, 0, + pdata->Data, oldSize, putf8str, (size_t)utf8StrSz)); pdata->Release(); } -void String::AssignString(const InitStruct& src, UPInt size) +void String::AssignString(const InitStruct& src, size_t size) { DataDesc* poldData = GetData(); DataDesc* pnewData = AllocData(size, 0); @@ -270,7 +270,7 @@ void String::AssignString(const InitStruct& src, UPInt size) poldData->Release(); } -void String::AssignString(const char* putf8str, UPInt size) +void String::AssignString(const char* putf8str, size_t size) { DataDesc* poldData = GetData(); SetData(AllocDataCopy1(size, 0, putf8str, size)); @@ -284,8 +284,10 @@ void String::operator = (const char* pstr) void String::operator = (const wchar_t* pwstr) { + pwstr = pwstr ? pwstr : L""; + DataDesc* poldData = GetData(); - UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0; + size_t size = (size_t)UTF8Util::GetEncodeStringSize(pwstr); DataDesc* pnewData = AllocData(size, 0); UTF8Util::EncodeString(pnewData->Data, pwstr); @@ -316,9 +318,9 @@ void String::operator += (const String& src) { DataDesc *pourData = GetData(), *psrcData = src.GetData(); - UPInt ourSize = pourData->GetSize(), + size_t ourSize = pourData->GetSize(), srcSize = psrcData->GetSize(); - UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); + size_t lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); SetData(AllocDataCopy2(ourSize + srcSize, lflag, pourData->Data, ourSize, psrcData->Data, srcSize)); @@ -340,12 +342,12 @@ String String::operator + (const String& src) const return tmp1; } -void String::Remove(UPInt posAt, SPInt removeLength) +void String::Remove(size_t posAt, intptr_t removeLength) { DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); + size_t oldSize = pdata->GetSize(); // Length indicates the number of characters to remove. - UPInt length = GetLength(); + size_t length = GetLength(); // If index is past the string, nothing to remove. if (posAt >= length) @@ -355,8 +357,8 @@ void String::Remove(UPInt posAt, SPInt removeLength) removeLength = length - posAt; // Get the byte position of the UTF8 char at position posAt. - SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); - SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); + intptr_t bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); + intptr_t removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(), pdata->Data, bytePos, @@ -365,9 +367,9 @@ void String::Remove(UPInt posAt, SPInt removeLength) } -String String::Substring(UPInt start, UPInt end) const +String String::Substring(size_t start, size_t end) const { - UPInt length = GetLength(); + size_t length = GetLength(); if ((start >= length) || (start >= end)) return String(); @@ -378,9 +380,9 @@ String String::Substring(UPInt start, UPInt end) const return String(pdata->Data + start, end - start); // Get position of starting character. - SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); - SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); - return String(pdata->Data + byteStart, (UPInt)byteSize); + intptr_t byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); + intptr_t byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); + return String(pdata->Data + byteStart, (size_t)byteSize); } void String::Clear() @@ -393,11 +395,11 @@ void String::Clear() String String::ToUpper() const { - UInt32 c; + uint32_t c; const char* psource = GetData()->Data; const char* pend = psource + GetData()->GetSize(); String str; - SPInt bufferOffset = 0; + intptr_t bufferOffset = 0; char buffer[512]; while(psource < pend) @@ -405,7 +407,7 @@ String String::ToUpper() const do { c = UTF8Util::DecodeNextChar_Advance0(&psource); UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c))); - } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); // Append string a piece at a time. str.AppendString(buffer, bufferOffset); @@ -417,11 +419,11 @@ String String::ToUpper() const String String::ToLower() const { - UInt32 c; + uint32_t c; const char* psource = GetData()->Data; const char* pend = psource + GetData()->GetSize(); String str; - SPInt bufferOffset = 0; + intptr_t bufferOffset = 0; char buffer[512]; while(psource < pend) @@ -429,7 +431,7 @@ String String::ToLower() const do { c = UTF8Util::DecodeNextChar_Advance0(&psource); UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c))); - } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); // Append string a piece at a time. str.AppendString(buffer, bufferOffset); @@ -441,13 +443,13 @@ String String::ToLower() const -String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) +String& String::Insert(const char* substr, size_t posAt, intptr_t strSize) { DataDesc* poldData = GetData(); - UPInt oldSize = poldData->GetSize(); - UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize; - UPInt byteIndex = (poldData->LengthIsSize()) ? - posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); + size_t oldSize = poldData->GetSize(); + size_t insertSize = (strSize < 0) ? OVR_strlen(substr) : (size_t)strSize; + size_t byteIndex = (poldData->LengthIsSize()) ? + posAt : (size_t)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); OVR_ASSERT(byteIndex <= oldSize); @@ -461,27 +463,27 @@ String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) } /* -String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len) +String& String::Insert(const uint32_t* substr, size_t posAt, intptr_t len) { - for (SPInt i = 0; i < len; ++i) + for (intptr_t i = 0; i < len; ++i) { - UPInt charw = InsertCharAt(substr[i], posAt); + size_t charw = InsertCharAt(substr[i], posAt); posAt += charw; } return *this; } */ -UPInt String::InsertCharAt(UInt32 c, UPInt posAt) +size_t String::InsertCharAt(uint32_t c, size_t posAt) { - char buf[8]; - SPInt index = 0; + char buf[8]; + intptr_t index = 0; UTF8Util::EncodeChar(buf, &index, c); OVR_ASSERT(index >= 0); - buf[(UPInt)index] = 0; + buf[(size_t)index] = 0; Insert(buf, posAt, index); - return (UPInt)index; + return (size_t)index; } @@ -490,22 +492,22 @@ int String::CompareNoCase(const char* a, const char* b) return OVR_stricmp(a, b); } -int String::CompareNoCase(const char* a, const char* b, SPInt len) +int String::CompareNoCase(const char* a, const char* b, intptr_t len) { if (len) { - SPInt f,l; - SPInt slen = len; + intptr_t f,l; + intptr_t slen = len; const char *s = b; do { - f = (SPInt)OVR_tolower((int)(*(a++))); - l = (SPInt)OVR_tolower((int)(*(b++))); + f = (intptr_t)OVR_tolower((int)(*(a++))); + l = (intptr_t)OVR_tolower((int)(*(b++))); } while (--len && f && (f == l) && *b != 0); if (f == l && (len != 0 || *b != 0)) { - f = (SPInt)slen; - l = (SPInt)OVR_strlen(s); + f = (intptr_t)slen; + l = (intptr_t)OVR_strlen(s); return int(f - l); } @@ -518,10 +520,10 @@ int String::CompareNoCase(const char* a, const char* b, SPInt len) // ***** Implement hash static functions // Hash function -UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) +size_t String::BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed) { - const UByte* pdata = (const UByte*) pdataIn; - UPInt h = seed; + const uint8_t* pdata = (const uint8_t*) pdataIn; + size_t h = seed; while (size > 0) { size--; @@ -532,10 +534,10 @@ UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) } // Hash function, case-insensitive -UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed) +size_t String::BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed) { - const UByte* pdata = (const UByte*) pdataIn; - UPInt h = seed; + const uint8_t* pdata = (const uint8_t*) pdataIn; + size_t h = seed; while (size > 0) { size--; @@ -560,7 +562,7 @@ StringBuffer::StringBuffer() { } -StringBuffer::StringBuffer(UPInt growSize) +StringBuffer::StringBuffer(size_t growSize) : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) { SetGrowSize(growSize); @@ -572,7 +574,7 @@ StringBuffer::StringBuffer(const char* data) AppendString(data); } -StringBuffer::StringBuffer(const char* data, UPInt dataSize) +StringBuffer::StringBuffer(const char* data, size_t dataSize) : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) { AppendString(data, dataSize); @@ -601,32 +603,32 @@ StringBuffer::~StringBuffer() if (pData) OVR_FREE(pData); } -void StringBuffer::SetGrowSize(UPInt growSize) +void StringBuffer::SetGrowSize(size_t growSize) { if (growSize <= 16) GrowSize = 16; else { - UByte bits = Alg::UpperBit(UInt32(growSize-1)); - UPInt size = 1<<bits; + uint8_t bits = Alg::UpperBit(uint32_t(growSize-1)); + size_t size = (size_t)1 << bits; GrowSize = size == growSize ? growSize : size; } } -UPInt StringBuffer::GetLength() const +size_t StringBuffer::GetLength() const { - UPInt length, size = GetSize(); + size_t length, size = GetSize(); if (LengthIsSize) return size; - length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize()); + length = (size_t)UTF8Util::GetLength(pData, (size_t)GetSize()); if (length == GetSize()) LengthIsSize = true; return length; } -void StringBuffer::Reserve(UPInt _size) +void StringBuffer::Reserve(size_t _size) { if (_size >= BufferSize) // >= because of trailing zero! (!AB) { @@ -637,7 +639,7 @@ void StringBuffer::Reserve(UPInt _size) pData = (char*)OVR_REALLOC(pData, BufferSize); } } -void StringBuffer::Resize(UPInt _size) +void StringBuffer::Resize(size_t _size) { Reserve(_size); LengthIsSize = false; @@ -660,71 +662,79 @@ void StringBuffer::Clear() */ } // Appends a character -void StringBuffer::AppendChar(UInt32 ch) +void StringBuffer::AppendChar(uint32_t ch) { char buff[8]; - UPInt origSize = GetSize(); + size_t origSize = GetSize(); // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes // in the UTF8 string. - SPInt srcSize = 0; + intptr_t srcSize = 0; UTF8Util::EncodeChar(buff, &srcSize, ch); OVR_ASSERT(srcSize >= 0); - UPInt size = origSize + srcSize; + size_t size = origSize + srcSize; Resize(size); + OVR_ASSERT(pData != NULL); memcpy(pData + origSize, buff, srcSize); } // Append a string -void StringBuffer::AppendString(const wchar_t* pstr, SPInt len) +void StringBuffer::AppendString(const wchar_t* pstr, intptr_t len) { - if (!pstr) + if (!pstr || !len) return; - SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len); - UPInt origSize = GetSize(); - UPInt size = srcSize + origSize; + intptr_t srcSize = UTF8Util::GetEncodeStringSize(pstr, len); + size_t origSize = GetSize(); + size_t size = srcSize + origSize; Resize(size); + OVR_ASSERT(pData != NULL); UTF8Util::EncodeString(pData + origSize, pstr, len); } -void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz) +void StringBuffer::AppendString(const char* putf8str, intptr_t utf8StrSz) { if (!putf8str || !utf8StrSz) return; if (utf8StrSz == -1) - utf8StrSz = (SPInt)OVR_strlen(putf8str); + utf8StrSz = (intptr_t)OVR_strlen(putf8str); - UPInt origSize = GetSize(); - UPInt size = utf8StrSz + origSize; + size_t origSize = GetSize(); + size_t size = utf8StrSz + origSize; Resize(size); + OVR_ASSERT(pData != NULL); memcpy(pData + origSize, putf8str, utf8StrSz); } - +// If pstr is NULL then the StringBuffer is cleared. void StringBuffer::operator = (const char* pstr) { pstr = pstr ? pstr : ""; - UPInt size = OVR_strlen(pstr); + size_t size = OVR_strlen(pstr); Resize(size); + OVR_ASSERT((pData != NULL) || (size == 0)); memcpy(pData, pstr, size); } +// If pstr is NULL then the StringBuffer is cleared. void StringBuffer::operator = (const wchar_t* pstr) { pstr = pstr ? pstr : L""; - UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr); + size_t size = (size_t)UTF8Util::GetEncodeStringSize(pstr); Resize(size); + OVR_ASSERT((pData != NULL) || (size == 0)); UTF8Util::EncodeString(pData, pstr); } void StringBuffer::operator = (const String& src) { - Resize(src.GetSize()); - memcpy(pData, src.ToCStr(), src.GetSize()); + const size_t size = src.GetSize(); + Resize(size); + OVR_ASSERT((pData != NULL) || (size == 0)); + memcpy(pData, src.ToCStr(), size); } void StringBuffer::operator = (const StringBuffer& src) @@ -735,16 +745,17 @@ void StringBuffer::operator = (const StringBuffer& src) // Inserts substr at posAt -void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) +void StringBuffer::Insert(const char* substr, size_t posAt, intptr_t len) { - UPInt oldSize = Size; - UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len; - UPInt byteIndex = LengthIsSize ? posAt : - (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size); + size_t oldSize = Size; + size_t insertSize = (len < 0) ? OVR_strlen(substr) : (size_t)len; + size_t byteIndex = LengthIsSize ? posAt : + (size_t)UTF8Util::GetByteIndex(posAt, pData, (intptr_t)Size); OVR_ASSERT(byteIndex <= oldSize); Reserve(oldSize + insertSize); + OVR_ASSERT(pData != NULL); // pData is unilaterally written to below. memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1); memcpy (pData + byteIndex, substr, insertSize); LengthIsSize = false; @@ -753,16 +764,16 @@ void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) } // Inserts character at posAt -UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt) +size_t StringBuffer::InsertCharAt(uint32_t c, size_t posAt) { char buf[8]; - SPInt len = 0; + intptr_t len = 0; UTF8Util::EncodeChar(buf, &len, c); OVR_ASSERT(len >= 0); - buf[(UPInt)len] = 0; + buf[(size_t)len] = 0; Insert(buf, posAt, len); - return (UPInt)len; + return (size_t)len; } } // OVR diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h index 0866968..ecef940 100644 --- a/LibOVR/Src/Kernel/OVR_String.h +++ b/LibOVR/Src/Kernel/OVR_String.h @@ -1,22 +1,22 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_String.h Content : String UTF8 string implementation with copy-on-write semantics (thread-safe for assignment but not modification). Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -59,7 +59,7 @@ protected: //Flag_GetLength = 0x7FFFFFFF, // This flag is set if GetLength() == GetSize() for a string. // Avoid extra scanning is Substring and indexing logic. - Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1) + Flag_LengthIsSizeShift = (sizeof(size_t)*8 - 1) }; @@ -68,13 +68,13 @@ protected: { // Number of bytes. Will be the same as the number of chars if the characters // are ascii, may not be equal to number of chars in case string data is UTF8. - UPInt Size; - volatile SInt32 RefCount; + size_t Size; + volatile int32_t RefCount; char Data[1]; void AddRef() { - AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1); + AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, 1); } // Decrement ref count. This needs to be thread-safe, since // a different thread could have also decremented the ref count. @@ -88,13 +88,13 @@ protected: // checking against 0 needs to made an atomic operation. void Release() { - if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) + if ((AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) OVR_FREE(this); } - static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; } - UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; } - UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); } + static size_t GetLengthFlagBit() { return size_t(1) << Flag_LengthIsSizeShift; } + size_t GetSize() const { return Size & ~GetLengthFlagBit() ; } + size_t GetLengthFlag() const { return Size & GetLengthFlagBit(); } bool LengthIsSize() const { return GetLengthFlag() != 0; } }; @@ -109,11 +109,11 @@ protected: union { DataDesc* pData; - UPInt HeapTypeBits; + size_t HeapTypeBits; }; typedef union { DataDesc* pData; - UPInt HeapTypeBits; + size_t HeapTypeBits; } DataDescUnion; inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); } @@ -122,7 +122,7 @@ protected: { DataDescUnion u; u.pData = pData; - u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask); + u.HeapTypeBits = (u.HeapTypeBits & ~(size_t)HT_Mask); return u.pData; } @@ -135,12 +135,12 @@ protected: } - DataDesc* AllocData(UPInt size, UPInt lengthIsSize); - DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize, - const char* pdata, UPInt copySize); - DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize, - const char* pdata1, UPInt copySize1, - const char* pdata2, UPInt copySize2); + DataDesc* AllocData(size_t size, size_t lengthIsSize); + DataDesc* AllocDataCopy1(size_t size, size_t lengthIsSize, + const char* pdata, size_t copySize); + DataDesc* AllocDataCopy2(size_t size, size_t lengthIsSize, + const char* pdata1, size_t copySize1, + const char* pdata2, size_t copySize2); // Special constructor to avoid data initalization when used in derived class. struct NoConstructor { }; @@ -152,7 +152,7 @@ public: struct InitStruct { virtual ~InitStruct() { } - virtual void InitString(char* pbuffer, UPInt size) const = 0; + virtual void InitString(char* pbuffer, size_t size) const = 0; }; @@ -160,10 +160,10 @@ public: String(); String(const char* data); String(const char* data1, const char* pdata2, const char* pdata3 = 0); - String(const char* data, UPInt buflen); + String(const char* data, size_t buflen); String(const String& src); String(const StringBuffer& src); - String(const InitStruct& src, UPInt size); + String(const InitStruct& src, size_t size); explicit String(const wchar_t* data); // Destructor (Captain Obvious guarantees!) @@ -186,68 +186,69 @@ public: const char* ToCStr() const { return GetData()->Data; } // Returns number of bytes - UPInt GetSize() const { return GetData()->GetSize() ; } + size_t GetSize() const { return GetData()->GetSize() ; } // Tells whether or not the string is empty bool IsEmpty() const { return GetSize() == 0; } // Returns number of characters - UPInt GetLength() const; + size_t GetLength() const; + int GetLengthI() const { return (int)GetLength(); } // Returns character at the specified index - UInt32 GetCharAt(UPInt index) const; - UInt32 GetFirstCharAt(UPInt index, const char** offset) const; - UInt32 GetNextChar(const char** offset) const; + uint32_t GetCharAt(size_t index) const; + uint32_t GetFirstCharAt(size_t index, const char** offset) const; + uint32_t GetNextChar(const char** offset) const; // Appends a character - void AppendChar(UInt32 ch); + void AppendChar(uint32_t ch); // Append a string - void AppendString(const wchar_t* pstr, SPInt len = -1); - void AppendString(const char* putf8str, SPInt utf8StrSz = -1); + void AppendString(const wchar_t* pstr, intptr_t len = -1); + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); // Assigned a string with dynamic data (copied through initializer). - void AssignString(const InitStruct& src, UPInt size); + void AssignString(const InitStruct& src, size_t size); // Assigns string with known size. - void AssignString(const char* putf8str, UPInt size); + void AssignString(const char* putf8str, size_t size); // Resize the string to the new size -// void Resize(UPInt _size); +// void Resize(size_t _size); // Removes the character at posAt - void Remove(UPInt posAt, SPInt len = 1); + void Remove(size_t posAt, intptr_t len = 1); // Returns a String that's a substring of this. // -start is the index of the first UTF8 character you want to include. // -end is the index one past the last UTF8 character you want to include. - String Substring(UPInt start, UPInt end) const; + String Substring(size_t start, size_t end) const; // Case-conversion String ToUpper() const; String ToLower() const; // Inserts substr at posAt - String& Insert (const char* substr, UPInt posAt, SPInt len = -1); + String& Insert (const char* substr, size_t posAt, intptr_t len = -1); // Inserts character at posAt - UPInt InsertCharAt(UInt32 c, UPInt posAt); + size_t InsertCharAt(uint32_t c, size_t posAt); // Inserts substr at posAt, which is an index of a character (not byte). // Of size is specified, it is in bytes. -// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1); +// String& Insert(const uint32_t* substr, size_t posAt, intptr_t size = -1); // Get Byte index of the character at position = index - UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); } + size_t GetByteIndex(size_t index) const { return (size_t)UTF8Util::GetByteIndex(index, GetData()->Data); } // Utility: case-insensitive string compare. stricmp() & strnicmp() are not // ANSI or POSIX, do not seem to appear in Linux. static int OVR_STDCALL CompareNoCase(const char* a, const char* b); - static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len); + static int OVR_STDCALL CompareNoCase(const char* a, const char* b, intptr_t len); // Hash function, case-insensitive - static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381); + static size_t OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed = 5381); // Hash function, case-sensitive - static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381); + static size_t OVR_STDCALL BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed = 5381); // ***** File path parsing helper functions. @@ -343,10 +344,10 @@ public: // Accesses raw bytes const char& operator [] (int index) const { - OVR_ASSERT(index >= 0 && (UPInt)index < GetSize()); + OVR_ASSERT(index >= 0 && (size_t)index < GetSize()); return GetData()->Data[index]; } - const char& operator [] (UPInt index) const + const char& operator [] (size_t index) const { OVR_ASSERT(index < GetSize()); return GetData()->Data[index]; @@ -373,9 +374,9 @@ public: // Hash functor used for strings. struct HashFunctor { - UPInt operator()(const String& data) const + size_t operator()(const String& data) const { - UPInt size = data.GetSize(); + size_t size = data.GetSize(); return String::BernsteinHashFunction((const char*)data, size); } }; @@ -383,14 +384,14 @@ public: // lookup based on NoCaseKey. struct NoCaseHashFunctor { - UPInt operator()(const String& data) const + size_t operator()(const String& data) const { - UPInt size = data.GetSize(); + size_t size = data.GetSize(); return String::BernsteinHashFunctionCIS((const char*)data, size); } - UPInt operator()(const NoCaseKey& data) const + size_t operator()(const NoCaseKey& data) const { - UPInt size = data.pStr->GetSize(); + size_t size = data.pStr->GetSize(); return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size); } }; @@ -404,18 +405,18 @@ public: class StringBuffer { char* pData; - UPInt Size; - UPInt BufferSize; - UPInt GrowSize; + size_t Size; + size_t BufferSize; + size_t GrowSize; mutable bool LengthIsSize; public: // Constructors / Destructor. StringBuffer(); - explicit StringBuffer(UPInt growSize); + explicit StringBuffer(size_t growSize); StringBuffer(const char* data); - StringBuffer(const char* data, UPInt buflen); + StringBuffer(const char* data, size_t buflen); StringBuffer(const String& src); StringBuffer(const StringBuffer& src); explicit StringBuffer(const wchar_t* data); @@ -423,8 +424,8 @@ public: // Modify grow size used for growing/shrinking the buffer. - UPInt GetGrowSize() const { return GrowSize; } - void SetGrowSize(UPInt growSize); + size_t GetGrowSize() const { return GrowSize; } + void SetGrowSize(size_t growSize); // *** General Functions @@ -437,38 +438,38 @@ public: const char* ToCStr() const { return (pData) ? pData : ""; } // Returns number of bytes. - UPInt GetSize() const { return Size ; } + size_t GetSize() const { return Size ; } // Tells whether or not the string is empty. bool IsEmpty() const { return GetSize() == 0; } // Returns number of characters - UPInt GetLength() const; + size_t GetLength() const; // Returns character at the specified index - UInt32 GetCharAt(UPInt index) const; - UInt32 GetFirstCharAt(UPInt index, const char** offset) const; - UInt32 GetNextChar(const char** offset) const; + uint32_t GetCharAt(size_t index) const; + uint32_t GetFirstCharAt(size_t index, const char** offset) const; + uint32_t GetNextChar(const char** offset) const; // Resize the string to the new size - void Resize(UPInt _size); - void Reserve(UPInt _size); + void Resize(size_t _size); + void Reserve(size_t _size); // Appends a character - void AppendChar(UInt32 ch); + void AppendChar(uint32_t ch); // Append a string - void AppendString(const wchar_t* pstr, SPInt len = -1); - void AppendString(const char* putf8str, SPInt utf8StrSz = -1); + void AppendString(const wchar_t* pstr, intptr_t len = -1); + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); void AppendFormat(const char* format, ...); // Assigned a string with dynamic data (copied through initializer). - //void AssignString(const InitStruct& src, UPInt size); + //void AssignString(const InitStruct& src, size_t size); // Inserts substr at posAt - void Insert (const char* substr, UPInt posAt, SPInt len = -1); + void Insert (const char* substr, size_t posAt, intptr_t len = -1); // Inserts character at posAt - UPInt InsertCharAt(UInt32 c, UPInt posAt); + size_t InsertCharAt(uint32_t c, size_t posAt); // Assignment void operator = (const char* str); @@ -487,10 +488,10 @@ public: // Accesses raw bytes char& operator [] (int index) { - OVR_ASSERT(((UPInt)index) < GetSize()); + OVR_ASSERT(((size_t)index) < GetSize()); return pData[index]; } - char& operator [] (UPInt index) + char& operator [] (size_t index) { OVR_ASSERT(index < GetSize()); return pData[index]; @@ -498,10 +499,10 @@ public: const char& operator [] (int index) const { - OVR_ASSERT(((UPInt)index) < GetSize()); + OVR_ASSERT(((size_t)index) < GetSize()); return pData[index]; } - const char& operator [] (UPInt index) const + const char& operator [] (size_t index) const { OVR_ASSERT(index < GetSize()); return pData[index]; @@ -520,7 +521,7 @@ public: StringDataPtr() : pStr(NULL), Size(0) {} StringDataPtr(const StringDataPtr& p) : pStr(p.pStr), Size(p.Size) {} - StringDataPtr(const char* pstr, UPInt sz) + StringDataPtr(const char* pstr, size_t sz) : pStr(pstr), Size(sz) {} StringDataPtr(const char* pstr) : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {} @@ -532,7 +533,7 @@ public: public: const char* ToCStr() const { return pStr; } - UPInt GetSize() const { return Size; } + size_t GetSize() const { return Size; } bool IsEmpty() const { return GetSize() == 0; } // value is a prefix of this string @@ -550,33 +551,33 @@ public: // Find first character. // init_ind - initial index. - SPInt FindChar(char c, UPInt init_ind = 0) const + intptr_t FindChar(char c, size_t init_ind = 0) const { - for (UPInt i = init_ind; i < GetSize(); ++i) + for (size_t i = init_ind; i < GetSize(); ++i) if (pStr[i] == c) - return static_cast<SPInt>(i); + return static_cast<intptr_t>(i); return -1; } // Find last character. // init_ind - initial index. - SPInt FindLastChar(char c, UPInt init_ind = ~0) const + intptr_t FindLastChar(char c, size_t init_ind = ~0) const { - if (init_ind == (UPInt)~0 || init_ind > GetSize()) + if (init_ind == (size_t)~0 || init_ind > GetSize()) init_ind = GetSize(); else ++init_ind; - for (UPInt i = init_ind; i > 0; --i) + for (size_t i = init_ind; i > 0; --i) if (pStr[i - 1] == c) - return static_cast<SPInt>(i - 1); + return static_cast<intptr_t>(i - 1); return -1; } // Create new object and trim size bytes from the left. - StringDataPtr GetTrimLeft(UPInt size) const + StringDataPtr GetTrimLeft(size_t size) const { // Limit trim size to the size of the string. size = Alg::PMin(GetSize(), size); @@ -584,7 +585,7 @@ public: return StringDataPtr(ToCStr() + size, GetSize() - size); } // Create new object and trim size bytes from the right. - StringDataPtr GetTrimRight(UPInt size) const + StringDataPtr GetTrimRight(size_t size) const { // Limit trim to the size of the string. size = Alg::PMin(GetSize(), size); @@ -596,7 +597,7 @@ public: // Useful for parsing. StringDataPtr GetNextToken(char separator = ':') const { - UPInt cur_pos = 0; + size_t cur_pos = 0; const char* cur_str = ToCStr(); for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos) @@ -611,7 +612,7 @@ public: } // Trim size bytes from the left. - StringDataPtr& TrimLeft(UPInt size) + StringDataPtr& TrimLeft(size_t size) { // Limit trim size to the size of the string. size = Alg::PMin(GetSize(), size); @@ -621,7 +622,7 @@ public: return *this; } // Trim size bytes from the right. - StringDataPtr& TrimRight(UPInt size) + StringDataPtr& TrimRight(size_t size) { // Limit trim to the size of the string. size = Alg::PMin(GetSize(), size); @@ -636,7 +637,7 @@ public: // Hash functor used string data pointers struct HashFunctor { - UPInt operator()(const StringDataPtr& data) const + size_t operator()(const StringDataPtr& data) const { return String::BernsteinHashFunction(data.ToCStr(), data.GetSize()); } @@ -649,7 +650,7 @@ public: protected: const char* pStr; - UPInt Size; + size_t Size; }; } // OVR diff --git a/LibOVR/Src/Kernel/OVR_StringHash.h b/LibOVR/Src/Kernel/OVR_StringHash.h index baa80a7..410a578 100644 --- a/LibOVR/Src/Kernel/OVR_StringHash.h +++ b/LibOVR/Src/Kernel/OVR_StringHash.h @@ -7,16 +7,16 @@ Content : String hash table used when optional case-insensitive Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, diff --git a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp index e196dd7..d52b6bb 100644 --- a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp +++ b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp @@ -5,16 +5,16 @@ Content : String format functions. Created : February 27, 2013 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -32,22 +32,45 @@ namespace OVR { void StringBuffer::AppendFormat(const char* format, ...) { va_list argList; + char buffer[512]; + char* bufferUsed = buffer; + char* bufferAllocated = NULL; va_start(argList, format); - UPInt size = OVR_vscprintf(format, argList); - va_end(argList); - char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1)); + #if !defined(OVR_CC_MSVC) // Non-Microsoft compilers require you to save a copy of the va_list. + va_list argListSaved; + va_copy(argListSaved, argList); + #endif + + int requiredStrlen = OVR_vsnprintf(bufferUsed, OVR_ARRAY_COUNT(buffer), format, argList); // The large majority of the time this will succeed. + + if(requiredStrlen >= (int)sizeof(buffer)) // If the initial capacity wasn't enough... + { + bufferAllocated = (char*)OVR_ALLOC(sizeof(char) * (requiredStrlen + 1)); + bufferUsed = bufferAllocated; + if(bufferAllocated) + { + #if !defined(OVR_CC_MSVC) + va_end(argList); + va_copy(argList, argListSaved); + #endif + requiredStrlen = OVR_vsnprintf(bufferAllocated, (requiredStrlen + 1), format, argList); + } + } + + if(requiredStrlen < 0) // If there was a printf format error... + { + bufferUsed = NULL; + } - va_start(argList, format); - UPInt result = OVR_vsprintf(buffer, size+1, format, argList); - OVR_UNUSED1(result); va_end(argList); - OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf")); - AppendString(buffer); + if(bufferUsed) + AppendString(bufferUsed); - OVR_FREE(buffer); + if(bufferAllocated) + OVR_FREE(bufferAllocated); } } // OVR diff --git a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp index 02abe15..95f3de9 100644 --- a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp +++ b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp @@ -5,16 +5,16 @@ Content : String filename/url helper function Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -39,7 +39,7 @@ void ScanFilePath(const char* url, const char** pfilename, const char** pext) const char *filename = 0; const char *lastDot = 0; - UInt32 charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal = UTF8Util::DecodeNextChar(&url); while (charVal != 0) { @@ -76,8 +76,8 @@ void ScanFilePath(const char* url, const char** pfilename, const char** pext) // - protocol: 'file://', 'http://' const char* ScanPathProtocol(const char* url) { - UInt32 charVal = UTF8Util::DecodeNextChar(&url); - UInt32 charVal2; + uint32_t charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal2; while (charVal != 0) { @@ -118,7 +118,7 @@ bool String::HasAbsolutePath(const char* url) if (!url || !*url) return true; // Treat empty strings as absolute. - UInt32 charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal = UTF8Util::DecodeNextChar(&url); // Fist character of '/' or '\\' means absolute url. if ((charVal == '/') || (charVal == '\\')) diff --git a/LibOVR/Src/Kernel/OVR_SysFile.cpp b/LibOVR/Src/Kernel/OVR_SysFile.cpp index 604527a..6ef27c7 100644 --- a/LibOVR/Src/Kernel/OVR_SysFile.cpp +++ b/LibOVR/Src/Kernel/OVR_SysFile.cpp @@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32) Created : April 5, 1999 Authors : Michael Antonov -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -51,24 +51,24 @@ public: // Return position / file size virtual int Tell() { return 0; } - virtual SInt64 LTell() { return 0; } + virtual int64_t LTell() { return 0; } virtual int GetLength() { return 0; } - virtual SInt64 LGetLength() { return 0; } + virtual int64_t LGetLength() { return 0; } // virtual bool Stat(FileStats *pfs) { return 0; } virtual int GetErrorCode() { return Error_FileNotFound; } // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } - virtual int Read(UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } - virtual int SkipBytes(int numBytes) { return 0; OVR_UNUSED(numBytes); } - virtual int BytesAvailable() { return 0; } - virtual bool Flush() { return 0; } - virtual int Seek(int offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } - virtual SInt64 LSeek(SInt64 offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } + virtual int Write(const uint8_t * /*pbuffer*/, int /*numBytes*/) { return -1; } + virtual int Read(uint8_t * /*pbuffer*/, int /*numBytes*/) { return -1; } + virtual int SkipBytes(int /*numBytes*/) { return 0; } + virtual int BytesAvailable() { return 0; } + virtual bool Flush() { return 0; } + virtual int Seek(int /*offset*/, int /*origin*/) { return -1; } + virtual int64_t LSeek(int64_t /*offset*/, int /*origin*/) { return -1; } - virtual int CopyFromStream(File *pstream, int byteSize) { return -1; OVR_UNUSED2(pstream, byteSize); } - virtual bool Close() { return 0; } + virtual int CopyFromStream(File * /*pstream*/, int /*byteSize*/) { return -1; } + virtual bool Close() { return 0; } }; diff --git a/LibOVR/Src/Kernel/OVR_SysFile.h b/LibOVR/Src/Kernel/OVR_SysFile.h index 61ad6e8..925c51d 100644 --- a/LibOVR/Src/Kernel/OVR_SysFile.h +++ b/LibOVR/Src/Kernel/OVR_SysFile.h @@ -11,16 +11,16 @@ Notes : errno may not be preserved across use of GBaseFile member functi : Directories cannot be deleted while files opened from them are in use (For the GetFullName function) -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -48,9 +48,9 @@ class SysFile; struct FileStat { // No change or create time because they are not available on most systems - SInt64 ModifyTime; - SInt64 AccessTime; - SInt64 FileSize; + int64_t ModifyTime; + int64_t AccessTime; + int64_t FileSize; bool operator== (const FileStat& stat) const { diff --git a/LibOVR/Src/Kernel/OVR_System.cpp b/LibOVR/Src/Kernel/OVR_System.cpp index 3144ade..66c764a 100644 --- a/LibOVR/Src/Kernel/OVR_System.cpp +++ b/LibOVR/Src/Kernel/OVR_System.cpp @@ -6,16 +6,16 @@ Content : General kernel initialization/cleanup, including that Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -28,10 +28,56 @@ limitations under the License. #include "OVR_System.h" #include "OVR_Threads.h" #include "OVR_Timer.h" +#include "../Displays/OVR_Display.h" +#ifdef OVR_OS_WIN32 +#include "../Displays/OVR_Win32_ShimFunctions.h" +#endif namespace OVR { -// ***** OVR::System Implementation +#ifdef OVR_OS_WIN32 +extern bool anyRiftsInExtendedMode(); +#endif + +// Stack of destroy listeners (push/pop semantics) +static SystemSingletonInternal *SystemShutdownListenerStack = 0; +static Lock stackLock; +static bool DisplayShimInitialized = false; + +void SystemSingletonInternal::PushDestroyCallbacks() +{ + Lock::Locker locker(&stackLock); + + // Push listener onto the stack + NextSingleton = SystemShutdownListenerStack; + SystemShutdownListenerStack = this; +} + +void System::DirectDisplayInitialize() +{ +#ifdef OVR_OS_WIN32 + // Set up display code for Windows + Win32::DisplayShim::GetInstance(); + + // This code will look for the first display. If it's a display + // that's extending the destkop, the code will assume we're in + // compatibility mode. Compatibility mode prevents shim loading + // and renders only to extended Rifts. + // If we find a display and it's application exclusive, + // we load the shim so we can render to it. + // If no display is available, we revert to whatever the + // driver tells us we're in + + bool anyExtendedRifts = anyRiftsInExtendedMode() || Display::InCompatibilityMode( false ); + + DisplayShimInitialized = Win32::DisplayShim::GetInstance().Initialize(anyExtendedRifts); +#endif +} + +bool System::DirectDisplayEnabled() +{ + return DisplayShimInitialized; +} // Initializes System core, installing allocator. void System::Init(Log* log, Allocator *palloc) @@ -41,6 +87,8 @@ void System::Init(Log* log, Allocator *palloc) Log::SetGlobalLog(log); Timer::initializeTimerSystem(); Allocator::setInstance(palloc); + Display::Initialize(); + DirectDisplayInitialize(); } else { @@ -52,13 +100,33 @@ void System::Destroy() { if (Allocator::GetInstance()) { - // Wait for all threads to finish; this must be done so that memory - // allocator and all destructors finalize correctly. +#ifdef OVR_OS_WIN32 + Win32::DisplayShim::GetInstance().Shutdown(); +#endif + + // Invoke all of the post-finish callbacks (normal case) + for (SystemSingletonInternal *listener = SystemShutdownListenerStack; listener; listener = listener->NextSingleton) + { + listener->OnThreadDestroy(); + } + #ifdef OVR_ENABLE_THREADS - Thread::FinishAllThreads(); + // Wait for all threads to finish; this must be done so that memory + // allocator and all destructors finalize correctly. + Thread::FinishAllThreads(); #endif - // Shutdown heap and destroy SysAlloc singleton, if any. + // Invoke all of the post-finish callbacks (normal case) + for (SystemSingletonInternal *next, *listener = SystemShutdownListenerStack; listener; listener = next) + { + next = listener->NextSingleton; + + listener->OnSystemDestroy(); + } + + SystemShutdownListenerStack = 0; + + // Shutdown heap and destroy SysAlloc singleton, if any. Allocator::GetInstance()->onSystemShutdown(); Allocator::setInstance(0); @@ -77,5 +145,5 @@ bool System::IsInitialized() return Allocator::GetInstance() != 0; } -} // OVR +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h index 253fe19..9d09911 100644 --- a/LibOVR/Src/Kernel/OVR_System.h +++ b/LibOVR/Src/Kernel/OVR_System.h @@ -7,16 +7,16 @@ Content : General kernel initialization/cleanup, including that Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -31,9 +31,103 @@ limitations under the License. #include "OVR_Allocator.h" #include "OVR_Log.h" +#include "OVR_Atomic.h" namespace OVR { + +//----------------------------------------------------------------------------- +// SystemSingleton + +// Subsystems are implemented using the Singleton pattern. +// To avoid code duplication in all the places where Singletons are defined, +// The pattern is defined once here and used everywhere. + +class SystemSingletonInternal +{ + friend class System; + + SystemSingletonInternal* NextSingleton; + + // No copying allowed + OVR_NON_COPYABLE(SystemSingletonInternal); + +protected: + SystemSingletonInternal() : + NextSingleton(0) + { + } + + virtual ~SystemSingletonInternal(){} + + // Call this to register the destroy events + // Destroy callbacks will be called in the reverse order they were registered + // Note: As a rule of thumb, call this at the end of the singleton class constructor. + void PushDestroyCallbacks(); + + // Required: Invoked when the System object is shutting down + // Called after threads are stopped + // Called before Log, Allocator, and Timer subsystems are stopped + // Listeners are called in the opposite order they were registered + virtual void OnSystemDestroy() = 0; + + // Called just before waiting for threads to die + // Listeners are called in the opposite order they were registered + // Useful to start terminating threads at the right time + // Note: The singleton must not delete itself here. + virtual void OnThreadDestroy() {} +}; + +// Singletons derive from this class +template<class T> +class SystemSingletonBase : public SystemSingletonInternal +{ + static AtomicPtr<T> SingletonInstance; + static T* SlowGetInstance(); + +protected: + ~SystemSingletonBase() + { + // Make sure the instance gets set to zero on dtor + if (SingletonInstance == this) + SingletonInstance = 0; + } + +public: + static OVR_FORCE_INLINE T* GetInstance() + { + // Fast version + // Note: The singleton instance is stored in an AtomicPtr<> to allow it to be accessed + // atomically from multiple threads without locks. + T* instance = SingletonInstance; + return instance ? instance : SlowGetInstance(); + } +}; + +// For reference, see N3337 14.5.1.3 (Static data members of class templates): +template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstance; + +// Place this in the singleton class in the header file +#define OVR_DECLARE_SINGLETON(T) \ + friend class OVR::SystemSingletonBase<T>; \ +private: \ + T(); \ + virtual ~T(); \ + virtual void OnSystemDestroy(); + +// Place this in the singleton class source file +#define OVR_DEFINE_SINGLETON(T) \ + namespace OVR { \ + template<> T* SystemSingletonBase<T>::SlowGetInstance() \ + { \ + static OVR::Lock lock; \ + OVR::Lock::Locker locker(&lock); \ + if (!SingletonInstance) SingletonInstance = new T; \ + return SingletonInstance; \ + } \ + } + + // ***** System Core Initialization class // System initialization must take place before any other OVR_Kernel objects are used; @@ -47,19 +141,20 @@ namespace OVR { class System { public: - // System constructor expects allocator to be specified, if it is being substituted. System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), Allocator* palloc = DefaultAllocator::InitSystemSingleton()) { Init(log, palloc); } - ~System() { Destroy(); } + static void OVR_CDECL DirectDisplayInitialize(); + static bool OVR_CDECL DirectDisplayEnabled(); + // Returns 'true' if system was properly initialized. static bool OVR_CDECL IsInitialized(); @@ -68,11 +163,12 @@ public: static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), Allocator *palloc = DefaultAllocator::InitSystemSingleton()); - // De-initializes System more, finalizing the threading system and destroying + // De-initializes System more, finalizing the threading system and destroying // the global memory allocator. - static void OVR_CDECL Destroy(); + static void OVR_CDECL Destroy(); }; -} // OVR + +} // namespace OVR #endif diff --git a/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp new file mode 100644 index 0000000..90ba3cc --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp @@ -0,0 +1,401 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_ThreadCommandQueue.cpp +Content : Command queue for operations executed on a thread +Created : October 29, 2012 + +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_ThreadCommandQueue.h" + +namespace OVR { + + +//------------------------------------------------------------------------ +// ***** CircularBuffer + +// CircularBuffer is a FIFO buffer implemented in a single block of memory, +// which allows writing and reading variable-size data chucks. Write fails +// if buffer is full. + +class CircularBuffer +{ + enum { + AlignSize = 16, + AlignMask = AlignSize - 1 + }; + + uint8_t* pBuffer; + size_t Size; + size_t Tail; // Byte offset of next item to be popped. + size_t Head; // Byte offset of where next push will take place. + size_t End; // When Head < Tail, this is used instead of Size. + + inline size_t roundUpSize(size_t size) + { return (size + AlignMask) & ~(size_t)AlignMask; } + +public: + + CircularBuffer(size_t size) + : Size(size), Tail(0), Head(0), End(0) + { + pBuffer = (uint8_t*)OVR_ALLOC_ALIGNED(roundUpSize(size), AlignSize); + } + ~CircularBuffer() + { + // For ThreadCommands, we must consume everything before shutdown. + OVR_ASSERT(IsEmpty()); + OVR_FREE_ALIGNED(pBuffer); + } + + bool IsEmpty() const { return (Head == Tail); } + + // Allocates a state block of specified size and advances pointers, + // returning 0 if buffer is full. + uint8_t* Write(size_t size); + + // Returns a pointer to next available data block; 0 if none available. + uint8_t* ReadBegin() + { return (Head != Tail) ? (pBuffer + Tail) : 0; } + // Consumes data of specified size; this must match size passed to Write. + void ReadEnd(size_t size); +}; + + +// Allocates a state block of specified size and advances pointers, +// returning 0 if buffer is full. +uint8_t* CircularBuffer::Write(size_t size) +{ + uint8_t* p = 0; + + size = roundUpSize(size); + // Since this is circular buffer, always allow at least one item. + OVR_ASSERT(size < Size/2); + + if (Head >= Tail) + { + OVR_ASSERT(End == 0); + + if (size <= (Size - Head)) + { + p = pBuffer + Head; + Head += size; + } + else if (size < Tail) + { + p = pBuffer; + End = Head; + Head = size; + OVR_ASSERT(Head != Tail); + } + } + else + { + OVR_ASSERT(End != 0); + + if ((Tail - Head) > size) + { + p = pBuffer + Head; + Head += size; + OVR_ASSERT(Head != Tail); + } + } + + return p; +} + +void CircularBuffer::ReadEnd(size_t size) +{ + OVR_ASSERT(Head != Tail); + size = roundUpSize(size); + + Tail += size; + if (Tail == End) + { + Tail = End = 0; + } + else if (Tail == Head) + { + OVR_ASSERT(End == 0); + Tail = Head = 0; + } +} + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommand + +ThreadCommand::PopBuffer::~PopBuffer() +{ + if (Size) { + Destruct<ThreadCommand>(toCommand()); + } +} + +void ThreadCommand::PopBuffer::InitFromBuffer(void* data) +{ + ThreadCommand* cmd = (ThreadCommand*)data; + OVR_ASSERT(cmd->Size <= MaxSize); + + if (Size) { + Destruct<ThreadCommand>(toCommand()); + } + Size = cmd->Size; + memcpy(Buffer, (void*)cmd, Size); +} + +void ThreadCommand::PopBuffer::Execute() +{ + ThreadCommand* command = toCommand(); + OVR_ASSERT(command); + command->Execute(); + if (NeedsWait()) { + GetEvent()->PulseEvent(); + } +} + +//------------------------------------------------------------------------------------- + +class ThreadCommandQueueImpl : public NewOverrideBase +{ + typedef ThreadCommand::NotifyEvent NotifyEvent; + friend class ThreadCommandQueue; + +public: + + ThreadCommandQueueImpl(ThreadCommandQueue* queue) : + pQueue(queue), + ExitEnqueued(false), + ExitProcessed(false), + CommandBuffer(2048), + PullThreadId(0) + { + } + ~ThreadCommandQueueImpl(); + + + bool PushCommand(const ThreadCommand& command); + bool PopCommand(ThreadCommand::PopBuffer* popBuffer); + + + // ExitCommand is used by notify us that Thread is shutting down. + struct ExitCommand : public ThreadCommand + { + ThreadCommandQueueImpl* pImpl; + + ExitCommand(ThreadCommandQueueImpl* impl, bool wait) + : ThreadCommand(sizeof(ExitCommand), wait, true), pImpl(impl) { } + + virtual void Execute() const + { + Lock::Locker lock(&pImpl->QueueLock); + pImpl->ExitProcessed = true; + } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ExitCommand>(p, *this); } + }; + + + NotifyEvent* AllocNotifyEvent_NTS() + { + NotifyEvent* p = AvailableEvents.GetFirst(); + + if (!AvailableEvents.IsNull(p)) + p->RemoveNode(); + else + p = new NotifyEvent; + return p; + } + + void FreeNotifyEvent_NTS(NotifyEvent* p) + { + AvailableEvents.PushBack(p); + } + + void FreeNotifyEvents_NTS() + { + while(!AvailableEvents.IsEmpty()) + { + NotifyEvent* p = AvailableEvents.GetFirst(); + p->RemoveNode(); + delete p; + } + } + + ThreadCommandQueue* pQueue; + Lock QueueLock; + volatile bool ExitEnqueued; + volatile bool ExitProcessed; + List<NotifyEvent> AvailableEvents; + List<NotifyEvent> BlockedProducers; + CircularBuffer CommandBuffer; + + // The pull thread id is set to the last thread that pulled commands. + // Since this thread command queue is designed for a single thread, + // reentrant behavior that would cause a dead-lock for messages that + // wait for completion can be avoided by simply comparing the + // thread id of the last pull. + OVR::ThreadId PullThreadId; +}; + +ThreadCommandQueueImpl::~ThreadCommandQueueImpl() +{ + Lock::Locker lock(&QueueLock); + OVR_ASSERT(BlockedProducers.IsEmpty()); + FreeNotifyEvents_NTS(); +} + +bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command) +{ + if (command.NeedsWait() && PullThreadId == OVR::GetCurrentThreadId()) + { + command.Execute(); + return true; + } + + ThreadCommand::NotifyEvent* completeEvent = 0; + ThreadCommand::NotifyEvent* queueAvailableEvent = 0; + + // Repeat writing command into buffer until it is available. + for (;;) { + { // Lock Scope + Lock::Locker lock(&QueueLock); + + if (queueAvailableEvent) { + FreeNotifyEvent_NTS(queueAvailableEvent); + queueAvailableEvent = 0; + } + + // Don't allow any commands after PushExitCommand() is called. + if (ExitEnqueued && !command.ExitFlag) { + return false; + } + + bool bufferWasEmpty = CommandBuffer.IsEmpty(); + uint8_t* buffer = CommandBuffer.Write(command.GetSize()); + + if (buffer) { + ThreadCommand* c = command.CopyConstruct(buffer); + + if (c->NeedsWait()) { + completeEvent = c->pEvent = AllocNotifyEvent_NTS(); + } + + // Signal-waker consumer when we add data to buffer. + if (bufferWasEmpty) { + pQueue->OnPushNonEmpty_Locked(); + } + + break; + } + + queueAvailableEvent = AllocNotifyEvent_NTS(); + BlockedProducers.PushBack(queueAvailableEvent); + } // Lock Scope + + queueAvailableEvent->Wait(); + } // Intentional infinite loop + + // Command was enqueued, wait if necessary. + if (completeEvent) { + completeEvent->Wait(); + Lock::Locker lock(&QueueLock); + FreeNotifyEvent_NTS(completeEvent); + } + + return true; +} + + +// Pops the next command from the thread queue, if any is available. +bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer) +{ + PullThreadId = OVR::GetCurrentThreadId(); + + Lock::Locker lock(&QueueLock); + + uint8_t* buffer = CommandBuffer.ReadBegin(); + if (!buffer) + { + // Notify thread while in lock scope, enabling initialization of wait. + pQueue->OnPopEmpty_Locked(); + return false; + } + + popBuffer->InitFromBuffer(buffer); + CommandBuffer.ReadEnd(popBuffer->GetSize()); + + if (!BlockedProducers.IsEmpty()) + { + ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst(); + queueAvailableEvent->RemoveNode(); + queueAvailableEvent->PulseEvent(); + // Event is freed later by waiter. + } + return true; +} + + +//------------------------------------------------------------------------------------- + +ThreadCommandQueue::ThreadCommandQueue() +{ + pImpl = new ThreadCommandQueueImpl(this); +} +ThreadCommandQueue::~ThreadCommandQueue() +{ + delete pImpl; +} + +bool ThreadCommandQueue::PushCommand(const ThreadCommand& command) +{ + return pImpl->PushCommand(command); +} + +bool ThreadCommandQueue::PopCommand(ThreadCommand::PopBuffer* popBuffer) +{ + return pImpl->PopCommand(popBuffer); +} + +void ThreadCommandQueue::PushExitCommand(bool wait) +{ + // Exit is processed in two stages: + // - First, ExitEnqueued flag is set to block further commands from queuing up. + // - Second, the actual exit call is processed on the consumer thread, flushing + // any prior commands. + // IsExiting() only returns true after exit has flushed. + { + Lock::Locker lock(&pImpl->QueueLock); + if (pImpl->ExitEnqueued) + return; + pImpl->ExitEnqueued = true; + } + + PushCommand(ThreadCommandQueueImpl::ExitCommand(pImpl, wait)); +} + +bool ThreadCommandQueue::IsExiting() const +{ + return pImpl->ExitProcessed; +} + + +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h new file mode 100644 index 0000000..9c2a7d3 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h @@ -0,0 +1,318 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_ThreadCommandQueue.h +Content : Command queue for operations executed on a thread +Created : October 29, 2012 +Author : Michael Antonov + +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. + +************************************************************************************/ + +#ifndef OVR_ThreadCommandQueue_h +#define OVR_ThreadCommandQueue_h + +#include "../Kernel/OVR_Types.h" +#include "../Kernel/OVR_List.h" +#include "../Kernel/OVR_Atomic.h" +#include "../Kernel/OVR_Threads.h" + +namespace OVR { + +class ThreadCommand; +class ThreadCommandQueue; + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommand + +// ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue. +class ThreadCommand +{ +public: + // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the + // calling (producer) thread when command is completed or queue slot is available. + class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase + { + Event E; + public: + NotifyEvent() { } + + void Wait() { E.Wait(); } + void PulseEvent() { E.PulseEvent(); } + }; + + // ThreadCommand::PopBuffer is temporary storage for a command popped off + // by ThreadCommandQueue::PopCommand. + class PopBuffer + { + enum { MaxSize = 256 }; + + size_t Size; + union { + uint8_t Buffer[MaxSize]; + size_t Align; + }; + + ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; } + + public: + PopBuffer() : Size(0) { } + ~PopBuffer(); + + void InitFromBuffer(void* data); + + bool HasCommand() const { return Size != 0; } + size_t GetSize() const { return Size; } + bool NeedsWait() const { return toCommand()->NeedsWait(); } + NotifyEvent* GetEvent() const { return toCommand()->pEvent; } + + // Execute the command and also notifies caller to finish waiting, + // if necessary. + void Execute(); + }; + + uint16_t Size; + bool WaitFlag; + bool ExitFlag; // Marks the last exit command. + NotifyEvent* pEvent; + + ThreadCommand(size_t size, bool waitFlag, bool exitFlag = false) + : Size((uint16_t)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { } + virtual ~ThreadCommand() { } + + bool NeedsWait() const { return WaitFlag; } + size_t GetSize() const { return Size; } + + virtual void Execute() const = 0; + // Copy constructor used for serializing this to memory buffer. + virtual ThreadCommand* CopyConstruct(void* p) const = 0; +}; + + +//------------------------------------------------------------------------------------- + +// CleanType is a template that strips 'const' and '&' modifiers from the argument type; +// for example, typename CleanType<A&>::Type is equivalent to A. +template<class T> struct CleanType { typedef T Type; }; +template<class T> struct CleanType<T&> { typedef T Type; }; +template<class T> struct CleanType<const T> { typedef T Type; }; +template<class T> struct CleanType<const T&> { typedef T Type; }; + +// SelfType is a template that yields the argument type. This helps avoid conflicts with +// automatic template argument deduction for function calls when identical argument +// is already defined. +template<class T> struct SelfType { typedef T Type; }; + + + +//------------------------------------------------------------------------------------- +// ThreadCommand specializations for member functions with different number of +// arguments and argument types. + +// Used to return nothing from a ThreadCommand, to avoid problems with 'void'. +struct Void +{ + Void() {} + Void(int) {} +}; + +// ThreadCommand for member function with 0 arguments. +template<class C, class R> +class ThreadCommandMF0 : public ThreadCommand +{ + typedef R (C::*FnPtr)(); + C* pClass; + FnPtr pFn; + R* pRet; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)()) : + (void)(pClass->*pFn)(); + } + +public: + ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF0), needsWait), + pClass(pclass), pFn(fn), pRet(ret) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF0>(p, *this); } +}; + + +// ThreadCommand for member function with 1 argument. +template<class C, class R, class A0> +class ThreadCommandMF1 : public ThreadCommand +{ + typedef R (C::*FnPtr)(A0); + C* pClass; + FnPtr pFn; + R* pRet; + typename CleanType<A0>::Type AVal0; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) : + (void)(pClass->*pFn)(AVal0); + } + +public: + ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF1), needsWait), + pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF1>(p, *this); } +}; + +// ThreadCommand for member function with 2 arguments. +template<class C, class R, class A0, class A1> +class ThreadCommandMF2 : public ThreadCommand +{ + typedef R (C::*FnPtr)(A0, A1); + C* pClass; + FnPtr pFn; + R* pRet; + typename CleanType<A0>::Type AVal0; + typename CleanType<A1>::Type AVal1; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) : + (void)(pClass->*pFn)(AVal0, AVal1); + } + +public: + ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF2), needsWait), + pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF2>(p, *this); } +}; + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommandQueue + +// ThreadCommandQueue is a queue of executable function-call commands intended to be +// serviced by a single consumer thread. Commands are added to the queue with PushCall +// and removed with PopCall; they are processed in FIFO order. Multiple producer threads +// are supported and will be blocked if internal data buffer is full. + +class ThreadCommandQueue +{ +public: + + ThreadCommandQueue(); + virtual ~ThreadCommandQueue(); + + + // Pops the next command from the thread queue, if any is available. + // The command should be executed by calling popBuffer->Execute(). + // Returns 'false' if no command is available at the time of the call. + bool PopCommand(ThreadCommand::PopBuffer* popBuffer); + + // Generic implementaion of PushCommand; enqueues a command for execution. + // Returns 'false' if push failed, usually indicating thread shutdown. + bool PushCommand(const ThreadCommand& command); + + // + void PushExitCommand(bool wait); + + // Returns 'true' once ExitCommand has been processed, so the thread can shut down. + bool IsExiting() const; + + + // These two virtual functions serve as notifications for derived + // thread waiting. + virtual void OnPushNonEmpty_Locked() { } + virtual void OnPopEmpty_Locked() { } + + + // *** PushCall with no result + + // Enqueue a member function of 'this' class to be called on consumer thread. + // By default the function returns immediately; set 'wait' argument to 'true' to + // wait for completion. + template<class C, class R> + bool PushCall(R (C::*fn)(), bool wait = false) + { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); } + template<class C, class R, class A0> + bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false) + { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); } + template<class C, class R, class A0, class A1> + bool PushCall(R (C::*fn)(A0, A1), + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); } + // Enqueue a specified member function call of class C. + // By default the function returns immediately; set 'wait' argument to 'true' to + // wait for completion. + template<class C, class R> + bool PushCall(C* p, R (C::*fn)(), bool wait = false) + { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); } + template<class C, class R, class A0> + bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false) + { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); } + template<class C, class R, class A0, class A1> + bool PushCall(C* p, R (C::*fn)(A0, A1), + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); } + + + // *** PushCall with Result + + // Enqueue a member function of 'this' class call and wait for call to complete + // on consumer thread before returning. + template<class C, class R> + bool PushCallAndWaitResult(R (C::*fn)(), R* ret) + { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); } + template<class C, class R, class A0> + bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0) + { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); } + template<class C, class R, class A0, class A1> + bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret, + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); } + // Enqueue a member function call for class C and wait for the call to complete + // on consumer thread before returning. + template<class C, class R> + bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret) + { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); } + template<class C, class R, class A0> + bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0) + { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); } + template<class C, class R, class A0, class A1> + bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret, + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); } + +private: + class ThreadCommandQueueImpl* pImpl; +}; + + +} // namespace OVR + +#endif // OVR_ThreadCommandQueue_h diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h index 307f107..e159157 100644 --- a/LibOVR/Src/Kernel/OVR_Threads.h +++ b/LibOVR/Src/Kernel/OVR_Threads.h @@ -6,16 +6,16 @@ Content : Contains thread-related (safe) functionality Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -175,8 +175,13 @@ public: //----------------------------------------------------------------------------------- // ***** Thread class -// ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and -// Thread::GetThreadId. +// ThreadHandle is a handle to a thread, which on some platforms (e.g. Windows) is +// different from ThreadId. On Unix platforms, a ThreadHandle is the same as a +// ThreadId and is pthread_t. +typedef void* ThreadHandle; + +// ThreadId uniquely identifies a thread; returned by Windows GetCurrentThreadId(), +// Unix pthread_self() and Thread::GetThreadId. typedef void* ThreadId; @@ -196,9 +201,7 @@ typedef void* ThreadId; class Thread : public RefCountBase<Thread> { // NOTE: Waitable must be the first base since it implements RefCountImpl. - public: - // *** Callback functions, can be used instead of overriding Run // Run function prototypes. @@ -234,30 +237,31 @@ public: // Thread constructor parameters struct CreateParams { - CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, + CreateParams(ThreadFn func = 0, void* hand = 0, size_t ssize = 128 * 1024, int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) : threadFunction(func), userHandle(hand), stackSize(ssize), processor(proc), initialState(state), priority(prior) {} ThreadFn threadFunction; // Thread function void* userHandle; // User handle passes to a thread - UPInt stackSize; // Thread stack size + size_t stackSize; // Thread stack size int processor; // Thread hardware processor ThreadState initialState; // ThreadPriority priority; // Thread priority }; + // *** Constructors // A default constructor always creates a thread in NotRunning state, because // the derived class has not yet been initialized. The derived class can call Start explicitly. // "processor" parameter specifies which hardware processor this thread will be run on. // -1 means OS decides this. Implemented only on Win32 - Thread(UPInt stackSize = 128 * 1024, int processor = -1); + Thread(size_t stackSize = 128 * 1024, int processor = -1); // Constructors that initialize the thread with a pointer to function. // An option to start a thread is available, but it should not be used if classes are derived from Thread. // "processor" parameter specifies which hardware processor this thread will be run on. // -1 means OS decides this. Implemented only on Win32 - Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024, + Thread(ThreadFn threadFunction, void* userHandle = 0, size_t stackSize = 128 * 1024, int processor = -1, ThreadState initialState = NotRunning); // Constructors that initialize the thread with a create parameters structure. explicit Thread(const CreateParams& params); @@ -314,6 +318,11 @@ public: // Returns current thread state ThreadState GetThreadState() const; + // Wait for thread to finish for a maxmimum number of milliseconds + // For maxWaitMs = 0 it simply polls and then returns if the thread is not finished + // For maxWaitMs < 0 it will wait forever + bool Join(int maxWaitMs = -1) const; + // Returns the number of available CPUs on the system static int GetCPUCount(); @@ -321,19 +330,35 @@ public: // and set to the return value if Run function after the thread is finished. inline int GetExitCode() const { return ExitCode; } // Returns an OS handle -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) void* GetOSHandle() const { return ThreadHandle; } #else pthread_t GetOSHandle() const { return ThreadHandle; } #endif -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) ThreadId GetThreadId() const { return IdValue; } #else ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } #endif - static int GetOSPriority(ThreadPriority); + // Returns the platform-specific equivalent const that corresponds to the given ThreadPriority. + static int GetOSPriority(ThreadPriority); + static ThreadPriority GetOVRPriority(int osPriority); // May return a value outside the ThreadPriority enum range in unusual cases. + + // Gets this instance's priority. + ThreadPriority GetPriority(); + + // Gets the current thread's priority. + static ThreadPriority GetCurrentPriority(); + + // Sets this instance's thread's priority. + // Some platforms (e.g. Unix) don't let you set thread priorities unless you have root privileges/ + bool SetPriority(ThreadPriority); + + // Sets the current thread's priority. + static bool SetCurrentPriority(ThreadPriority); + // *** Sleep // Sleep secs seconds @@ -343,16 +368,18 @@ public: // *** Debugging functionality -#if defined(OVR_OS_WIN32) - virtual void SetThreadName( const char* name ); -#else - virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); } -#endif + virtual void SetThreadName(const char* name); + static void SetThreadName(const char* name, ThreadId threadId); + static void SetCurrentThreadName(const char* name); + + static void GetThreadName(char* name, size_t nameCapacity, ThreadId threadId); + static void GetCurrentThreadName(char* name, size_t nameCapacity); private: #if defined(OVR_OS_WIN32) - friend unsigned WINAPI Thread_Win32StartFn(void *pthread); - + friend unsigned WINAPI Thread_Win32StartFn(void *phandle); +#elif defined(OVR_OS_MS) // Any other Microsoft OS... + friend DWORD WINAPI Thread_Win32StartFn(void *phandle); #else friend void *Thread_PthreadStartFn(void * phandle); @@ -362,15 +389,15 @@ private: protected: // Thread state flags - AtomicInt<UInt32> ThreadFlags; - AtomicInt<SInt32> SuspendCount; - UPInt StackSize; + AtomicInt<uint32_t> ThreadFlags; + AtomicInt<int32_t> SuspendCount; + size_t StackSize; // Hardware processor which this thread is running on. int Processor; ThreadPriority Priority; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) void* ThreadHandle; volatile ThreadId IdValue; diff --git a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp index da483d5..760e489 100644 --- a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp +++ b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp @@ -5,16 +5,16 @@ Content : Created : Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -33,11 +33,21 @@ limitations under the License. #include "OVR_Log.h" #include <pthread.h> +#include <sched.h> #include <time.h> #include <unistd.h> #include <sys/time.h> #include <errno.h> +#if defined(OVR_OS_MAC) || defined(OVR_OS_BSD) + #include <sys/sysctl.h> + #include <sys/param.h> + #if !defined(OVR_OS_MAC) + #include <pthread_np.h> + #endif +#endif + + namespace OVR { @@ -127,9 +137,9 @@ void MutexImpl::Unlock(Mutex* pmutex) OVR_UNUSED(pmutex); OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); - unsigned lockCount; + //unsigned lockCount; LockCount--; - lockCount = LockCount; + //lockCount = LockCount; pthread_mutex_unlock(&SMutex); } @@ -619,6 +629,48 @@ Thread::ThreadState Thread::GetThreadState() const return Running; return NotRunning; } + +// Join thread +bool Thread::Join(int maxWaitMs) const +{ + // If polling, + if (maxWaitMs == 0) + { + // Just return if finished + return IsFinished(); + } + // If waiting forever, + else if (maxWaitMs > 0) + { + UInt32 t0 = Timer::GetTicksMs(); + + while (!IsFinished()) + { + UInt32 t1 = Timer::GetTicksMs(); + + // If the wait has expired, + int delta = (int)(t1 - t0); + if (delta >= maxWaitMs) + { + return false; + } + + Thread::MSleep(10); + } + + return true; + } + else + { + while (!IsFinished()) + { + pthread_join(ThreadHandle, NULL); + } + } + + return true; +} + /* static const char* mapsched_policy(int policy) { @@ -662,12 +714,88 @@ pthread_attr_t Thread::Attr; /* static */ int Thread::GetOSPriority(ThreadPriority p) -//static inline int MapToSystemPrority(Thread::ThreadPriority p) { OVR_UNUSED(p); return -1; } +/* static */ +Thread::ThreadPriority Thread::GetOVRPriority(int osPriority) +{ + #if defined(OVR_OS_LINUX) + return (ThreadPriority)(Thread::NormalPriority - osPriority); // This works for both SCHED_OTHER, SCHED_RR, and SCHED_FIFO. + #else + // Apple priorities are such that the min is a value less than the max. + static int minPriority = sched_get_priority_min(SCHED_FIFO); // We don't have a means to pass a policy type to this function. + static int maxPriority = sched_get_priority_max(SCHED_FIFO); + + return (ThreadPriority)(Thread::NormalPriority - (osPriority - ((minPriority + maxPriority) / 2))); + #endif +} + + +Thread::ThreadPriority Thread::GetPriority() +{ + int policy; + sched_param param; + + int result = pthread_getschedparam(ThreadHandle, &policy, ¶m); + + if(result == 0) + { + #if !defined(OVR_OS_LINUX) + if(policy == SCHED_OTHER) + { + return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X. + } + #endif + + return GetOVRPriority(param.sched_priority); + } + + return Thread::NormalPriority; +} + +/* static */ +Thread::ThreadPriority Thread::GetCurrentPriority() +{ + int policy; + sched_param param; + pthread_t currentThreadId = pthread_self(); + + int result = pthread_getschedparam(currentThreadId, &policy, ¶m); + + if(result == 0) + { + #if !defined(OVR_OS_LINUX) + if(policy == SCHED_OTHER) + { + return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X. + } + #endif + + return GetOVRPriority(param.sched_priority); + } + + return Thread::NormalPriority; +} + + +bool Thread::SetPriority(ThreadPriority) +{ + // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam + // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges. + return false; +} + +/* static */ +bool Thread::SetCurrentPriority(ThreadPriority) +{ + // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam + // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges. + return false; +} + bool Thread::Start(ThreadState initialState) { if (initialState == NotRunning) @@ -779,9 +907,78 @@ bool Thread::MSleep(unsigned msecs) /* static */ int Thread::GetCPUCount() { - return 1; + #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD) + // http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/sysctlbyname.3.html + int cpuCount = 0; + size_t len = sizeof(cpuCount); + + if(sysctlbyname("hw.logicalcpu", &cpuCount, &len, NULL, 0) != 0) + cpuCount = 1; + + return cpuCount; + + #else // Linux, Android + + // Alternative: read /proc/cpuinfo + #ifdef _SC_NPROCESSORS_ONLN + return (int)sysconf(_SC_NPROCESSORS_ONLN); + #else + return 1; + #endif + #endif } + +void Thread::SetThreadName( const char* name ) +{ + #if defined (OVR_OS_APPLE) + if(ThreadHandle == pthread_self()) + pthread_setname_np(name); + // Else there's nothing we can do. + #else + if(ThreadHandle != 0) + pthread_setname_np(ThreadHandle, name); + // Else we can possibly save this name and set it later when the thread starts. + #endif +} + + +void Thread::SetThreadName(const char* name, ThreadId threadId) +{ + #if defined (OVR_OS_APPLE) + if(pthread_equal((pthread_t)threadId, pthread_self())) + pthread_setname_np(name); + // Else there's no way to set the name of another thread. + #else + pthread_setname_np((pthread_t)threadId, name); + #endif } + +void Thread::SetCurrentThreadName(const char* name) +{ + #if defined (OVR_OS_APPLE) + pthread_setname_np(name); + #else + pthread_setname_np(pthread_self(), name); + #endif +} + + +void Thread::GetThreadName(char* name, size_t nameCapacity, ThreadId threadId) +{ + name[0] = 0; + pthread_getname_np((pthread_t)threadId, name, nameCapacity); +} + + +void Thread::GetCurrentThreadName(char* name, size_t nameCapacity) +{ + name[0] = 0; + pthread_getname_np(pthread_self(), name, nameCapacity); +} + + +} // namespace OVR + #endif // OVR_ENABLE_THREADS diff --git a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp index 91a5e31..4786435 100644 --- a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp +++ b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp @@ -6,16 +6,16 @@ Content : Windows specific thread-related (safe) functionality Created : September 19, 2012
Notes :
-Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
-Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+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.1
+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,
@@ -28,6 +28,7 @@ limitations under the License. #include "OVR_Threads.h"
#include "OVR_Hash.h"
#include "OVR_Log.h"
+#include "OVR_Timer.h"
#ifdef OVR_ENABLE_THREADS
@@ -67,7 +68,12 @@ MutexImpl::MutexImpl(bool recursive) {
Recursive = recursive;
LockCount = 0;
+#if defined(OVR_OS_WIN32) // Older versions of Windows don't support CreateSemaphoreEx, so stick with CreateSemaphore for portability.
hMutexOrSemaphore = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL);
+#else
+ // No CreateSemaphore() call, so emulate it.
+ hMutexOrSemaphore = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphoreEx(NULL, 1, 1, NULL, 0, SEMAPHORE_ALL_ACCESS);
+#endif
}
MutexImpl::~MutexImpl()
{
@@ -541,7 +547,7 @@ __declspec(thread) Thread* pCurrentThread = 0; // *** Thread constructors.
-Thread::Thread(UPInt stackSize, int processor)
+Thread::Thread(size_t stackSize, int processor)
{
CreateParams params;
params.stackSize = stackSize;
@@ -549,7 +555,7 @@ Thread::Thread(UPInt stackSize, int processor) Init(params);
}
-Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
+Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, size_t stackSize,
int processor, Thread::ThreadState initialState)
{
CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
@@ -597,9 +603,14 @@ Thread::~Thread() // Default Run implementation
int Thread::Run()
{
- // Call pointer to function, if available.
- return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
+ if (!ThreadFunction)
+ return 0;
+
+ int ret = ThreadFunction(this, UserHandle);
+
+ return ret;
}
+
void Thread::OnExit()
{
}
@@ -608,7 +619,7 @@ void Thread::OnExit() void Thread::FinishAndRelease()
{
// Note: thread must be US.
- ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
+ ThreadFlags &= (uint32_t)~(OVR_THREAD_STARTED);
ThreadFlags |= OVR_THREAD_FINISHED;
// Release our reference; this is equivalent to 'delete this'
@@ -624,9 +635,9 @@ class ThreadList : public NewOverrideBase //------------------------------------------------------------------------
struct ThreadHashOp
{
- UPInt operator()(const Thread* ptr)
+ size_t operator()(const Thread* ptr)
{
- return (((UPInt)ptr) >> 6) ^ (UPInt)ptr;
+ return (((size_t)ptr) >> 6) ^ (size_t)ptr;
}
};
@@ -722,11 +733,12 @@ int Thread::PRun() if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
{
Suspend();
- ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
+ ThreadFlags &= (uint32_t)~OVR_THREAD_START_SUSPENDED;
}
// Call the virtual run function
ExitCode = Run();
+
return ExitCode;
}
@@ -761,7 +773,7 @@ void Thread::SetExitFlag(bool exitFlag) if (exitFlag)
ThreadFlags |= OVR_THREAD_EXIT;
else
- ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
+ ThreadFlags &= (uint32_t) ~OVR_THREAD_EXIT;
}
@@ -779,12 +791,39 @@ bool Thread::IsSuspended() const Thread::ThreadState Thread::GetThreadState() const
{
if (IsSuspended())
- return Suspended;
+ return Suspended;
if (ThreadFlags & OVR_THREAD_STARTED)
- return Running;
+ return Running;
return NotRunning;
}
+// Join thread
+bool Thread::Join(int maxWaitMs) const
+{
+ // If polling,
+ if (maxWaitMs == 0)
+ {
+ // Just return if finished
+ return IsFinished();
+ }
+ // If waiting forever,
+ else if (maxWaitMs > 0)
+ {
+ // Try waiting once
+ WaitForSingleObject(ThreadHandle, maxWaitMs);
+ // Return if the wait succeeded
+ return IsFinished();
+ }
+
+ // While not finished,
+ while (!IsFinished())
+ {
+ // Wait for the thread handle to signal
+ WaitForSingleObject(ThreadHandle, INFINITE);
+ }
+
+ return true;
+}
// ***** Thread management
@@ -793,19 +832,79 @@ int Thread::GetOSPriority(ThreadPriority p) {
switch(p)
{
- case Thread::CriticalPriority: return THREAD_PRIORITY_TIME_CRITICAL;
- case Thread::HighestPriority: return THREAD_PRIORITY_HIGHEST;
- case Thread::AboveNormalPriority: return THREAD_PRIORITY_ABOVE_NORMAL;
- case Thread::NormalPriority: return THREAD_PRIORITY_NORMAL;
- case Thread::BelowNormalPriority: return THREAD_PRIORITY_BELOW_NORMAL;
- case Thread::LowestPriority: return THREAD_PRIORITY_LOWEST;
- case Thread::IdlePriority: return THREAD_PRIORITY_IDLE;
+ // If the process is REALTIME_PRIORITY_CLASS then it could have priority values 3 through14 and -3 through -14.
+ case Thread::CriticalPriority: return THREAD_PRIORITY_TIME_CRITICAL; // 15
+ case Thread::HighestPriority: return THREAD_PRIORITY_HIGHEST; // 2
+ case Thread::AboveNormalPriority: return THREAD_PRIORITY_ABOVE_NORMAL; // 1
+ case Thread::NormalPriority: return THREAD_PRIORITY_NORMAL; // 0
+ case Thread::BelowNormalPriority: return THREAD_PRIORITY_BELOW_NORMAL; // -1
+ case Thread::LowestPriority: return THREAD_PRIORITY_LOWEST; // -2
+ case Thread::IdlePriority: return THREAD_PRIORITY_IDLE; // -15
}
return THREAD_PRIORITY_NORMAL;
}
+/* static */
+Thread::ThreadPriority Thread::GetOVRPriority(int osPriority)
+{
+ // If the process is REALTIME_PRIORITY_CLASS then it could have priority values 3 through14 and -3 through -14.
+ // As a result, it's possible for those cases that an unknown/invalid ThreadPriority enum be returned. However,
+ // in practice we don't expect to be using such processes.
+
+ // The ThreadPriority types aren't linearly distributed, so we need to check for some values explicitly.
+ if(osPriority == THREAD_PRIORITY_TIME_CRITICAL)
+ return Thread::CriticalPriority;
+ if(osPriority == THREAD_PRIORITY_IDLE)
+ return Thread::IdlePriority;
+ return (ThreadPriority)(Thread::NormalPriority - osPriority);
+}
+
+Thread::ThreadPriority Thread::GetPriority()
+{
+ int osPriority = ::GetThreadPriority(ThreadHandle);
+
+ if(osPriority != THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return GetOVRPriority(osPriority);
+ }
+
+ return NormalPriority;
+}
+
+/* static */
+Thread::ThreadPriority Thread::GetCurrentPriority()
+{
+ int osPriority = ::GetThreadPriority(::GetCurrentThread());
+
+ if(osPriority != THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return GetOVRPriority(osPriority);
+ }
+
+ return NormalPriority;
+}
+
+bool Thread::SetPriority(ThreadPriority p)
+{
+ BOOL ret = ::SetThreadPriority(ThreadHandle, Thread::GetOSPriority(p));
+ return (ret != FALSE);
+}
+
+/* static */
+bool Thread::SetCurrentPriority(ThreadPriority p)
+{
+ BOOL ret = ::SetThreadPriority(::GetCurrentThread(), Thread::GetOSPriority(p));
+ return (ret != FALSE);
+}
+
+
+
// The actual first function called on thread start
+#if defined(OVR_OS_WIN32)
unsigned WINAPI Thread_Win32StartFn(void * phandle)
+#else // Other Micorosft OSs...
+DWORD WINAPI Thread_Win32StartFn(void *phandle)
+#endif
{
Thread * pthread = (Thread*)phandle;
if (pthread->Processor != -1)
@@ -852,8 +951,15 @@ bool Thread::Start(ThreadState initialState) ExitCode = 0;
SuspendCount = 0;
ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
+#if defined(OVR_OS_WIN32)
ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize,
Thread_Win32StartFn, this, 0, (unsigned*)&IdValue);
+#else // Other Micorosft OSs...
+ DWORD TheThreadId;
+ ThreadHandle = CreateThread(0, (unsigned)StackSize,
+ Thread_Win32StartFn, this, 0, &TheThreadId);
+ IdValue = (ThreadId)TheThreadId;
+#endif
// Failed? Fail the function
if (ThreadHandle == 0)
@@ -890,13 +996,15 @@ bool Thread::Resume() return 0;
// Decrement count, and resume thread if it is 0
- SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1);
+ int32_t oldCount = SuspendCount.ExchangeAdd_Acquire(-1);
if (oldCount >= 1)
{
if (oldCount == 1)
{
- if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF)
- return 1;
+ if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF)
+ {
+ return 1;
+ }
}
else
{
@@ -922,8 +1030,12 @@ void Thread::Exit(int exitCode) FinishAndRelease();
ThreadList::RemoveRunningThread(this);
- // Call the exit function.
+ // Call the exit function.
+#if defined(OVR_OS_WIN32) // _endthreadex doesn't exist on other Microsoft OSs and instead we need to call ExitThread directly.
_endthreadex((unsigned)exitCode);
+#else
+ ExitThread((unsigned)exitCode);
+#endif
}
@@ -951,43 +1063,74 @@ bool Thread::MSleep(unsigned msecs) return 1;
}
+
+
void Thread::SetThreadName( const char* name )
{
-#if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING)
- // Looks ugly, but it is the recommended way to name a thread.
- typedef struct tagTHREADNAME_INFO {
- DWORD dwType; // Must be 0x1000
- LPCSTR szName; // Pointer to name (in user address space)
- DWORD dwThreadID; // Thread ID (-1 for caller thread)
- DWORD dwFlags; // Reserved for future use; must be zero
- } THREADNAME_INFO;
+ if(IdValue)
+ SetThreadName(name, IdValue);
+ // Else we don't know what thread to name. We can save the name and wait until the thread is created.
+}
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = name;
- info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId());
- info.dwFlags = 0;
+void Thread::SetThreadName(const char* name, ThreadId threadId)
+{
+ #if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING)
+ // http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+ #pragma pack(push,8)
+ struct THREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000
+ LPCSTR szName; // Pointer to name (in user address space)
+ DWORD dwThreadID; // Thread ID (-1 for caller thread)
+ DWORD dwFlags; // Reserved for future use; must be zero
+ };
+ #pragma pack(pop)
+
+ THREADNAME_INFO info = { 0x1000, name, (DWORD)threadId, 0 };
+
+ __try
+ {
+ RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
+ }
+ __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER )
+ {
+ return;
+ }
+ #endif // OVR_BUILD_SHIPPING
+}
- __try
- {
-#ifdef _WIN64
- RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info );
-#else
- RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info );
-#endif
- }
- __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER )
- {
- }
-#endif // OVR_BUILD_SHIPPING
+
+void Thread::SetCurrentThreadName( const char* name )
+{
+ SetThreadName(name, (ThreadId)::GetCurrentThreadId());
+}
+
+
+void Thread::GetThreadName(char* name, size_t /*nameCapacity*/, ThreadId /*threadId*/)
+{
+ // Not possible on Windows.
+ name[0] = 0;
+}
+
+
+void Thread::GetCurrentThreadName(char* name, size_t /*nameCapacity*/)
+{
+ // Not possible on Windows.
+ name[0] = 0;
}
+
// static
int Thread::GetCPUCount()
{
SYSTEM_INFO sysInfo;
- GetSystemInfo(&sysInfo);
+
+ #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) // GetNativeSystemInfo requires WinXP+ and a corresponding SDK (0x0501) or later.
+ GetNativeSystemInfo(&sysInfo);
+ #else
+ GetSystemInfo(&sysInfo);
+ #endif
+
return (int) sysInfo.dwNumberOfProcessors;
}
@@ -1001,5 +1144,3 @@ ThreadId GetCurrentThreadId() } // OVR
#endif
-
-
diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp index a8de47d..3a75ec2 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.cpp +++ b/LibOVR/Src/Kernel/OVR_Timer.cpp @@ -5,16 +5,16 @@ Content : Provides static functions for precise timing Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -27,22 +27,61 @@ limitations under the License. #include "OVR_Timer.h" #include "OVR_Log.h" -#if defined (OVR_OS_WIN32) +#if defined(OVR_OS_MS) && !defined(OVR_OS_MS_MOBILE) +#define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <MMSystem.h> #elif defined(OVR_OS_ANDROID) #include <time.h> #include <android/log.h> - +#elif defined(OVR_OS_MAC) +#include <mach/mach_time.h> #else +#include <time.h> #include <sys/time.h> +#include <errno.h> +#endif + + +#if defined(OVR_BUILD_DEBUG) && defined(OVR_OS_WIN32) + #ifndef NTSTATUS + #define NTSTATUS DWORD + #endif + + typedef NTSTATUS (NTAPI* NtQueryTimerResolutionType)(PULONG MaximumTime, PULONG MinimumTime, PULONG CurrentTime); + NtQueryTimerResolutionType pNtQueryTimerResolution; #endif + + +#if defined(OVR_OS_MS) && !defined(OVR_OS_WIN32) // Non-desktop Microsoft platforms... + +// Add this alias here because we're not going to include OVR_CAPI.cpp +extern "C" { + double ovr_GetTimeInSeconds() + { + return Timer::GetSeconds(); + } +} + +#endif + + + + namespace OVR { // For recorded data playback -bool Timer::useFakeSeconds = false; -double Timer::FakeSeconds = 0; +bool Timer::useFakeSeconds = false; +double Timer::FakeSeconds = 0; + + + +//------------------------------------------------------------------------ +// *** Android Specific Timer + +#if defined(OVR_OS_ANDROID) // To consider: This implementation can also work on most Linux distributions //------------------------------------------------------------------------ // *** Timer - Platform Independent functions @@ -53,51 +92,65 @@ double Timer::GetSeconds() if(useFakeSeconds) return FakeSeconds; - return double(Timer::GetTicksNanos()) * 0.000000001; -} - - -#ifndef OVR_OS_WIN32 - -// Unused on OSs other then Win32. -void Timer::initializeTimerSystem() -{ -} -void Timer::shutdownTimerSystem() -{ -} + // Choreographer vsync timestamp is based on. + struct timespec tp; + const int status = clock_gettime(CLOCK_MONOTONIC, &tp); +#ifdef OVR_BUILD_DEBUG + if (status != 0) + { + OVR_DEBUG_LOG(("clock_gettime status=%i", status )); + } +#else + OVR_UNUSED(status); #endif + return (double)tp.tv_sec; +} -//------------------------------------------------------------------------ -// *** Android Specific Timer - -#if defined(OVR_OS_ANDROID) -UInt64 Timer::GetTicksNanos() +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); // Choreographer vsync timestamp is based on. struct timespec tp; const int status = clock_gettime(CLOCK_MONOTONIC, &tp); +#ifdef OVR_BUILD_DEBUG if (status != 0) { OVR_DEBUG_LOG(("clock_gettime status=%i", status )); } - const UInt64 result = (UInt64)tp.tv_sec * (UInt64)(1000 * 1000 * 1000) + UInt64(tp.tv_nsec); +#else + OVR_UNUSED(status); +#endif + + const uint64_t result = (uint64_t)tp.tv_sec * (uint64_t)(1000 * 1000 * 1000) + uint64_t(tp.tv_nsec); return result; } +void Timer::initializeTimerSystem() +{ + // Empty for this platform. +} + +void Timer::shutdownTimerSystem() +{ + // Empty for this platform. +} + + + + + //------------------------------------------------------------------------ // *** Win32 Specific Timer -#elif defined (OVR_OS_WIN32) +#elif defined (OVR_OS_MS) // This helper class implements high-resolution wrapper that combines timeGetTime() output @@ -106,8 +159,15 @@ UInt64 Timer::GetTicksNanos() struct PerformanceTimer { PerformanceTimer() - : OldMMTimeMs(0), MMTimeWrapCounter(0), PrefFrequency(0), - LastResultNanos(0), PerfMinusTicksDeltaNanos(0) + : UsingVistaOrLater(false), + TimeCS(), + OldMMTimeMs(0), + MMTimeWrapCounter(0), + PerfFrequency(0), + PerfFrequencyInverse(0), + PerfFrequencyInverseNanos(0), + PerfMinusTicksDeltaNanos(0), + LastResultNanos(0) { } enum { @@ -117,168 +177,372 @@ struct PerformanceTimer void Initialize(); void Shutdown(); - UInt64 GetTimeNanos(); - + uint64_t GetTimeSeconds(); + double GetTimeSecondsDouble(); + uint64_t GetTimeNanos(); UINT64 getFrequency() { - if (PrefFrequency == 0) + if (PerfFrequency == 0) { LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); - PrefFrequency = freq.QuadPart; + PerfFrequency = freq.QuadPart; + PerfFrequencyInverse = 1.0 / (double)PerfFrequency; + PerfFrequencyInverseNanos = 1000000000.0 / (double)PerfFrequency; } - return PrefFrequency; + return PerfFrequency; } + double GetFrequencyInverse() + { + OVR_ASSERT(PerfFrequencyInverse != 0.0); // Assert that the frequency has been initialized. + return PerfFrequencyInverse; + } + + bool UsingVistaOrLater; CRITICAL_SECTION TimeCS; // timeGetTime() support with wrap. - UInt32 OldMMTimeMs; - UInt32 MMTimeWrapCounter; + uint32_t OldMMTimeMs; + uint32_t MMTimeWrapCounter; // Cached performance frequency result. - UInt64 PrefFrequency; + uint64_t PerfFrequency; // cycles per second, typically a large value like 3000000, but usually not the same as the CPU clock rate. + double PerfFrequencyInverse; // seconds per cycle (will be a small fractional value). + double PerfFrequencyInverseNanos; // nanoseconds per cycle. // Computed as (perfCounterNanos - ticksCounterNanos) initially, // and used to adjust timing. - UInt64 PerfMinusTicksDeltaNanos; + uint64_t PerfMinusTicksDeltaNanos; // Last returned value in nanoseconds, to ensure we don't back-step in time. - UInt64 LastResultNanos; + uint64_t LastResultNanos; }; -PerformanceTimer Win32_PerfTimer; +static PerformanceTimer Win32_PerfTimer; void PerformanceTimer::Initialize() { - timeBeginPeriod(1); + #if defined(OVR_OS_WIN32) // Desktop Windows only + // The following has the effect of setting the NT timer resolution (NtSetTimerResolution) to 1 millisecond. + MMRESULT mmr = timeBeginPeriod(1); + OVR_ASSERT(TIMERR_NOERROR == mmr); + OVR_UNUSED(mmr); + #endif + InitializeCriticalSection(&TimeCS); MMTimeWrapCounter = 0; getFrequency(); + + #if defined(OVR_OS_WIN32) // Desktop Windows only + // Set Vista flag. On Vista, we can just use QPC() without all the extra work + OSVERSIONINFOEX ver; + ZeroMemory(&ver, sizeof(OSVERSIONINFOEX)); + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ver.dwMajorVersion = 6; // Vista+ + + DWORDLONG condMask = 0; + VER_SET_CONDITION(condMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + + // VerifyVersionInfo returns true if the OS meets the conditions set above + UsingVistaOrLater = VerifyVersionInfo(&ver, VER_MAJORVERSION, condMask) != 0; + #else + UsingVistaOrLater = true; + #endif + + OVR_DEBUG_LOG(("PerformanceTimer UsingVistaOrLater = %d", (int)UsingVistaOrLater)); + + #if defined(OVR_BUILD_DEBUG) && defined(OVR_OS_WIN32) + HMODULE hNtDll = LoadLibrary(L"NtDll.dll"); + if (hNtDll) + { + pNtQueryTimerResolution = (NtQueryTimerResolutionType)GetProcAddress(hNtDll, "NtQueryTimerResolution"); + //pNtSetTimerResolution = (NtSetTimerResolutionType)GetProcAddress(hNtDll, "NtSetTimerResolution"); + + if(pNtQueryTimerResolution) + { + ULONG MinimumResolution; // in 100-ns units + ULONG MaximumResolution; + ULONG ActualResolution; + pNtQueryTimerResolution(&MinimumResolution, &MaximumResolution, &ActualResolution); + OVR_DEBUG_LOG(("NtQueryTimerResolution = Min %ld us, Max %ld us, Current %ld us", MinimumResolution / 10, MaximumResolution / 10, ActualResolution / 10)); + } + + FreeLibrary(hNtDll); + } + #endif } void PerformanceTimer::Shutdown() { DeleteCriticalSection(&TimeCS); - timeEndPeriod(1); + + #if defined(OVR_OS_WIN32) // Desktop Windows only + MMRESULT mmr = timeEndPeriod(1); + OVR_ASSERT(TIMERR_NOERROR == mmr); + OVR_UNUSED(mmr); + #endif } -UInt64 PerformanceTimer::GetTimeNanos() -{ - UInt64 resultNanos; - LARGE_INTEGER li; - DWORD mmTimeMs; - - // On Win32 QueryPerformanceFrequency is unreliable due to SMP and - // performance levels, so use this logic to detect wrapping and track - // high bits. - ::EnterCriticalSection(&TimeCS); - - // Get raw value and perf counter "At the same time". - mmTimeMs = timeGetTime(); - QueryPerformanceCounter(&li); - - if (OldMMTimeMs > mmTimeMs) - MMTimeWrapCounter++; - OldMMTimeMs = mmTimeMs; - - // Normalize to nanoseconds. - UInt64 mmCounterNanos = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000; - UInt64 frequency = getFrequency(); - UInt64 perfCounterSeconds = UInt64(li.QuadPart) / frequency; - UInt64 perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) * - Timer::NanosPerSecond ) / frequency; - UInt64 perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos; - - if (PerfMinusTicksDeltaNanos == 0) - PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos; - - // Compute result before snapping. - // - // On first call, this evaluates to: - // resultNanos = mmCounterNanos. - // Next call, assuming no wrap: - // resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos). - // After wrap, this would be: - // resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos). - // - resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos; - - // Snap the range so that resultNanos never moves further apart then its target resolution. - // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically - // larger then 1 ms intervals even when 1 ms resolution is requested. - if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2)) - { - resultNanos = mmCounterNanos + MMTimerResolutionNanos*2; - if (resultNanos < LastResultNanos) - resultNanos = LastResultNanos; - PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos; +uint64_t PerformanceTimer::GetTimeSeconds() +{ + if (UsingVistaOrLater) + { + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + OVR_ASSERT(PerfFrequencyInverse != 0); // Initialize should have been called earlier. + return (uint64_t)(li.QuadPart * PerfFrequencyInverse); } - else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos)) - { - resultNanos = mmCounterNanos - MMTimerResolutionNanos; - if (resultNanos < LastResultNanos) - resultNanos = LastResultNanos; - PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos; + + return (uint64_t)(GetTimeNanos() * .0000000001); +} + + +double PerformanceTimer::GetTimeSecondsDouble() +{ + if (UsingVistaOrLater) + { + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + OVR_ASSERT(PerfFrequencyInverse != 0); + return (li.QuadPart * PerfFrequencyInverse); } - LastResultNanos = resultNanos; - ::LeaveCriticalSection(&TimeCS); + return (GetTimeNanos() * .0000000001); +} - //Tom's addition, to keep precision - static UInt64 initial_time = 0; - if (!initial_time) initial_time = resultNanos; - resultNanos -= initial_time; +uint64_t PerformanceTimer::GetTimeNanos() +{ + uint64_t resultNanos; + LARGE_INTEGER li; + + OVR_ASSERT(PerfFrequencyInverseNanos != 0); // Initialize should have been called earlier. + + if (UsingVistaOrLater) // Includes non-desktop platforms + { + // Then we can use QPC() directly without all that extra work + QueryPerformanceCounter(&li); + resultNanos = (uint64_t)(li.QuadPart * PerfFrequencyInverseNanos); + } + else + { + // On Win32 QueryPerformanceFrequency is unreliable due to SMP and + // performance levels, so use this logic to detect wrapping and track + // high bits. + ::EnterCriticalSection(&TimeCS); + + // Get raw value and perf counter "At the same time". + QueryPerformanceCounter(&li); + + DWORD mmTimeMs = timeGetTime(); + if (OldMMTimeMs > mmTimeMs) + MMTimeWrapCounter++; + OldMMTimeMs = mmTimeMs; + + // Normalize to nanoseconds. + uint64_t perfCounterNanos = (uint64_t)(li.QuadPart * PerfFrequencyInverseNanos); + uint64_t mmCounterNanos = ((uint64_t(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000; + if (PerfMinusTicksDeltaNanos == 0) + PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos; + + // Compute result before snapping. + // + // On first call, this evaluates to: + // resultNanos = mmCounterNanos. + // Next call, assuming no wrap: + // resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos). + // After wrap, this would be: + // resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos). + // + resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos; + + // Snap the range so that resultNanos never moves further apart then its target resolution. + // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically + // larger then 1 ms intervals even when 1 ms resolution is requested. + if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2)) + { + resultNanos = mmCounterNanos + MMTimerResolutionNanos*2; + if (resultNanos < LastResultNanos) + resultNanos = LastResultNanos; + PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos; + } + else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos)) + { + resultNanos = mmCounterNanos - MMTimerResolutionNanos; + if (resultNanos < LastResultNanos) + resultNanos = LastResultNanos; + PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos; + } + + LastResultNanos = resultNanos; + ::LeaveCriticalSection(&TimeCS); + } + + //Tom's addition, to keep precision + //static uint64_t initial_time = 0; + //if (!initial_time) initial_time = resultNanos; + //resultNanos -= initial_time; + // FIXME: This cannot be used for cross-process timestamps return resultNanos; } +//------------------------------------------------------------------------ +// *** Timer - Platform Independent functions + +// Returns global high-resolution application timer in seconds. +double Timer::GetSeconds() +{ + if(useFakeSeconds) + return FakeSeconds; + + return Win32_PerfTimer.GetTimeSecondsDouble(); +} + + + // Delegate to PerformanceTimer. -UInt64 Timer::GetTicksNanos() +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); return Win32_PerfTimer.GetTimeNanos(); } void Timer::initializeTimerSystem() { Win32_PerfTimer.Initialize(); - } void Timer::shutdownTimerSystem() { Win32_PerfTimer.Shutdown(); } -#else // !OVR_OS_WIN32 && !OVR_OS_ANDROID + + +#elif defined(OVR_OS_MAC) + + +double Timer::TimeConvertFactorNanos = 0.0; +double Timer::TimeConvertFactorSeconds = 0.0; //------------------------------------------------------------------------ // *** Standard OS Timer -UInt64 Timer::GetTicksNanos() +// Returns global high-resolution application timer in seconds. +double Timer::GetSeconds() +{ + if(useFakeSeconds) + return FakeSeconds; + + OVR_ASSERT(TimeConvertFactorNanos != 0.0); + return (double)mach_absolute_time() * TimeConvertFactorNanos; +} + + +uint64_t Timer::GetTicksNanos() +{ + if (useFakeSeconds) + return (uint64_t) (FakeSeconds * NanosPerSecond); + + OVR_ASSERT(TimeConvertFactorSeconds != 0.0); + return (uint64_t)(mach_absolute_time() * TimeConvertFactorSeconds); +} + +void Timer::initializeTimerSystem() +{ + mach_timebase_info_data_t timeBase; + mach_timebase_info(&timeBase); + TimeConvertFactorSeconds = ((double)timeBase.numer / (double)timeBase.denom); + TimeConvertFactorNanos = TimeConvertFactorSeconds / 1000000000.0; +} + +void Timer::shutdownTimerSystem() +{ + // Empty for this platform. +} + + +#else // Posix platforms (e.g. Linux, BSD Unix) + + +bool Timer::MonotonicClockAvailable = false; + + +// Returns global high-resolution application timer in seconds. +double Timer::GetSeconds() +{ + if(useFakeSeconds) + return FakeSeconds; + + // http://linux/die/netman3/clock_gettime + #if defined(CLOCK_MONOTONIC) // If we can use clock_gettime, which has nanosecond precision... + if(MonotonicClockAvailable) + { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); // Better to use CLOCK_MONOTONIC than CLOCK_REALTIME. + return static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec) / 1E9; + } + #endif + + // We cannot use rdtsc because its frequency changes at runtime. + struct timeval tv; + gettimeofday(&tv, 0); + + return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1E6; +} + + +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); + + #if defined(CLOCK_MONOTONIC) // If we can use clock_gettime, which has nanosecond precision... + if(MonotonicClockAvailable) + { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((uint64_t)ts.tv_sec * 1000000000ULL) + (uint64_t)ts.tv_nsec; + } + #endif - // TODO: prefer rdtsc when available? - UInt64 result; + + // We cannot use rdtsc because its frequency changes at runtime. + uint64_t result; // Return microseconds. struct timeval tv; gettimeofday(&tv, 0); - result = (UInt64)tv.tv_sec * 1000000; + result = (uint64_t)tv.tv_sec * 1000000; result += tv.tv_usec; return result * 1000; } + +void Timer::initializeTimerSystem() +{ + #if defined(CLOCK_MONOTONIC) + timespec ts; // We could also check for the availability of CLOCK_MONOTONIC with sysconf(_SC_MONOTONIC_CLOCK) + int result = clock_gettime(CLOCK_MONOTONIC, &ts); + MonotonicClockAvailable = (result == 0); + #endif +} + +void Timer::shutdownTimerSystem() +{ + // Empty for this platform. +} + + + #endif // OS-specific diff --git a/LibOVR/Src/Kernel/OVR_Timer.h b/LibOVR/Src/Kernel/OVR_Timer.h index 12cba3b..6c8dbb7 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.h +++ b/LibOVR/Src/Kernel/OVR_Timer.h @@ -6,16 +6,16 @@ Content : Provides static functions for precise timing Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -42,9 +42,9 @@ class Timer { public: enum { - MsPerSecond = 1000, // Milliseconds in one second. - NanosPerSecond = MsPerSecond * 1000 * 1000, - MksPerSecond = MsPerSecond * 1000 + MsPerSecond = 1000, // Milliseconds in one second. + MksPerSecond = 1000 * 1000, // Microseconds in one second. + NanosPerSecond = 1000 * 1000 * 1000, // Nanoseconds in one second. }; // ***** Timing APIs for Application @@ -56,19 +56,19 @@ public: static double OVR_STDCALL GetSeconds(); // Returns time in Nanoseconds, using highest possible system resolution. - static UInt64 OVR_STDCALL GetTicksNanos(); + static uint64_t OVR_STDCALL GetTicksNanos(); // Kept for compatibility. // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 49.2 days. // Use either time difference of two values of GetTicks to avoid wrap-around. - static UInt32 OVR_STDCALL GetTicksMs() - { return UInt32(GetTicksNanos() / 1000000); } + static uint32_t OVR_STDCALL GetTicksMs() + { return uint32_t(GetTicksNanos() / 1000000); } // for recorded data playback - static void SetFakeSeconds(double fakeSeconds) + static void SetFakeSeconds(double fakeSeconds, bool enable = true) { FakeSeconds = fakeSeconds; - useFakeSeconds = true; + useFakeSeconds = enable; } private: @@ -79,7 +79,18 @@ private: // for recorded data playback static double FakeSeconds; - static bool useFakeSeconds; + static bool useFakeSeconds; + + #if defined(OVR_OS_ANDROID) + // Android-specific data + #elif defined (OVR_OS_MS) + // Microsoft-specific data + #elif defined(OVR_OS_MAC) + static double TimeConvertFactorNanos; // Conversion factor for GetTicksNanos + static double TimeConvertFactorSeconds; // Conversion factor for GetSeconds. + #else + static bool MonotonicClockAvailable; // True if clock_gettime supports CLOCK_MONOTONIC + #endif }; diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h index 8f2b3f3..d42d131 100644 --- a/LibOVR/Src/Kernel/OVR_Types.h +++ b/LibOVR/Src/Kernel/OVR_Types.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Types.h Content : Standard library defines and simple types Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -28,16 +28,42 @@ limitations under the License. #ifndef OVR_Types_H #define OVR_Types_H +#include "OVR_Compiler.h" + + +// Unsupported compiler configurations +#if _MSC_VER == 0x1600 +# if _MSC_FULL_VER < 160040219 +# error "Oculus does not support VS2010 without SP1 installed: It will crash in Release mode" +# endif +#endif + + //----------------------------------------------------------------------------------- -// ****** Operating System +// ****** Operating system identification +// +// Try to use the most generic version of these defines as possible in order to achieve +// the simplest portable code. For example, instead of using #if (defined(OVR_OS_IPHONE) || defined(OVR_OS_MAC)), +// consider using #if defined(OVR_OS_APPLE). // // Type definitions exist for the following operating systems: (OVR_OS_x) // -// WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) -// DARWIN - Darwin OS (Mac OS X) -// LINUX - Linux -// ANDROID - Android -// IPHONE - iPhone +// WIN32 - Win32 and Win64 (Windows XP and later) Does not include Microsoft phone and console platforms, despite that Microsoft's _WIN32 may be defined by the compiler for them. +// WIN64 - Win64 (Windows XP and later) +// MAC - Mac OS X (may be defined in addition to BSD) +// LINUX - Linux +// BSD - BSD Unix +// ANDROID - Android (may be defined in addition to LINUX) +// IPHONE - iPhone +// MS_MOBILE - Microsoft mobile OS. +// +// Meta platforms +// MS - Any OS by Microsoft (e.g. Win32, Win64, phone, console) +// APPLE - Any OS by Apple (e.g. iOS, OS X) +// UNIX - Linux, BSD, Mac OS X. +// MOBILE - iOS, Android, Microsoft phone +// CONSOLE - Console platforms +// #if (defined(__APPLE__) && (defined(__GNUC__) ||\ defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__) @@ -46,22 +72,57 @@ limitations under the License. # else # define OVR_OS_DARWIN # define OVR_OS_MAC +# define OVR_OS_BSD # endif #elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) -# define OVR_OS_WIN32 +# define OVR_OS_WIN64 +# define OVR_OS_WIN32 // Defined for compatibility and because the Win64 API supports the Win32 API. #elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) # define OVR_OS_WIN32 +#elif defined(ANDROID) || defined(__ANDROID__) +# define OVR_OS_ANDROID +# define OVR_OS_LINUX #elif defined(__linux__) || defined(__linux) # define OVR_OS_LINUX +#elif defined(_BSD_) || defined(__FreeBSD__) +# define OVR_OS_BSD #else # define OVR_OS_OTHER #endif -#if defined(ANDROID) -# define OVR_OS_ANDROID +#if !defined(OVR_OS_MS_MOBILE) +# if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_AMD64)) && !defined(OVR_OS_WIN32) && !defined(OVR_OS_CONSOLE) +# define OVR_OS_MS_MOBILE +# endif +#endif + +#if !defined(OVR_OS_MS) +# if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64) || defined(OVR_OS_MS_MOBILE) +# define OVR_OS_MS +# endif +#endif + +#if !defined(OVR_OS_APPLE) +# if defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) +# define OVR_OS_APPLE +# endif +#endif + +#if !defined(OVR_OS_UNIX) +# if defined(OVR_OS_ANDROID) || defined(OVR_OS_BSD) || defined(OVR_OS_LINUX) || defined(OVR_OS_MAC) +# define OVR_OS_UNIX +# endif +#endif + +#if !defined(OVR_OS_MOBILE) +# if defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE) || defined(OVR_OS_MS_MOBILE) +# define OVR_OS_MOBILE +# endif #endif + + //----------------------------------------------------------------------------------- // ***** CPU Architecture // @@ -75,7 +136,7 @@ limitations under the License. // OTHER - CPU for which no special support is present or needed -#if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +#if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(_M_AMD64) # define OVR_CPU_X86_64 # define OVR_64BIT_POINTERS #elif defined(__i386__) || defined(OVR_OS_WIN32) @@ -101,7 +162,7 @@ limitations under the License. // Altivec - Available on all modern ppc processors. // Neon - Available on some armv7+ processors. -#if defined(__SSE__) || defined(OVR_OS_WIN32) +#if defined(__SSE__) || defined(_M_IX86) || defined(_M_AMD64) // _M_IX86 and _M_AMD64 are Microsoft identifiers for Intel-based platforms. # define OVR_CPU_SSE #endif // __SSE__ @@ -115,47 +176,6 @@ limitations under the License. //----------------------------------------------------------------------------------- -// ***** Compiler -// -// The following compilers are defined: (OVR_CC_x) -// -// MSVC - Microsoft Visual C/C++ -// INTEL - Intel C++ for Linux / Windows -// GNU - GNU C++ -// ARM - ARM C/C++ - -#if defined(__INTEL_COMPILER) -// Intel 4.0 = 400 -// Intel 5.0 = 500 -// Intel 6.0 = 600 -// Intel 8.0 = 800 -// Intel 9.0 = 900 -# define OVR_CC_INTEL __INTEL_COMPILER - -#elif defined(_MSC_VER) -// MSVC 5.0 = 1100 -// MSVC 6.0 = 1200 -// MSVC 7.0 (VC2002) = 1300 -// MSVC 7.1 (VC2003) = 1310 -// MSVC 8.0 (VC2005) = 1400 -// MSVC 9.0 (VC2008) = 1500 -// MSVC 10.0 (VC2010) = 1600 -// MSVC 11.0 (VC2012) = 1700 -// MSVC 12.0 (VC2013) = 1800 -# define OVR_CC_MSVC _MSC_VER - -#elif defined(__GNUC__) -# define OVR_CC_GNU - -#elif defined(__CC_ARM) -# define OVR_CC_ARM - -#else -# error "Oculus does not support this Compiler" -#endif - - -//----------------------------------------------------------------------------------- // ***** Compiler Warnings // Disable MSVC warnings @@ -194,16 +214,23 @@ limitations under the License. # define _CRTDBG_MAP_ALLOC # include <stdlib.h> # include <crtdbg.h> - -#if 0 -// Uncomment this to help debug memory leaks under Visual Studio in OVR apps only. -// This shouldn't be defined in customer releases. -# ifndef OVR_DEFINE_NEW -# define OVR_DEFINE_NEW new(__FILE__, __LINE__) -# define new OVR_DEFINE_NEW -# endif #endif + +//----------------------------------------------------------------------------------- +// ***** int8_t, int16_t, etc. + +#if defined(OVR_CC_MSVC) && (OVR_CC_VER <= 1500) // VS2008 and earlier + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; +#else + #include <stdint.h> #endif @@ -219,7 +246,7 @@ typedef size_t UPInt; typedef ptrdiff_t SPInt; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) typedef char SByte; // 8 bit Integer (Byte) typedef unsigned char UByte; @@ -255,33 +282,60 @@ typedef int64_t SInt64; typedef uint64_t UInt64; #endif + + +//osx PID is a signed int32 (already defined to pid_t in OSX framework) +//linux PID is a signed int32 (already defined) +//win32 PID is an unsigned int64 +#ifdef OVR_OS_WIN32 +//process ID representation +typedef unsigned long pid_t; +#endif +struct OVR_GUID +{ + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +}; -// ***** BaseTypes Namespace -// BaseTypes namespace is explicitly declared to allow base types to be used -// by customers directly without other contents of OVR namespace. -// -// Its is expected that OVR samples will declare 'using namespace OVR::BaseTypes' -// to allow using these directly without polluting the target scope with other -// OVR declarations, such as Ptr<>, String or Mutex. -namespace BaseTypes -{ - using OVR::UPInt; - using OVR::SPInt; - using OVR::UByte; - using OVR::SByte; - using OVR::UInt16; - using OVR::SInt16; - using OVR::UInt32; - using OVR::SInt32; - using OVR::UInt64; - using OVR::SInt64; -} // OVR::BaseTypes } // OVR + +//----------------------------------------------------------------------------------- +// ****** Standard C/C++ Library +// +// Identifies which standard library is currently being used. +// +// LIBSTDCPP - GNU libstdc++, used by GCC. +// LIBCPP - LLVM libc++, typically used by clang and GCC. +// DINKUMWARE - Used by Microsoft and various non-Microsoft compilers (e.g. Sony clang). + +#if !defined(OVR_STDLIB_LIBSTDCPP) + #if defined(__GLIBCXX__) + #define OVR_STDLIB_LIBSTDCPP 1 + #endif +#endif + +#if !defined(OVR_STDLIB_LIBCPP) + #if defined(__clang__) + #if defined(__cplusplus) && __has_include(<__config>) + #define OVR_STDLIB_LIBCPP 1 + #endif + #endif +#endif + +#if !defined(OVR_STDLIB_DINKUMWARE) + #if defined(_YVALS) // Dinkumware globally #defines _YVALS from the #includes above. + #define OVR_STDLIB_DINKUMWARE 1 + #endif +#endif + + //----------------------------------------------------------------------------------- // ***** Macro Definitions // @@ -302,19 +356,9 @@ namespace BaseTypes #define OVR_BIG_ENDIAN 2 -// Force inline substitute - goes before function declaration -#if defined(OVR_CC_MSVC) -# define OVR_FORCE_INLINE __forceinline -#elif defined(OVR_CC_GNU) -# define OVR_FORCE_INLINE __attribute__((always_inline)) inline -#else -# define OVR_FORCE_INLINE inline -#endif // OVR_CC_MSVC - - -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_MS) - // ***** Win32 + // ***** Windows and non-desktop platforms // Byte order #define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN @@ -369,56 +413,415 @@ namespace BaseTypes #endif // defined(OVR_OS_WIN32) +//----------------------------------------------------------------------------------- +// ***** OVR_PTR_SIZE +// +// Specifies the byte size of pointers (same as sizeof void*). + +#if !defined(OVR_PTR_SIZE) + #if defined(__WORDSIZE) + #define OVR_PTR_SIZE ((__WORDSIZE) / 8) + #elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__64BIT__) || defined(__Ptr_Is_64) + #define OVR_PTR_SIZE 8 + #elif defined(__CC_ARM) && (__sizeof_ptr == 8) + #define OVR_PTR_SIZE 8 + #else + #define OVR_PTR_SIZE 4 + #endif +#endif + //----------------------------------------------------------------------------------- -// ***** OVR_DEBUG_BREAK, OVR_ASSERT +// ***** OVR_WORD_SIZE +// +// Specifies the byte size of a machine word/register. Not necessarily the same as +// the size of pointers, but usually >= the size of pointers. + +#if !defined(OVR_WORD_SIZE) + #define OVR_WORD_SIZE OVR_PTR_SIZE // For our currently supported platforms these are equal. +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_FORCE_INLINE // -// If not in debug build, macros do nothing -#ifndef OVR_BUILD_DEBUG +// Force inline substitute - goes before function declaration +// Example usage: +// OVR_FORCE_INLINE void Test(); -# define OVR_DEBUG_CODE(c) c -# define OVR_DEBUG_BREAK ((void)0) -# define OVR_ASSERT(p) ((void)0) +#if !defined(OVR_FORCE_INLINE) + #if defined(OVR_CC_MSVC) + #define OVR_FORCE_INLINE __forceinline + #elif defined(OVR_CC_GNU) + #define OVR_FORCE_INLINE __attribute__((always_inline)) inline + #else + #define OVR_FORCE_INLINE inline + #endif // OVR_CC_MSVC +#endif -#else -// Microsoft Win32 specific debugging support -#if defined(OVR_OS_WIN32) -# ifdef OVR_CPU_X86 -# if defined(__cplusplus_cli) -# define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) -# elif defined(OVR_CC_GNU) -# define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) -# else -# define OVR_DEBUG_BREAK do { OVR_ASM int 3 } while (0) -# endif -# else -# define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) -# endif -// Unix specific debugging support -#elif defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) -# define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) +// ------------------------------------------------------------------------ +// ***** OVR_NO_INLINE +// +// Cannot be used with inline or OVR_FORCE_INLINE. +// Example usage: +// OVR_NO_INLINE void Test(); + +#if !defined(OVR_NO_INLINE) + #if defined(OVR_CC_MSVC) && (_MSC_VER >= 1500) // VS2008+ + #define OVR_NO_INLINE __declspec(noinline) + #elif !defined(OVR_CC_MSVC) + #define OVR_NO_INLINE __attribute__((noinline)) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_STRINGIZE +// +// Converts a preprocessor symbol to a string. +// +// Example usage: +// printf("Line: %s", OVR_STRINGIZE(__LINE__)); +// +#if !defined(OVR_STRINGIFY) + #define OVR_STRINGIZEIMPL(x) #x + #define OVR_STRINGIZE(x) OVR_STRINGIZEIMPL(x) +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_JOIN +// +// Joins two preprocessing symbols together. Supports the case when either or the +// the symbols are macros themselves. +// +// Example usage: +// char OVR_JOIN(unique_, __LINE__); // Results in (e.g.) char unique_123; +// +#if !defined(OVR_JOIN) + #define OVR_JOIN(a, b) OVR_JOIN1(a, b) + #define OVR_JOIN1(a, b) OVR_JOIN2(a, b) + #define OVR_JOIN2(a, b) a##b +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_OFFSETOF +// +// Portable implementation of offsetof for structs and classes. offsetof and GCC's +// __builtin_offsetof work only with POD types (standard-layout types under C++11), +// despite that it can safely work with a number of types that aren't POD. This +// version works with more types without generating compiler warnings or errors. +// Returns the offset as a size_t, as per offsetof. +// +// Example usage: +// struct Test{ int i; float f; }; +// size_t fPos = OVR_OFFSETOF(Test, f); + +#if defined(OVR_CC_GNU) + #define OVR_OFFSETOF(class_, member_) ((size_t)(((uintptr_t)&reinterpret_cast<const volatile char&>((((class_*)65536)->member_))) - 65536)) +#else + #define OVR_OFFSETOF(class_, member_) offsetof(class_, member_) +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_SIZEOF_MEMBER +// +// Implements a portable way to determine the size of struct or class data member. +// C++11 allows this directly via sizeof (see OVR_CPP_NO_EXTENDED_SIZEOF), and this +// macro exists to handle pre-C++11 compilers. +// Returns the offset as a size_t, as per sizeof. +// +// Example usage: +// struct Test{ int i; float f; }; +// size_t fSize = OVR_SIZEOF_MEMBER(Test, f); +// +#if defined(OVR_CPP_NO_EXTENDED_SIZEOF) + #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(((class_*)0)->member_)) #else -# define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0) + #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(class_::member_)) #endif -#define OVR_DEBUG_CODE(c) -// This will cause compiler breakpoint -#define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; } } while(0) +//----------------------------------------------------------------------------------- +// ***** OVR_DEBUG_BREAK, OVR_DEBUG_CODE, +// OVR_ASSERT, OVR_ASSERT_M, OVR_ASSERT_AND_UNUSED +// +// Macros have effect only in debug builds. +// +// Example OVR_DEBUG_BREAK usage (note the lack of parentheses): +// #define MY_ASSERT(expression) do { if (!(expression)) { OVR_DEBUG_BREAK; } } while(0) +// +// Example OVR_DEBUG_CODE usage: +// OVR_DEBUG_CODE(printf("debug test\n");) +// or +// OVR_DEBUG_CODE(printf("debug test\n")); +// +// Example OVR_ASSERT usage: +// OVR_ASSERT(count < 100); +// OVR_ASSERT_M(count < 100, "count is too high"); +// +#if defined(OVR_BUILD_DEBUG) + // Causes a debugger breakpoint in debug builds. Has no effect in release builds. + // Microsoft Win32 specific debugging support + #if defined(OVR_CC_MSVC) + #define OVR_DEBUG_BREAK __debugbreak() + #elif defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + #define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) + #else + #define OVR_DEBUG_BREAK __builtin_trap() + #endif + #else + #define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0) + #endif + + // The expresssion is defined only in debug builds. It is defined away in release builds. + #define OVR_DEBUG_CODE(c) c + + // In debug builds this tests the given expression; if false then executes OVR_DEBUG_BREAK, + // if true then no action. Has no effect in release builds. + #if defined(__clang_analyzer__) // During static analysis, make it so the analyzer thinks that failed asserts result in program exit. Reduced false positives. + #include <stdlib.h> + #define OVR_ASSERT_M(p, message) do { if (!(p)) { OVR_DEBUG_BREAK; exit(0); } } while(0) + #define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; exit(0); } } while(0) + #else + // void OVR_ASSERT_M(bool expression, const char message); + // Note: The expresion below is expanded into all usage of this assertion macro. + // We should try to minimize the size of the expanded code to the extent possible. + #define OVR_ASSERT_M(p, message) do \ + { \ + if (!(p)) \ + { \ + intptr_t ovrAssertUserParam; \ + OVRAssertionHandler ovrAssertUserHandler = OVR::GetAssertionHandler(&ovrAssertUserParam); \ + \ + if(ovrAssertUserHandler && !OVRIsDebuggerPresent()) \ + { \ + ovrAssertUserHandler(ovrAssertUserParam, "Assertion failure", message); \ + } \ + else \ + { \ + OVR_DEBUG_BREAK; \ + } \ + } \ + } while(0) + + // void OVR_ASSERT(bool expression); + #define OVR_ASSERT(p) OVR_ASSERT_M((p), (#p)) + #endif + + // Acts the same as OVR_ASSERT in debug builds. Acts the same as OVR_UNUSED in release builds. + // Example usage: OVR_ASSERT_AND_UNUSED(x < 30, x); + #define OVR_ASSERT_AND_UNUSED(expression, value) OVR_ASSERT(expression); OVR_UNUSED(value) + +#else + + // The expresssion is defined only in debug builds. It is defined away in release builds. + #define OVR_DEBUG_CODE(c) + + // Causes a debugger breakpoint in debug builds. Has no effect in release builds. + #define OVR_DEBUG_BREAK ((void)0) + + // In debug builds this tests the given expression; if false then executes OVR_DEBUG_BREAK, + // if true then no action. Has no effect in release builds. + #define OVR_ASSERT(p) ((void)0) + #define OVR_ASSERT_M(p, m) ((void)0) + + // Acts the same as OVR_ASSERT in debug builds. Acts the same as OVR_UNUSED in release builds. + // Example usage: OVR_ASSERT_AND_UNUSED(x < 30, x); + #define OVR_ASSERT_AND_UNUSED(expression, value) OVR_UNUSED(value) #endif // OVR_BUILD_DEBUG -// Compile-time assert; produces compiler error if condition is false -#define OVR_COMPILER_ASSERT(x) { int zero = 0; switch(zero) {case 0: case x:;} } +// Assert handler +// The user of this library can override the default assertion handler and provide their own. +namespace OVR +{ + // The return value meaning is reserved for future definition and currently has no effect. + typedef intptr_t (*OVRAssertionHandler)(intptr_t userParameter, const char* title, const char* message); + + // Returns the current assertion handler. + OVRAssertionHandler GetAssertionHandler(intptr_t* userParameter = NULL); + + // Sets the current assertion handler. + // The default assertion handler if none is set simply issues a debug break. + // Example usage: + // intptr_t CustomAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message)) { + // MessageBox(title, message); + // OVR_DEBUG_BREAK; + // } + void SetAssertionHandler(OVRAssertionHandler assertionHandler, intptr_t userParameter = 0); + + // Implements the default assertion handler. + intptr_t DefaultAssertionHandler(intptr_t userParameter, const char* title, const char* message); + + // Currently defined in OVR_DebugHelp.cpp + bool OVRIsDebuggerPresent(); +} + + +// ------------------------------------------------------------------------ +// ***** static_assert +// +// Portable support for C++11 static_assert. +// Acts as if the following were declared: +// void static_assert(bool const_expression, const char* msg); +// +// Example usage: +// static_assert(sizeof(int32_t) == 4, "int32_t expected to be 4 bytes."); + +#if defined(OVR_CPP_NO_STATIC_ASSERT) // If the compiler doesn't provide it intrinsically... + #if !defined(OVR_SA_UNUSED) + #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #define OVR_SA_UNUSED __attribute__((unused)) + #else + #define OVR_SA_UNUSED + #endif + #define OVR_SA_PASTE(a,b) a##b + #define OVR_SA_HELP(a,b) OVR_SA_PASTE(a,b) + #endif + + #if defined(__COUNTER__) + #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __COUNTER__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #else + #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __LINE__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #endif +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_COMPILER_ASSERT +// +// Compile-time assert; produces compiler error if condition is false. +// The expression must be a compile-time constant expression. +// This macro is deprecated in favor of static_assert, which provides better +// compiler output and works in a broader range of contexts. +// +// Example usage: +// OVR_COMPILER_ASSERT(sizeof(int32_t == 4)); + +#if !defined(OVR_COMPILER_ASSERT) + #define OVR_COMPILER_ASSERT(expression) static_assert(expression, #expression) + #define OVR_COMPILER_ASSERT_M(expression, msg) static_assert(expression, msg) +#endif + + +// ***** OVR_PROCESSOR_PAUSE +// +// Yields the processor for other hyperthreads, usually for the purpose of implementing spins and spin locks. +// +// Example usage: +// while(!finished()) +// OVR_PROCESSOR_PAUSE(); + +#if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #define OVR_PROCESSOR_PAUSE() asm volatile("pause" ::: "memory") // Consumes 38-40 clocks on current Intel x86 and x64 hardware. + #elif defined(OVR_CC_MSVC) + #include <emmintrin.h> + #pragma intrinsic(_mm_pause) // Maps to asm pause. + #define OVR_PROCESSOR_PAUSE _mm_pause + #else + #define OVR_PROCESSOR_PAUSE() + #endif +#else + #define OVR_PROCESSOR_PAUSE() +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_ARRAY_COUNT +// +// Returns the element count of a C array. +// +// Example usage: +// float itemArray[16]; +// for(size_t i = 0; i < OVR_ARRAY_COUNT(itemArray); i++) { ... } + +#if defined(OVR_CPP_NO_CONSTEXPR) + #ifndef OVR_ARRAY_COUNT + #define OVR_ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0])) + #endif +#else + // Smarter C++11 version which knows the difference between arrays and pointers. + template <typename T, size_t N> + char (&OVRArrayCountHelper(T (&x)[N]))[N]; + #define OVR_ARRAY_COUNT(x) (sizeof(OVRArrayCountHelper(x))) +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_CURRENT_FUNCTION +// +// Portable wrapper for __PRETTY_FUNCTION__, C99 __func__, __FUNCTION__. +// This represents the most expressive version available. +// Acts as if the following were declared: +// static const char OVR_CURRENT_FUNCTION[] = "function-name"; +// +// Example usage: +// void Test() { printf("%s", OVR_CURRENT_FUNCTION); } + +#if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || (defined(__ICC) && (__ICC >= 600)) // GCC, clang, Intel + #define OVR_CURRENT_FUNCTION __PRETTY_FUNCTION__ +#elif defined(__FUNCSIG__) // VC++ + #define OVR_CURRENT_FUNCTION __FUNCSIG__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) // C99 compilers + #define OVR_CURRENT_FUNCTION __func__ +#else + #define OVR_CURRENT_FUNCTION __FUNCTION__ +#endif //----------------------------------------------------------------------------------- -// ***** OVR_UNUSED - Unused Argument handling +// ***** OVR_DEPRECATED / OVR_DEPRECATED_MSG +// +// Portably annotates a function or struct as deprecated. +// Note that clang supports __deprecated_enum_msg, which may be useful to support. +// +// Example usage: +// OVR_DEPRECATED void Test(); // Use on the function declaration, as opposed to definition. +// +// struct OVR_DEPRECATED Test{ ... }; +// +// OVR_DEPRECATED_MSG("Test is deprecated") +// void Test(); + +#if !defined(OVR_DEPRECATED) + #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION > 1400) // VS2005+ + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __declspec(deprecated(msg)) + #elif defined(OVR_CC_CLANG) && OVR_CC_HAS_FEATURE(attribute_deprecated_with_message) + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) + #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 405) + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) + #elif !defined(OVR_CC_MSVC) + #define OVR_DEPRECATED __attribute__((deprecated)) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated)) + #else + #define OVR_DEPRECATED + #define OVR_DEPRECATED_MSG(msg) + #endif +#endif + +//----------------------------------------------------------------------------------- +// ***** OVR_UNUSED - Unused Argument handling // Macro to quiet compiler warnings about unused parameters/variables. +// +// Example usage: +// void Test() { +// int x = SomeFunction(); +// OVR_UNUSED(x); +// } +// + #if defined(OVR_CC_GNU) # define OVR_UNUSED(a) do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0) #else @@ -438,8 +841,10 @@ namespace BaseTypes //----------------------------------------------------------------------------------- // ***** Configuration Macros +// +// Expands to the current build type as a const char string literal. +// Acts as the following declaration: const char OVR_BUILD_STRING[]; -// SF Build type #ifdef OVR_BUILD_DEBUG # define OVR_BUILD_STRING "Debug" #else @@ -471,4 +876,34 @@ namespace BaseTypes // +//----------------------------------------------------------------------------------- +// ***** Find normal allocations +// +// Our allocations are all supposed to go through the OVR System Allocator, so that +// they can be run through a game's own preferred allocator. Occasionally we will +// accidentally introduce new code that doesn't adhere to this contract. And it +// then becomes difficult to track down these normal allocations. This piece of +// code makes it easy to check for normal allocations by asserting whenever they +// happen in our code. + +//#define OVR_FIND_NORMAL_ALLOCATIONS +#ifdef OVR_FIND_NORMAL_ALLOCATIONS + +inline void* operator new (size_t size, const char* filename, int line) +{ + void* ptr = new char[size]; + OVR_ASSERT(false); + return ptr; +} + +#define new new(__FILE__, __LINE__) + +#endif // OVR_FIND_NORMAL_ALLOCATIONS + + +#include "OVR_Nullptr.h" + + + + #endif // OVR_Types_h diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp index f8aa697..68e58ea 100644 --- a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp @@ -7,16 +7,16 @@ Notes : Notes : Much useful info at "UTF-8 and Unicode FAQ" http://www.cl.cam.ac.uk/~mgk25/unicode.html -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -30,10 +30,10 @@ limitations under the License. namespace OVR { namespace UTF8Util { -SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) +intptr_t OVR_STDCALL GetLength(const char* buf, intptr_t buflen) { const char* p = buf; - SPInt length = 0; + intptr_t length = 0; if (buflen != -1) { @@ -53,10 +53,10 @@ SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) return length; } -UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length) { const char* buf = putf8str; - UInt32 c = 0; + uint32_t c = 0; if (length != -1) { @@ -87,7 +87,7 @@ UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) return c; } -SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char *putf8str, intptr_t length) { const char* buf = putf8str; @@ -104,7 +104,7 @@ SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) while (index > 0) { - UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf); + uint32_t c = UTF8Util::DecodeNextChar_Advance0(&buf); index--; if (c == 0) @@ -114,7 +114,7 @@ SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) return buf-putf8str; } -int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) +int OVR_STDCALL GetEncodeCharSize(uint32_t ucs_character) { if (ucs_character <= 0x7F) return 1; @@ -132,9 +132,9 @@ int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) return 0; } -UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) { - UInt32 uc; + uint32_t uc; char c; // Security considerations: @@ -171,7 +171,7 @@ UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) if (c == 0) return 0; // End of buffer. - if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII. + if ((c & 0x80) == 0) return (uint32_t) c; // Conventional 7-bit ASCII. // Multi-byte sequences. if ((c & 0xE0) == 0xC0) @@ -236,7 +236,7 @@ UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) } -void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) +void OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* pindex, uint32_t ucs_character) { if (ucs_character <= 0x7F) { @@ -289,9 +289,9 @@ void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) } } -SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length) { - SPInt len = 0; + intptr_t len = 0; if (length != -1) for (int i = 0; i < length; i++) { @@ -307,9 +307,9 @@ SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) return len; } -void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length) { - SPInt ofs = 0; + intptr_t ofs = 0; if (length != -1) { for (int i = 0; i < length; i++) @@ -329,14 +329,14 @@ void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) pbuff[ofs] = 0; } -UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen) +size_t OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen) { wchar_t *pbegin = pbuff; if (bytesLen == -1) { while (1) { - UInt32 ch = DecodeNextChar_Advance0(&putf8str); + uint32_t ch = DecodeNextChar_Advance0(&putf8str); if (ch == 0) break; else if (ch >= 0xFFFF) @@ -349,7 +349,7 @@ UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytes const char* p = putf8str; while ((p - putf8str) < bytesLen) { - UInt32 ch = DecodeNextChar_Advance0(&p); + uint32_t ch = DecodeNextChar_Advance0(&p); if (ch >= 0xFFFF) ch = 0xFFFD; *pbuff++ = wchar_t(ch); @@ -384,12 +384,12 @@ UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytes #include <stdio.h> -bool check_equal(const char* utf8_in, const UInt32* ucs_in) +bool check_equal(const char* utf8_in, const uint32_t* ucs_in) { for (;;) { - UInt32 next_ucs = *ucs_in++; - UInt32 next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); + uint32_t next_ucs = *ucs_in++; + uint32_t next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); if (next_ucs != next_ucs_from_utf8) { return false; @@ -429,11 +429,11 @@ void log_ascii(const char* line) } -void log_ucs(const UInt32* line) +void log_ucs(const uint32_t* line) { for (;;) { - UInt32 uc = *line++; + uint32_t uc = *line++; if (uc == 0) { // End of line. @@ -458,7 +458,7 @@ int main(int argc, const char* argv[]) { { const char* test8 = "Ignacio Castaño"; - const UInt32 test32[] = + const uint32_t test32[] = { 0x49, 0x67, 0x6E, 0x61, 0x63, 0x69, 0x6F, 0x20, 0x43, 0x61, @@ -484,7 +484,7 @@ int main(int argc, const char* argv[]) const int LINE_SIZE = 200; // max line size char line_buffer_utf8[LINE_SIZE]; char reencoded_utf8[6 * LINE_SIZE]; - UInt32 line_buffer_ucs[LINE_SIZE]; + uint32_t line_buffer_ucs[LINE_SIZE]; int byte_counter = 0; for (;;) @@ -503,10 +503,10 @@ int main(int argc, const char* argv[]) // Decode into UCS. const char* p = line_buffer_utf8; - UInt32* q = line_buffer_ucs; + uint32_t* q = line_buffer_ucs; for (;;) { - UInt32 uc = UTF8Util::DecodeNextChar(&p); + uint32_t uc = UTF8Util::DecodeNextChar(&p); *q++ = uc; OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE); @@ -520,7 +520,7 @@ int main(int argc, const char* argv[]) int index = 0; for (;;) { - UInt32 uc = *q++; + uint32_t uc = *q++; OVR_ASSERT(index < LINE_SIZE * 6 - 6); int last_index = index; UTF8Util::EncodeChar(reencoded_utf8, &index, uc); diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.h b/LibOVR/Src/Kernel/OVR_UTF8Util.h index 6a596012..3b640f0 100644 --- a/LibOVR/Src/Kernel/OVR_UTF8Util.h +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.h @@ -1,21 +1,21 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_UTF8Util.h Content : UTF8 Unicode character encoding/decoding support Created : September 19, 2012 Notes : -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +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.1 +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, @@ -38,56 +38,56 @@ namespace OVR { namespace UTF8Util { // Determines the length of UTF8 string in characters. // If source length is specified (in bytes), null 0 character is counted properly. -SPInt OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1); +intptr_t OVR_STDCALL GetLength(const char* putf8str, intptr_t length = -1); // Gets a decoded UTF8 character at index; you can access up to the index returned // by GetLength. 0 will be returned for out of bounds access. -UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1); +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length = -1); // Converts UTF8 character index into byte offset. // -1 is returned if index was out of bounds. -SPInt OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1); +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char* putf8str, intptr_t length = -1); // *** 16-bit Unicode string Encoding/Decoding routines. // Determines the number of bytes necessary to encode a string. // Does not count the terminating 0 (null) character. -SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1); +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length = -1); // Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at // least GetEncodeStringSize() + 1. -void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1); +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length = -1); // Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available. // Characters over 0xFFFF are replaced with 0xFFFD. // Returns the length of resulting string (number of characters) -UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1); +size_t OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen = -1); // *** Individual character Encoding/Decoding. // Determined the number of bytes necessary to encode a UCS character. -int OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter); +int OVR_STDCALL GetEncodeCharSize(uint32_t ucsCharacter); // Encodes the given UCS character into the given UTF-8 buffer. // Writes the data starting at buffer[offset], and // increments offset by the number of bytes written. // May write up to 6 bytes, so make sure there's room in the buffer -void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter); +void OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* poffset, uint32_t ucsCharacter); // Return the next Unicode character in the UTF-8 encoded buffer. // Invalid UTF-8 sequences produce a U+FFFD character as output. // Advances *utf8_buffer past the character returned. Pointer advance // occurs even if the terminating 0 character is hit, since that allows // strings with middle '\0' characters to be supported. -UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); // Safer version of DecodeNextChar, which doesn't advance pointer if // null character is hit. -inline UInt32 DecodeNextChar(const char** putf8Buffer) +inline uint32_t DecodeNextChar(const char** putf8Buffer) { - UInt32 ch = DecodeNextChar_Advance0(putf8Buffer); + uint32_t ch = DecodeNextChar_Advance0(putf8Buffer); if (ch == 0) (*putf8Buffer)--; return ch; diff --git a/LibOVR/Src/Kernel/OVR_mach_exc_OSX.c b/LibOVR/Src/Kernel/OVR_mach_exc_OSX.c new file mode 100644 index 0000000..142faf1 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_mach_exc_OSX.c @@ -0,0 +1,2955 @@ +/* This file was generated by the MIG utility with: + mig /usr/include/mach/mach_exc.defs + We pre-generate them instead of generate them at compile-time because we + need to rename some of the functions to append _OVR so we don't get conflicts + with any other versions of these functions the application may have. +*/ + +/* Begin mach_excUser.c */ + +#define __MIG_check__Reply__mach_exc_subsystem__ 1 +#define __NDR_convert__Reply__mach_exc_subsystem__ 1 +#define __NDR_convert__mig_reply_error_subsystem__ 1 + +#include "OVR_mach_exc_OSX.h" + +#if defined(__cplusplus) + extern "C" { +#endif + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __MachMsgErrorWithTimeout +#define __MachMsgErrorWithTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + case MACH_SEND_TIMED_OUT: \ + case MACH_RCV_TIMED_OUT: \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithTimeout */ + +#ifndef __MachMsgErrorWithoutTimeout +#define __MachMsgErrorWithoutTimeout(_R_) { \ + switch (_R_) { \ + case MACH_SEND_INVALID_DATA: \ + case MACH_SEND_INVALID_DEST: \ + case MACH_SEND_INVALID_HEADER: \ + mig_put_reply_port(InP->Head.msgh_reply_port); \ + break; \ + default: \ + mig_dealloc_reply_port(InP->Head.msgh_reply_port); \ + } \ +} +#endif /* __MachMsgErrorWithoutTimeout */ + +#ifndef __DeclareSendRpc +#define __DeclareSendRpc(_NUM_, _NAME_) +#endif /* __DeclareSendRpc */ + +#ifndef __BeforeSendRpc +#define __BeforeSendRpc(_NUM_, _NAME_) +#endif /* __BeforeSendRpc */ + +#ifndef __AfterSendRpc +#define __AfterSendRpc(_NUM_, _NAME_) +#endif /* __AfterSendRpc */ + +#ifndef __DeclareSendSimple +#define __DeclareSendSimple(_NUM_, _NAME_) +#endif /* __DeclareSendSimple */ + +#ifndef __BeforeSendSimple +#define __BeforeSendSimple(_NUM_, _NAME_) +#endif /* __BeforeSendSimple */ + +#ifndef __AfterSendSimple +#define __AfterSendSimple(_NUM_, _NAME_) +#endif /* __AfterSendSimple */ + +#ifndef msgh_request_port + #define msgh_request_port msgh_remote_port +#endif + +#ifndef msgh_reply_port + #define msgh_reply_port msgh_local_port +#endif + + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_t__defined) +#define __MIG_check__Reply__mach_exception_raise_t__defined +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined +#if defined(__NDR_convert__int_rep__mach_exc__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode(a, f) \ + __NDR_convert__int_rep__mach_exc__kern_return_t((kern_return_t *)(a), f) +#elif defined(__NDR_convert__int_rep__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode(a, f) \ + __NDR_convert__int_rep__kern_return_t((kern_return_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined */ + + + + + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_t_OVR(__Reply__mach_exception_raise_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_t __Reply; + if (Out0P->Head.msgh_id != 2505) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + + #if __MigTypeCheck + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply))) + { return MIG_TYPE_ERROR ; } + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined) + if (Out0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode(&Out0P->RetCode, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_t__RetCode__defined */ + { + return Out0P->RetCode; + } +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine mach_exception_raise_OVR */ +mig_external kern_return_t mach_exception_raise_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + mach_msg_trailer_t trailer; + } Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + + #ifdef __MIG_check__Reply__mach_exception_raise_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Reply__mach_exception_raise_t__defined */ + + __DeclareSendRpc(2405, "mach_exception_raise_OVR") + + #if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; + #endif /* UseStaticTemplates */ + + #if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; + #endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; + #if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; + #else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; + #endif /* UseStaticTemplates */ + + #if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; + #else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; + #endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt)); + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2405; + + __BeforeSendRpc(2405, "mach_exception_raise_OVR") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2405, "mach_exception_raise_OVR") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + + #if defined(__MIG_check__Reply__mach_exception_raise_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_t_OVR((__Reply__mach_exception_raise_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } + #endif /* defined(__MIG_check__Reply__mach_exception_raise_t__defined) */ + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) +#define __MIG_check__Reply__mach_exception_raise_state_t__defined +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined +#if defined(__NDR_convert__int_rep__mach_exc__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode(a, f) \ + __NDR_convert__int_rep__mach_exc__kern_return_t((kern_return_t *)(a), f) +#elif defined(__NDR_convert__int_rep__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode(a, f) \ + __NDR_convert__int_rep__kern_return_t((kern_return_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#if defined(__NDR_convert__int_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__int_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__natural_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined */ + + + +#ifndef __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + + +#ifndef __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#if defined(__NDR_convert__char_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__char_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__natural_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + + + + +#ifndef __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + + +#ifndef __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#if defined(__NDR_convert__float_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__float_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__natural_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + + + + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_t_OVR(__Reply__mach_exception_raise_state_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_state_t __Reply; + #if __MigTypeCheck + unsigned int msgh_size; + #endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2506) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + + #if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 576)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } + #endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + #ifdef __NDR_convert__mig_reply_error_t__defined + __NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P); + #endif /* __NDR_convert__mig_reply_error_t__defined */ + return ((mig_reply_error_t *)Out0P)->RetCode; + } + + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined) + if (Out0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt(&Out0P->new_stateCnt, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined */ + #if __MigTypeCheck + if ( Out0P->new_stateCnt > 144 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 576)) / 4 != Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 576) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_stateCnt__defined) + if (Out0P->NDR.int_rep != NDR_record.int_rep) { + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode(&Out0P->RetCode, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__RetCode__defined */ + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor(&Out0P->flavor, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state(&Out0P->new_state, Out0P->NDR.int_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__int_rep...) */ + + #if 0 || \ + defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined) || \ + 0 + if (Out0P->NDR.char_rep != NDR_record.char_rep) { + #if defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor(&Out0P->flavor, Out0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined) + __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state(&Out0P->new_state, Out0P->NDR.char_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__char_rep...) */ + + #if 0 || \ + defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined) || \ + 0 + if (Out0P->NDR.float_rep != NDR_record.float_rep) { + #if defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor(&Out0P->flavor, Out0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined) + __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state(&Out0P->new_state, Out0P->NDR.float_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine mach_exception_raise_state_OVR */ +mig_external kern_return_t mach_exception_raise_state_OVR +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + mach_msg_trailer_t trailer; + } Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + + #ifdef __MIG_check__Reply__mach_exception_raise_state_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Reply__mach_exception_raise_state_t__defined */ + + __DeclareSendRpc(2406, "mach_exception_raise_state_OVR") + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (8 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 592) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16); + + InP->flavor = *flavor; + + if (old_stateCnt > 144) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2406; + + __BeforeSendRpc(2406, "mach_exception_raise_state_OVR") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2406, "mach_exception_raise_state_OVR") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + + #if defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_state_t_OVR((__Reply__mach_exception_raise_state_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } + #endif /* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 144) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 144); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Reply__mach_exc_subsystem__ +#if !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Reply__mach_exception_raise_state_identity_t__defined +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined +#if defined(__NDR_convert__int_rep__mach_exc__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode(a, f) \ + __NDR_convert__int_rep__mach_exc__kern_return_t((kern_return_t *)(a), f) +#elif defined(__NDR_convert__int_rep__kern_return_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode(a, f) \ + __NDR_convert__int_rep__kern_return_t((kern_return_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#if defined(__NDR_convert__int_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__int_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__natural_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + + +#ifndef __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined +#define __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined */ + + + +#ifndef __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + + +#ifndef __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#if defined(__NDR_convert__char_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__char_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__natural_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + + + + +#ifndef __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + + +#ifndef __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#if defined(__NDR_convert__float_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__float_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__natural_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined +#define __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + + + + +mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_identity_t(__Reply__mach_exception_raise_state_identity_t *Out0P) +{ + + typedef __Reply__mach_exception_raise_state_identity_t __Reply; + #if __MigTypeCheck + unsigned int msgh_size; + #endif /* __MigTypeCheck */ + + if (Out0P->Head.msgh_id != 2507) { + if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) + { return MIG_SERVER_DIED; } + else + { return MIG_REPLY_MISMATCH; } + } + + #if __MigTypeCheck + msgh_size = Out0P->Head.msgh_size; + + if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + ((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 576)) && + (msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) || + Out0P->RetCode == KERN_SUCCESS))) + { return MIG_TYPE_ERROR ; } + #endif /* __MigTypeCheck */ + + if (Out0P->RetCode != KERN_SUCCESS) { + #ifdef __NDR_convert__mig_reply_error_t__defined + __NDR_convert__mig_reply_error_t((mig_reply_error_t *)Out0P); + #endif /* __NDR_convert__mig_reply_error_t__defined */ + return ((mig_reply_error_t *)Out0P)->RetCode; + } + + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined) + if (Out0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt(&Out0P->new_stateCnt, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined */ + #if __MigTypeCheck + if ( Out0P->new_stateCnt > 144 ) + return MIG_TYPE_ERROR; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 576)) / 4 != Out0P->new_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 576) + Out0P->new_stateCnt * 4)) + { return MIG_TYPE_ERROR ; } + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) || \ + defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_stateCnt__defined) + if (Out0P->NDR.int_rep != NDR_record.int_rep) { + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode(&Out0P->RetCode, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__RetCode__defined */ + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor(&Out0P->flavor, Out0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) + __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state(&Out0P->new_state, Out0P->NDR.int_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__int_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__int_rep...) */ + + #if 0 || \ + defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) || \ + 0 + if (Out0P->NDR.char_rep != NDR_record.char_rep) { + #if defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor(&Out0P->flavor, Out0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) + __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state(&Out0P->new_state, Out0P->NDR.char_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__char_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__char_rep...) */ + + #if 0 || \ + defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) || \ + 0 + if (Out0P->NDR.float_rep != NDR_record.float_rep) { + #if defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor(&Out0P->flavor, Out0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined) + __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state(&Out0P->new_state, Out0P->NDR.float_rep, Out0P->new_stateCnt); + #endif /* __NDR_convert__float_rep__Reply__mach_exception_raise_state_identity_t__new_state__defined */ + } + #endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Reply__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine mach_exception_raise_state_identity_OVR */ +mig_external kern_return_t mach_exception_raise_state_identity_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + mach_msg_trailer_t trailer; + } Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply; + #ifdef __MigPackStructs + #pragma pack() + #endif + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + union { + Request In; + Reply Out; + } Mess; + + Request *InP = &Mess.In; + Reply *Out0P = &Mess.Out; + + mach_msg_return_t msg_result; + unsigned int msgh_size; + unsigned int msgh_size_delta; + + + #ifdef __MIG_check__Reply__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */ + + __DeclareSendRpc(2407, "mach_exception_raise_state_identity_OVR") + + #if UseStaticTemplates + const static mach_msg_port_descriptor_t threadTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; + #endif /* UseStaticTemplates */ + + #if UseStaticTemplates + const static mach_msg_port_descriptor_t taskTemplate = { + /* name = */ MACH_PORT_NULL, + /* pad1 = */ 0, + /* pad2 = */ 0, + /* disp = */ 19, + /* type = */ MACH_MSG_PORT_DESCRIPTOR, + }; + #endif /* UseStaticTemplates */ + + InP->msgh_body.msgh_descriptor_count = 2; + #if UseStaticTemplates + InP->thread = threadTemplate; + InP->thread.name = thread; + #else /* UseStaticTemplates */ + InP->thread.name = thread; + InP->thread.disposition = 19; + InP->thread.type = MACH_MSG_PORT_DESCRIPTOR; + #endif /* UseStaticTemplates */ + + #if UseStaticTemplates + InP->task = taskTemplate; + InP->task.name = task; + #else /* UseStaticTemplates */ + InP->task.name = task; + InP->task.disposition = 19; + InP->task.type = MACH_MSG_PORT_DESCRIPTOR; + #endif /* UseStaticTemplates */ + + InP->NDR = NDR_record; + + InP->exception = exception; + + if (codeCnt > 2) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt); + + InP->codeCnt = codeCnt; + + msgh_size_delta = (8 * codeCnt); + msgh_size = (mach_msg_size_t)(sizeof(Request) - 592) + msgh_size_delta; + InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16); + + InP->flavor = *flavor; + + if (old_stateCnt > 144) { + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt); + + InP->old_stateCnt = old_stateCnt; + + msgh_size += (4 * old_stateCnt); + InP = &Mess.In; + InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX| + MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); + /* msgh_size passed as argument */ + InP->Head.msgh_request_port = exception_port; + InP->Head.msgh_reply_port = mig_get_reply_port(); + InP->Head.msgh_id = 2407; + + __BeforeSendRpc(2407, "mach_exception_raise_state_identity_OVR") + msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + __AfterSendRpc(2407, "mach_exception_raise_state_identity_OVR") + if (msg_result != MACH_MSG_SUCCESS) { + __MachMsgErrorWithoutTimeout(msg_result); + { return msg_result; } + } + + + #if defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P); + if (check_result != MACH_MSG_SUCCESS) + { return check_result; } + #endif /* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */ + + *flavor = Out0P->flavor; + + if (Out0P->new_stateCnt > 144) { + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 144); + *new_stateCnt = Out0P->new_stateCnt; + { return MIG_ARRAY_TOO_LARGE; } + } + (void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt); + + *new_stateCnt = Out0P->new_stateCnt; + + return KERN_SUCCESS; +} + +#if defined(__cplusplus) + } /* extern "C" */ +#endif + +/* End mach_excUser.c */ + + + + +/* Begin mach_excServer.c */ + +/* Module mach_exc */ + +#define __MIG_check__Request__mach_exc_subsystem__ 1 +#define __NDR_convert__Request__mach_exc_subsystem__ 1 + +#include <string.h> +#include <mach/ndr.h> +#include <mach/boolean.h> +#include <mach/kern_return.h> +#include <mach/notify.h> +#include <mach/mach_types.h> +#include <mach/message.h> +#include <mach/mig_errors.h> +#include <mach/port.h> + +#include <mach/std_types.h> +#include <mach/mig.h> +#include <mach/mig.h> +#include <mach/mach_types.h> + +#if defined(__cplusplus) + extern "C" { +#endif + +#ifndef mig_internal +#define mig_internal static __inline__ +#endif /* mig_internal */ + +#ifndef mig_external +#define mig_external +#endif /* mig_external */ + +#if !defined(__MigTypeCheck) && defined(TypeCheck) +#define __MigTypeCheck TypeCheck /* Legacy setting */ +#endif /* !defined(__MigTypeCheck) */ + +#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_) +#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */ +#endif /* !defined(__MigKernelSpecificCode) */ + +#ifndef LimitCheck +#define LimitCheck 0 +#endif /* LimitCheck */ + +#ifndef min +#define min(a,b) ( ((a) < (b))? (a): (b) ) +#endif /* min */ + +#if !defined(_WALIGN_) +#define _WALIGN_(x) (((x) + 3) & ~3) +#endif /* !defined(_WALIGN_) */ + +#if !defined(_WALIGNSZ_) +#define _WALIGNSZ_(x) _WALIGN_(sizeof(x)) +#endif /* !defined(_WALIGNSZ_) */ + +#ifndef UseStaticTemplates +#define UseStaticTemplates 0 +#endif /* UseStaticTemplates */ + +#ifndef __DeclareRcvRpc +#define __DeclareRcvRpc(_NUM_, _NAME_) +#endif /* __DeclareRcvRpc */ + +#ifndef __BeforeRcvRpc +#define __BeforeRcvRpc(_NUM_, _NAME_) +#endif /* __BeforeRcvRpc */ + +#ifndef __AfterRcvRpc +#define __AfterRcvRpc(_NUM_, _NAME_) +#endif /* __AfterRcvRpc */ + +#ifndef __DeclareRcvSimple +#define __DeclareRcvSimple(_NUM_, _NAME_) +#endif /* __DeclareRcvSimple */ + +#ifndef __BeforeRcvSimple +#define __BeforeRcvSimple(_NUM_, _NAME_) +#endif /* __BeforeRcvSimple */ + +#ifndef __AfterRcvSimple +#define __AfterRcvSimple(_NUM_, _NAME_) +#endif /* __AfterRcvSimple */ + +#define novalue void + +#ifndef msgh_request_port + #define msgh_request_port msgh_local_port +#endif +#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits) +#ifndef msgh_reply_port + #define msgh_reply_port msgh_remote_port +#endif +#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits) + +#define MIG_RETURN_ERROR(X, code) {\ + ((mig_reply_error_t *)X)->RetCode = code;\ + ((mig_reply_error_t *)X)->NDR = NDR_record;\ + return;\ + } + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + + +/* union of all replies */ + +#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined +#define __ReplyUnion__catch_mach_exc_subsystem__defined +union __ReplyUnion__catch_mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */ +/* Forward Declarations */ + + +mig_internal novalue _Xmach_exception_raise_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +mig_internal novalue _Xmach_exception_raise_state_identity_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_t__defined) +#define __MIG_check__Request__mach_exception_raise_t__defined +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#if defined(__NDR_convert__int_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__int_rep__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#if defined(__NDR_convert__char_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined +#if defined(__NDR_convert__char_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__char_rep__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#if defined(__NDR_convert__float_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined +#if defined(__NDR_convert__float_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__float_rep__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined */ + + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t_OVR(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P) +{ + const size_t sizeofRequest = sizeof(__Request__mach_exception_raise_t); + + typedef __Request__mach_exception_raise_t __Request; + #if __MigTypeCheck + unsigned int msgh_size; + #endif /* __MigTypeCheck */ + + #if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeofRequest - 16)) || (msgh_size > (mach_msg_size_t)sizeofRequest)) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; + #endif /* __MigTypeCheck */ + + #if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */ + #if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeofRequest - 16)) / 8 != In0P->codeCnt) || + (msgh_size != (mach_msg_size_t)(sizeofRequest - 16) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_t__exception(&In0P->exception, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__exception__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__code__defined */ + } + #endif /* defined(__NDR_convert__int_rep...) */ + + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_t__exception(&In0P->exception, In0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_t__exception__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_t__code__defined */ + } + #endif /* defined(__NDR_convert__char_rep...) */ + + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_t__exception(&In0P->exception, In0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_t__exception__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_t__code__defined */ + } + #endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine catch_mach_exception_raise_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine _Xmach_exception_raise_OVR */ +mig_internal novalue _Xmach_exception_raise_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + mach_msg_trailer_t trailer; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + typedef __Request__mach_exception_raise_t __Request; + typedef __Reply__mach_exception_raise_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Reply *OutP = (Reply *) OutHeadP; + #ifdef __MIG_check__Request__mach_exception_raise_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Request__mach_exception_raise_t__defined */ + + __DeclareRcvRpc(2405, "mach_exception_raise_OVR") + __BeforeRcvRpc(2405, "mach_exception_raise_OVR") + + #if defined(__MIG_check__Request__mach_exception_raise_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_t_OVR((__Request *)In0P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } + #endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */ + + OutP->RetCode = catch_mach_exception_raise_OVR(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt); + + OutP->NDR = NDR_record; + + + __AfterRcvRpc(2405, "mach_exception_raise_OVR") +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_t__defined +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#if defined(__NDR_convert__int_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__int_rep__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__int_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__int_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__natural_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#if defined(__NDR_convert__char_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined +#if defined(__NDR_convert__char_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__char_rep__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__char_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__char_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__natural_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#if defined(__NDR_convert__float_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined +#if defined(__NDR_convert__float_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__float_rep__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined +#if defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#if defined(__NDR_convert__float_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__float_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__natural_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined */ + + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t_OVR(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP) +{ + + typedef __Request__mach_exception_raise_state_t __Request; + __Request *In1P; + #if __MigTypeCheck + unsigned int msgh_size; + #endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + + #if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 592)) || (msgh_size > (mach_msg_size_t)sizeof(__Request))) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); + #if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 592)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 592) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; + #endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */ + #if __MigTypeCheck + if ( In1P->old_stateCnt > 144 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 592)) / 4 != In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 592) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception(&In0P->exception, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__exception__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__code__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__int_rep...) */ + + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception(&In0P->exception, In0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__exception__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__code__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__char_rep...) */ + + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception(&In0P->exception, In0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__exception__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__code__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor(&In1P->flavor, In0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__flavor__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine mach_exception_raise_state_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise_state_OVR +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine _Xmach_exception_raise_state_OVR */ +mig_internal novalue _Xmach_exception_raise_state_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + mach_msg_trailer_t trailer; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + typedef __Request__mach_exception_raise_state_t __Request; + typedef __Reply__mach_exception_raise_state_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; + #ifdef __MIG_check__Request__mach_exception_raise_state_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */ + + __DeclareRcvRpc(2406, "mach_exception_raise_state_OVR") + __BeforeRcvRpc(2406, "mach_exception_raise_state_OVR") + + #if defined(__MIG_check__Request__mach_exception_raise_state_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_t_OVR((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } + #endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */ + + OutP->new_stateCnt = 144; + + OutP->RetCode = catch_mach_exception_raise_state_OVR(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2406, "mach_exception_raise_state_OVR") +} + +#if ( __MigTypeCheck || __NDR_convert__ ) +#if __MIG_check__Request__mach_exc_subsystem__ +#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) +#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__int_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__exception_type_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exception_data_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__int_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__int_rep__int64_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__int_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__int_rep__mach_exc__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__int__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int((int *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_exc__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__int_rep__int32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__int_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__int_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__int_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__thread_state_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__int_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__int_rep__mach_exc__natural_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__int_rep__natural_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__int_rep__natural_t) +#elif defined(__NDR_convert__int_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__int_rep__uint32_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__int_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + +#ifndef __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined +#if defined(__NDR_convert__int_rep__mach_exc__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_exc__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#elif defined(__NDR_convert__int_rep__mach_msg_type_number_t__defined) +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined +#define __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(a, f) \ + __NDR_convert__int_rep__mach_msg_type_number_t((mach_msg_type_number_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__char_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__exception_type_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__char_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exception_data_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__char_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__char_rep__int64_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__char_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__char_rep__mach_exc__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__int__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int((int *)(a), f) +#elif defined(__NDR_convert__char_rep__mach_exc__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__char_rep__int32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__char_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__char_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__char_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__thread_state_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__char_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__char_rep__mach_exc__natural_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__char_rep__natural_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__char_rep__natural_t) +#elif defined(__NDR_convert__char_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__char_rep__uint32_t__defined) +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__char_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#if defined(__NDR_convert__float_rep__mach_exc__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__exception_type_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__exception_type_t((exception_type_t *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined +#if defined(__NDR_convert__float_rep__mach_exc__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exc__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exception_data_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__float_rep__mach_exception_data_t((mach_exception_data_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__int64_t) +#elif defined(__NDR_convert__float_rep__int64_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code(a, f, c) \ + __NDR_convert__ARRAY((int64_t *)(a), f, c, __NDR_convert__float_rep__int64_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#if defined(__NDR_convert__float_rep__mach_exc__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__int__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int((int *)(a), f) +#elif defined(__NDR_convert__float_rep__mach_exc__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__mach_exc__int32_t((int32_t *)(a), f) +#elif defined(__NDR_convert__float_rep__int32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor(a, f) \ + __NDR_convert__float_rep__int32_t((int32_t *)(a), f) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + +#ifndef __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#if defined(__NDR_convert__float_rep__mach_exc__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__float_rep__mach_exc__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__thread_state_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__float_rep__thread_state_t((thread_state_t *)(a), f, c) +#elif defined(__NDR_convert__float_rep__mach_exc__natural_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__natural_t) +#elif defined(__NDR_convert__float_rep__natural_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((natural_t *)(a), f, c, __NDR_convert__float_rep__natural_t) +#elif defined(__NDR_convert__float_rep__mach_exc__uint32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__mach_exc__uint32_t) +#elif defined(__NDR_convert__float_rep__uint32_t__defined) +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined +#define __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(a, f, c) \ + __NDR_convert__ARRAY((uint32_t *)(a), f, c, __NDR_convert__float_rep__uint32_t) +#endif /* defined(__NDR_convert__*__defined) */ +#endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + + +mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t_OVR(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP) +{ + const size_t sizeofRequest = sizeof(__Request__mach_exception_raise_state_identity_t); + + typedef __Request__mach_exception_raise_state_identity_t __Request; + __Request *In1P; + #if __MigTypeCheck + unsigned int msgh_size; + #endif /* __MigTypeCheck */ + unsigned int msgh_size_delta; + + #if __MigTypeCheck + msgh_size = In0P->Head.msgh_size; + if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) || + (In0P->msgh_body.msgh_descriptor_count != 2) || + (msgh_size < (mach_msg_size_t)(sizeofRequest - 592)) || (msgh_size > (mach_msg_size_t)sizeofRequest)) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if __MigTypeCheck + if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->thread.disposition != 17) + return MIG_TYPE_ERROR; + #endif /* __MigTypeCheck */ + + #if __MigTypeCheck + if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR || + In0P->task.disposition != 17) + return MIG_TYPE_ERROR; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */ + msgh_size_delta = (8 * In0P->codeCnt); + #if __MigTypeCheck + if ( In0P->codeCnt > 2 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeofRequest - 592)) / 8 < In0P->codeCnt) || + (msgh_size < (mach_msg_size_t)(sizeofRequest - 592) + (8 * In0P->codeCnt))) + return MIG_BAD_ARGUMENTS; + msgh_size -= msgh_size_delta; + #endif /* __MigTypeCheck */ + + *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16); + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */ + #if __MigTypeCheck + if ( In1P->old_stateCnt > 144 ) + return MIG_BAD_ARGUMENTS; + if (((msgh_size - (mach_msg_size_t)(sizeofRequest - 592)) / 4 != In1P->old_stateCnt) || + (msgh_size != (mach_msg_size_t)(sizeofRequest - 592) + (4 * In1P->old_stateCnt))) + return MIG_BAD_ARGUMENTS; + #endif /* __MigTypeCheck */ + + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) || \ + defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined) + if (In0P->NDR.int_rep != NDR_record.int_rep) { + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.int_rep, In0P->codeCnt); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.int_rep); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) + __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.int_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__int_rep...) */ + + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) || \ + 0 + if (In0P->NDR.char_rep != NDR_record.char_rep) { + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.char_rep, In0P->codeCnt); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.char_rep); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) + __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.char_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__char_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__char_rep...) */ + + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined) || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined) || \ + 0 || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) || \ + defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) || \ + 0 + if (In0P->NDR.float_rep != NDR_record.float_rep) { + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception(&In0P->exception, In0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__exception__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code(&In0P->code, In0P->NDR.float_rep, In0P->codeCnt); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__code__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor(&In1P->flavor, In0P->NDR.float_rep); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__flavor__defined */ + #if defined(__NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined) + __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state(&In1P->old_state, In0P->NDR.float_rep, In1P->old_stateCnt); + #endif /* __NDR_convert__float_rep__Request__mach_exception_raise_state_identity_t__old_state__defined */ + } + #endif /* defined(__NDR_convert__float_rep...) */ + + return MACH_MSG_SUCCESS; +} +#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ +#endif /* __MIG_check__Request__mach_exc_subsystem__ */ +#endif /* ( __MigTypeCheck || __NDR_convert__ ) */ + + +/* Routine catch_mach_exception_raise_state_identity_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t catch_mach_exception_raise_state_identity_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine mach_exception_raise_state_identity_OVR */ +mig_internal novalue _Xmach_exception_raise_state_identity_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + + #ifdef __MigPackStructs + #pragma pack(4) + #endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + mach_msg_trailer_t trailer; + } Request; + #ifdef __MigPackStructs + #pragma pack() + #endif + typedef __Request__mach_exception_raise_state_identity_t __Request; + typedef __Reply__mach_exception_raise_state_identity_t Reply; + + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + Request *In0P = (Request *) InHeadP; + Request *In1P; + Reply *OutP = (Reply *) OutHeadP; + #ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined + kern_return_t check_result; + #endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */ + + __DeclareRcvRpc(2407, "mach_exception_raise_state_identity_OVR") + __BeforeRcvRpc(2407, "mach_exception_raise_state_identity_OVR") + + #if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) + check_result = __MIG_check__Request__mach_exception_raise_state_identity_t_OVR((__Request *)In0P, (__Request **)&In1P); + if (check_result != MACH_MSG_SUCCESS) + { MIG_RETURN_ERROR(OutP, check_result); } + #endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */ + + OutP->new_stateCnt = 144; + + OutP->RetCode = catch_mach_exception_raise_state_identity_OVR(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt); + if (OutP->RetCode != KERN_SUCCESS) { + MIG_RETURN_ERROR(OutP, OutP->RetCode); + } + + OutP->NDR = NDR_record; + + + OutP->flavor = In1P->flavor; + OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 576) + (((4 * OutP->new_stateCnt))); + + __AfterRcvRpc(2407, "mach_exception_raise_state_identity_OVR") +} + + +#ifdef mig_external + mig_external +#else + extern +#endif /* mig_external */ + boolean_t mach_exc_server_OVR(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +#ifdef mig_external + mig_external +#else + extern +#endif /* mig_external */ + mig_routine_t mach_exc_server_routine_OVR(mach_msg_header_t *InHeadP); + + +/* Description of this subsystem, for use in direct RPC */ +const struct catch_mach_exc_subsystem_OVR { + mig_server_routine_t server; /* Server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + unsigned int maxsize; /* Max msg size */ + vm_address_t reserved; /* Reserved */ + struct routine_descriptor /*Array of routine descriptors */ + routine[3]; +} catch_mach_exc_subsystem_OVR = { + mach_exc_server_routine_OVR, + 2405, + 2408, + (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem), + (vm_address_t)0, + { + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_OVR, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_OVR, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)}, + { (mig_impl_routine_t) 0, + (mig_stub_routine_t) _Xmach_exception_raise_state_identity_OVR, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)}, + } +}; + +mig_external boolean_t mach_exc_server_OVR + (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) +{ + /* + * typedef struct { + * mach_msg_header_t Head; + * NDR_record_t NDR; + * kern_return_t RetCode; + * } mig_reply_error_t; + */ + + register mig_routine_t routine; + + OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0); + OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port; + /* Minimal size: routine() will update it if different */ + OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t); + OutHeadP->msgh_local_port = MACH_PORT_NULL; + OutHeadP->msgh_id = InHeadP->msgh_id + 100; + + if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) || + ((routine = catch_mach_exc_subsystem_OVR.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) + { + ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record; + ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID; + return FALSE; + } + (*routine) (InHeadP, OutHeadP); + return TRUE; +} + +mig_external mig_routine_t mach_exc_server_routine_OVR + (mach_msg_header_t *InHeadP) +{ + register int msgh_id; + + msgh_id = InHeadP->msgh_id - 2405; + + if ((msgh_id > 2) || (msgh_id < 0)) + return 0; + + return catch_mach_exc_subsystem_OVR.routine[msgh_id].stub_routine; +} + +#if defined(__cplusplus) + } /* extern "C" */ +#endif +/* End mach_excServer.c */ + + + diff --git a/LibOVR/Src/Kernel/OVR_mach_exc_OSX.h b/LibOVR/Src/Kernel/OVR_mach_exc_OSX.h new file mode 100644 index 0000000..4a1bcf0 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_mach_exc_OSX.h @@ -0,0 +1,277 @@ +#ifndef _mach_exc_user_ +#define _mach_exc_user_ + +/* Module mach_exc */ + +#include <string.h> +#include <mach/ndr.h> +#include <mach/boolean.h> +#include <mach/kern_return.h> +#include <mach/notify.h> +#include <mach/mach_types.h> +#include <mach/message.h> +#include <mach/mig_errors.h> +#include <mach/port.h> + +#ifdef AUTOTEST +#ifndef FUNCTION_PTR_T +#define FUNCTION_PTR_T +typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t); +typedef struct { + char *name; + function_ptr_t function; +} function_table_entry; +typedef function_table_entry *function_table_t; +#endif /* FUNCTION_PTR_T */ +#endif /* AUTOTEST */ + +#ifndef mach_exc_MSG_COUNT +#define mach_exc_MSG_COUNT 3 +#endif /* mach_exc_MSG_COUNT */ + +#include <mach/std_types.h> +#include <mach/mig.h> +#include <mach/mig.h> +#include <mach/mach_types.h> + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include <sys/cdefs.h> +__BEGIN_DECLS + +#if defined(__cplusplus) + extern "C" { +#endif + +/* Routine mach_exception_raise_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt +); + +/* Routine mach_exception_raise_state_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise_state_OVR +( + mach_port_t exception_port, + exception_type_t exception, + const mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +/* Routine mach_exception_raise_state_identity_OVR */ +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +kern_return_t mach_exception_raise_state_identity_OVR +( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt +); + +__END_DECLS + +/********************** Caution **************************/ +/* The following data types should be used to calculate */ +/* maximum message sizes only. The actual message may be */ +/* smaller, and the position of the arguments within the */ +/* message layout may vary from what is presented here. */ +/* For example, if any of the arguments are variable- */ +/* sized, and less than the maximum is sent, the data */ +/* will be packed tight in the actual message to reduce */ +/* the presence of holes. */ +/********************** Caution **************************/ + +/* typedefs for all requests */ + +#ifndef __Request__mach_exc_subsystem__defined +#define __Request__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + } __Request__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + int64_t code[2]; + int flavor; + mach_msg_type_number_t old_stateCnt; + natural_t old_state[144]; + } __Request__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Request__mach_exc_subsystem__defined */ + +/* union of all requests */ + +#ifndef __RequestUnion__mach_exc_subsystem__defined +#define __RequestUnion__mach_exc_subsystem__defined +union __RequestUnion__mach_exc_subsystem { + __Request__mach_exception_raise_t Request_mach_exception_raise; + __Request__mach_exception_raise_state_t Request_mach_exception_raise_state; + __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__mach_exc_subsystem__defined */ +/* typedefs for all replies */ + +#ifndef __Reply__mach_exc_subsystem__defined +#define __Reply__mach_exc_subsystem__defined + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + } __Reply__mach_exception_raise_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__mach_exception_raise_state_t; +#ifdef __MigPackStructs +#pragma pack() +#endif + +#ifdef __MigPackStructs +#pragma pack(4) +#endif + typedef struct { + mach_msg_header_t Head; + NDR_record_t NDR; + kern_return_t RetCode; + int flavor; + mach_msg_type_number_t new_stateCnt; + natural_t new_state[144]; + } __Reply__mach_exception_raise_state_identity_t; +#ifdef __MigPackStructs +#pragma pack() +#endif +#endif /* !__Reply__mach_exc_subsystem__defined */ + +/* union of all replies */ + +#ifndef __ReplyUnion__mach_exc_subsystem__defined +#define __ReplyUnion__mach_exc_subsystem__defined +union __ReplyUnion__mach_exc_subsystem { + __Reply__mach_exception_raise_t Reply_mach_exception_raise; + __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state; + __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity; +}; +#endif /* !__RequestUnion__mach_exc_subsystem__defined */ + +#ifndef subsystem_to_name_map_mach_exc +#define subsystem_to_name_map_mach_exc \ + { "mach_exception_raise_OVR", 2405 },\ + { "mach_exception_raise_state_OVR", 2406 },\ + { "mach_exception_raise_state_identity_OVR", 2407 } +#endif + +#ifdef __AfterMigUserHeader +__AfterMigUserHeader +#endif /* __AfterMigUserHeader */ + + +#ifdef mig_external +mig_external +#else +extern +#endif /* mig_external */ +boolean_t mach_exc_server_OVR( + mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + + +#if defined(__cplusplus) + } // extern"C" +#endif + + +#endif /* _mach_exc_user_ */ |