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)65 inline 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()75 s32 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()93 s32 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)108 s32 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()120 ThreadLocalStorage::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()130 ThreadLocalStorage::~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() const137 uptr 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)151 void 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()161 void 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