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: 38846 $ 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 #if defined(NN_PROCESSOR_ARM_V6) 30 31 NN_STATIC_ASSERT(TLS_NUM == 16); 32 33 typedef ThreadLocalRegion ThreadLocalBuffer; 34 GetThreadLocalBuffer()35 inline ThreadLocalBuffer* GetThreadLocalBuffer() 36 { 37 return GetThreadLocalRegion(); 38 } 39 40 #elif defined(NN_PROCESSOR_ARM_V5) 41 42 struct ThreadLocalBuffer 43 { 44 uptr tls[TLS_NUM]; 45 }; 46 47 ThreadLocalBuffer s_ThreadLocalBuffers[nn::os::CTR::ARM946ES::NUM_THREAD_INDEX]; 48 49 inline ThreadLocalBuffer* GetThreadLocalBuffer() 50 { 51 return s_ThreadLocalBuffers + nn::os::CTR::ARM946ES::GetThreadIndex(); 52 } 53 54 #endif 55 56 namespace { 57 58 u16 sTLSMap = 0; // Manage TLS allocation state with bits 0 - 15 59 60 /* Please see man pages for details 61 62 63 64 */ IsMappedIndex(s32 index)65inline bool IsMappedIndex(s32 index) 66 { 67 return ((sTLSMap >> index) & 1) == 1; 68 } 69 70 /* Please see man pages for details 71 72 73 74 */ SearchFreeTLSIndex()75s32 SearchFreeTLSIndex() 76 { 77 78 for(int i = 0; i < TLS_NUM; ++i) 79 { 80 if(!IsMappedIndex(i)) 81 { 82 return i; 83 } 84 } 85 return -1; 86 } 87 88 /* Please see man pages for details 89 90 91 92 */ AllocateTLSIndex()93s32 AllocateTLSIndex() 94 { 95 s32 index = SearchFreeTLSIndex(); 96 if(index >= 0 && index < TLS_NUM) 97 { 98 sTLSMap |= (1 << index); 99 } 100 return index; 101 } 102 103 /* Please see man pages for details 104 105 106 107 */ FreeTLSIndex(int index)108s32 FreeTLSIndex(int index) 109 { 110 if(!IsMappedIndex(index)) 111 { 112 return -1; 113 } 114 return sTLSMap &= ~(1 << index); 115 } 116 117 118 } // Namespace 119 ThreadLocalStorage()120ThreadLocalStorage::ThreadLocalStorage() 121 { 122 this->m_Index = AllocateTLSIndex(); 123 NN_TASSERTMSG_(m_Index >= 0, "Out of Thread Local Storage Slot."); 124 if ( m_Index < 0 ) 125 { 126 NN_OS_ERROR_IF_FAILED(ResultExceedTlsLimit()); 127 } 128 } 129 ~ThreadLocalStorage()130ThreadLocalStorage::~ThreadLocalStorage() 131 { 132 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 133 NN_TASSERT_(IsMappedIndex(m_Index)); 134 FreeTLSIndex(m_Index); 135 } 136 GetValue() const137uptr ThreadLocalStorage::GetValue() const 138 { 139 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 140 NN_TASSERT_(IsMappedIndex(m_Index)); 141 if ( IsMappedIndex(m_Index) ) 142 { 143 return GetThreadLocalBuffer()->tls[m_Index]; 144 } 145 else 146 { 147 return 0; 148 } 149 } 150 SetValue(uptr value)151void ThreadLocalStorage::SetValue(uptr value) 152 { 153 NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM); 154 NN_TASSERT_(IsMappedIndex(m_Index)); 155 if ( IsMappedIndex(m_Index) ) 156 { 157 GetThreadLocalBuffer()->tls[m_Index] = value; 158 } 159 } 160 ClearAllSlots()161void ThreadLocalStorage::ClearAllSlots() 162 { 163 ThreadLocalBuffer& tlr = *GetThreadLocalBuffer(); 164 165 for( int i = 0; i < TLS_NUM; ++i ) 166 { 167 tlr.tls[i] = 0; 168 } 169 } 170 171 }} // namespace nn::os 172 173