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: 23600 $
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 namespace {
29 
30 
31 u16 sTLSMap = 0;   // 0-15 ビットで TLS 確保状況を管理
32 
33 /*!
34     @brief スロットがマッピング済みかどうかを判定します。
35 
36     @return スロットがマッピング済みであれば true を返します。
37 */
IsMappedIndex(s32 index)38 inline bool IsMappedIndex(s32 index)
39 {
40     return ((sTLSMap >> index) & 1) == 1;
41 }
42 
43 /*!
44     @brief 空いているスレッドローカルストレージのスロットを探索します。
45 
46     @return 空いているスロット番号を返します。スロットに空きがなかった場合は -1 を返します。
47 */
SearchFreeTLSIndex()48 s32 SearchFreeTLSIndex()
49 {
50 
51     for(int i = 0; i < TLS_NUM; ++i)
52     {
53         if(!IsMappedIndex(i))
54         {
55             return i;
56         }
57     }
58     return -1;
59 }
60 
61 /*!
62     @brief スレッドローカルストレージからスロットを確保します。
63 
64     @return 確保したスロット番号を返します。スロットに空きがなかった場合は -1 を返します。
65 */
AllocateTLSIndex()66 s32 AllocateTLSIndex()
67 {
68     s32 index = SearchFreeTLSIndex();
69     if(index >= 0 && index < TLS_NUM)
70     {
71         sTLSMap |= (1 << index);
72     }
73     return index;
74 }
75 
76 /*!
77     @brief スレッドローカルストレージにスロットを解放します。
78 
79     @param[in] スロット番号
80 */
FreeTLSIndex(int index)81 s32 FreeTLSIndex(int index)
82 {
83     if(!IsMappedIndex(index))
84     {
85         return -1;
86     }
87     return sTLSMap &= ~(1 << index);
88 }
89 
90 
91 } // namespace
92 
ThreadLocalStorage()93 ThreadLocalStorage::ThreadLocalStorage()
94 {
95     this->m_Index = AllocateTLSIndex();
96     NN_TASSERTMSG_(m_Index >= 0, "Out of Thread Local Storage Slot.");
97 }
98 
~ThreadLocalStorage()99 ThreadLocalStorage::~ThreadLocalStorage()
100 {
101     NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM);
102     NN_TASSERT_(IsMappedIndex(m_Index));
103     FreeTLSIndex(m_Index);
104 }
105 
GetValue() const106 uptr ThreadLocalStorage::GetValue() const
107 {
108     NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM);
109     NN_TASSERT_(IsMappedIndex(m_Index));
110     return GetThreadLocalRegion()->tls[m_Index];
111 }
112 
SetValue(uptr value)113 void ThreadLocalStorage::SetValue(uptr value)
114 {
115     NN_TASSERT_(m_Index >= 0 && m_Index < TLS_NUM);
116     NN_TASSERT_(IsMappedIndex(m_Index));
117     GetThreadLocalRegion()->tls[m_Index] = value;
118 }
119 
ClearAllSlots()120 void ThreadLocalStorage::ClearAllSlots()
121 {
122     ThreadLocalRegion& tlr = *GetThreadLocalRegion();
123 
124     for( int i = 0; i < TLS_NUM; ++i )
125     {
126         tlr.tls[i] = 0;
127     }
128 }
129 
130 }} // namespace nn::os
131 
132