1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: os_ThreadLocalStorage.cpp 4 5 Copyright (C)2009-2012 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: 47384 $ 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/os/os_ErrorHandlerSelect.h> 20 #include <nn/assert.h> 21 #include <nn/hw/ARM/reg_access.h> 22 //--------------------------------------------------------------------------- 23 24 using namespace nn; 25 using nn::Result; 26 27 namespace nn{ namespace os{ 28 29 namespace 30 { 31 #if defined(NN_PROCESSOR_ARM_V6) 32 NN_STATIC_ASSERT(TLS_NUM == 16); 33 34 typedef ThreadLocalRegion ThreadLocalBuffer; 35 GetThreadLocalBuffer()36 inline ThreadLocalBuffer* GetThreadLocalBuffer() 37 { 38 return GetThreadLocalRegion(); 39 } 40 #elif defined(NN_PROCESSOR_ARM_V5) 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 #endif 53 54 u16 sTLSMap = 0; // Manages TLS allocation status with bits 0 to 15 55 56 /* Please see man pages for details 57 58 59 60 */ IsMappedIndex(s32 index)61 inline bool IsMappedIndex(s32 index) 62 { 63 if( (index < 0) || (TLS_NUM <= index) ) 64 { 65 return false; 66 } 67 68 return ((sTLSMap >> index) & 1) == 1; 69 } 70 71 /* Please see man pages for details 72 73 74 75 */ SearchFreeTLSIndex()76 s32 SearchFreeTLSIndex() 77 { 78 79 for(int i = 0; i < TLS_NUM; ++i) 80 { 81 if(!IsMappedIndex(i)) 82 { 83 return i; 84 } 85 } 86 return -1; 87 } 88 89 /* Please see man pages for details 90 91 92 93 */ AllocateTLSIndex()94 s32 AllocateTLSIndex() 95 { 96 s32 index = SearchFreeTLSIndex(); 97 if(index >= 0 && index < TLS_NUM) 98 { 99 sTLSMap |= (1 << index); 100 } 101 return index; 102 } 103 104 /* Please see man pages for details 105 106 107 108 */ FreeTLSIndex(int index)109 s32 FreeTLSIndex(int index) 110 { 111 if(!IsMappedIndex(index)) 112 { 113 return -1; 114 } 115 return sTLSMap &= ~(1 << index); 116 } 117 118 } // Namespace 119 120 121 ThreadLocalStorage()122ThreadLocalStorage::ThreadLocalStorage() 123 { 124 Initialize(); 125 } 126 ~ThreadLocalStorage()127ThreadLocalStorage::~ThreadLocalStorage() 128 { 129 if( IsMappedIndex(m_Index) ) 130 { 131 Finalize(); 132 } 133 } 134 Initialize()135void ThreadLocalStorage::Initialize() 136 { 137 this->m_Index = AllocateTLSIndex(); 138 NN_TASSERTMSG_(m_Index >= 0, "Out of Thread Local Storage Slot."); 139 if ( m_Index < 0 ) 140 { 141 NN_OS_ERROR_IF_FAILED(ResultExceedTlsLimit()); 142 } 143 } 144 Finalize()145void ThreadLocalStorage::Finalize() 146 { 147 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 148 NN_TASSERT_(IsMappedIndex(m_Index)); 149 150 FreeTLSIndex(m_Index); 151 } 152 GetValue() const153uptr ThreadLocalStorage::GetValue() const 154 { 155 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 156 NN_TASSERT_(IsMappedIndex(m_Index)); 157 158 return GetThreadLocalBuffer()->tls[m_Index]; 159 } 160 SetValue(uptr value)161void ThreadLocalStorage::SetValue(uptr value) 162 { 163 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 164 NN_TASSERT_(IsMappedIndex(m_Index)); 165 NN_TASSERT_(IsMappedIndex(m_Index)); 166 167 GetThreadLocalBuffer()->tls[m_Index] = value; 168 } 169 SetValueTo(void * pTo,uptr value)170void ThreadLocalStorage::SetValueTo(void* pTo, uptr value) 171 { 172 ThreadLocalBuffer* pTlb = reinterpret_cast<ThreadLocalBuffer*>(pTo); 173 pTlb->tls[m_Index] = value; 174 } 175 ClearAllSlots()176void ThreadLocalStorage::ClearAllSlots() 177 { 178 ThreadLocalBuffer& tlr = *GetThreadLocalBuffer(); 179 180 for( int i = 0; i < TLS_NUM; ++i ) 181 { 182 tlr.tls[i] = 0; 183 } 184 } 185 186 }} // namespace nn::os 187 188