1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: os_ThreadLocalStorage.cpp 4 5 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: 34323 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include <nn/os/os_ThreadLocalStorage.h> 17 #include <nn/os/os_Result.h> 18 #include <nn/os/os_Private.h> 19 #include <nn/assert.h> 20 #include <nn/hw/ARM/reg_access.h> 21 //--------------------------------------------------------------------------- 22 23 using namespace nn; 24 using nn::Result; 25 26 namespace nn{ namespace os{ 27 28 #if defined(NN_PROCESSOR_ARM_V6) 29 30 NN_STATIC_ASSERT(TLS_NUM == 16); 31 32 typedef ThreadLocalRegion ThreadLocalBuffer; 33 GetThreadLocalBuffer()34 inline ThreadLocalBuffer* GetThreadLocalBuffer() 35 { 36 return GetThreadLocalRegion(); 37 } 38 39 #elif defined(NN_PROCESSOR_ARM_V5) 40 41 struct ThreadLocalBuffer 42 { 43 uptr tls[TLS_NUM]; 44 }; 45 46 ThreadLocalBuffer s_ThreadLocalBuffers[nn::os::CTR::ARM946ES::NUM_THREAD_INDEX]; 47 48 inline ThreadLocalBuffer* GetThreadLocalBuffer() 49 { 50 return s_ThreadLocalBuffers + nn::os::CTR::ARM946ES::GetThreadIndex(); 51 } 52 53 #endif 54 55 namespace { 56 57 u16 sTLSMap = 0; // Manage TLS allocation state with bits 0 - 15 58 59 /* Please see man pages for details 60 61 62 63 */ IsMappedIndex(s32 index)64inline bool IsMappedIndex(s32 index) 65 { 66 return ((sTLSMap >> index) & 1) == 1; 67 } 68 69 /* Please see man pages for details 70 71 72 73 */ SearchFreeTLSIndex()74s32 SearchFreeTLSIndex() 75 { 76 77 for(int i = 0; i < TLS_NUM; ++i) 78 { 79 if(!IsMappedIndex(i)) 80 { 81 return i; 82 } 83 } 84 return -1; 85 } 86 87 /* Please see man pages for details 88 89 90 91 */ AllocateTLSIndex()92s32 AllocateTLSIndex() 93 { 94 s32 index = SearchFreeTLSIndex(); 95 if(index >= 0 && index < TLS_NUM) 96 { 97 sTLSMap |= (1 << index); 98 } 99 return index; 100 } 101 102 /* Please see man pages for details 103 104 105 106 */ FreeTLSIndex(int index)107s32 FreeTLSIndex(int index) 108 { 109 if(!IsMappedIndex(index)) 110 { 111 return -1; 112 } 113 return sTLSMap &= ~(1 << index); 114 } 115 116 117 } // Namespace 118 ThreadLocalStorage()119ThreadLocalStorage::ThreadLocalStorage() 120 { 121 this->m_Index = AllocateTLSIndex(); 122 NN_TASSERTMSG_(m_Index >= 0, "Out of Thread Local Storage Slot."); 123 } 124 ~ThreadLocalStorage()125ThreadLocalStorage::~ThreadLocalStorage() 126 { 127 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 128 NN_TASSERT_(IsMappedIndex(m_Index)); 129 FreeTLSIndex(m_Index); 130 } 131 GetValue() const132uptr ThreadLocalStorage::GetValue() const 133 { 134 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 135 NN_TASSERT_(IsMappedIndex(m_Index)); 136 return GetThreadLocalBuffer()->tls[m_Index]; 137 } 138 SetValue(uptr value)139void ThreadLocalStorage::SetValue(uptr value) 140 { 141 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 142 NN_TASSERT_(IsMappedIndex(m_Index)); 143 GetThreadLocalBuffer()->tls[m_Index] = value; 144 } 145 ClearAllSlots()146void ThreadLocalStorage::ClearAllSlots() 147 { 148 ThreadLocalBuffer& tlr = *GetThreadLocalBuffer(); 149 150 for( int i = 0; i < TLS_NUM; ++i ) 151 { 152 tlr.tls[i] = 0; 153 } 154 } 155 156 }} // namespace nn::os 157 158