1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_Default.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: 17465 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/Result.h>
17 #include <nn/os.h>
18
19 namespace nn { namespace os {
20
21 #if NN_PLATFORM_HAS_MMU
22 namespace
23 {
24 template <typename T>
RoundUp(T x,int r)25 T RoundUp(T x, int r)
26 {
27 return (x + (r - 1)) & ~(r - 1);
28 }
29
30
31 class DefaultAutoStackManager : public nn::os::Thread::AutoStackManager
32 {
33 private:
34 static const size_t DESTRUCTOR_STACK_SIZE = 512;
35
36 private:
37 nn::os::Mutex m_DestructorMutex; //!< スタック領域解放処理用同期オブジェクト
38 nn::os::StackBuffer<DESTRUCTOR_STACK_SIZE> m_DestructorStack;
39
40 public:
DefaultAutoStackManager()41 DefaultAutoStackManager()
42 : m_DestructorMutex(false)
43 {
44 }
45
Construct(size_t stackSize)46 virtual void* Construct(size_t stackSize)
47 {
48 nnosStackMemoryBlock stackBlock;
49 nnosStackMemoryBlockAllocate(&stackBlock, stackSize);
50
51 uptr stackBottom = nnosStackMemoryBlockGetStackBottom(&stackBlock);
52 stackBottom -= RoundUp(sizeof(nnosStackMemoryBlock), 8);
53
54 nnosStackMemoryBlock* pBlockOnStack = reinterpret_cast<nnosStackMemoryBlock*>(stackBottom);
55
56 nnosStackMemoryBlockInitialize(pBlockOnStack);
57 nn::os::detail::Switch(
58 reinterpret_cast<nn::os::StackMemoryBlock*>(pBlockOnStack),
59 reinterpret_cast<nn::os::StackMemoryBlock*>(&stackBlock) );
60
61 return reinterpret_cast<void*>(stackBottom);
62 }
63
Destruct(void * pStackBottom,bool isError)64 virtual void Destruct(void* pStackBottom, bool isError)
65 {
66 if( isError )
67 {
68 FreeStack(reinterpret_cast<nnosStackMemoryBlock*>(pStackBottom));
69 }
70 else
71 {
72 // 複数スレッドで同時にスタック領域解放処理が発生しないようにロックします。
73 m_DestructorMutex.Lock();
74
75 // スレッド用スタックを破棄します。
76 InvokeOnOtherStack(m_DestructorStack.GetStackBottom(), &FreeStack, pStackBottom, __return_address());
77 }
78 }
79
80 private:
FreeStack(void * pStackBottom)81 static void FreeStack(void* pStackBottom)
82 {
83 nnosStackMemoryBlock* pBlockOnStack = reinterpret_cast<nnosStackMemoryBlock*>(pStackBottom);
84 nnosStackMemoryBlockFree(pBlockOnStack);
85 }
86
InvokeOnOtherStack(uptr stackBottom NN_IS_UNUSED_VAR,void (* f)(void *)NN_IS_UNUSED_VAR,void * param NN_IS_UNUSED_VAR,uptr returnAddr NN_IS_UNUSED_VAR)87 static asm void InvokeOnOtherStack(
88 uptr stackBottom NN_IS_UNUSED_VAR,
89 void (*f)(void*) NN_IS_UNUSED_VAR,
90 void* param NN_IS_UNUSED_VAR,
91 uptr returnAddr NN_IS_UNUSED_VAR)
92 {
93 ARM
94
95 // r0: stackBottom
96 // r1: f
97 // r2: param
98 // r3: returnAddr
99
100 mov sp, r0
101 mov r0, r2
102 mov lr, r3
103
104 // r0: param
105 // r1: f
106 // lr: returnAddr
107
108 bx r1
109 }
110 };
111
112 DefaultAutoStackManager s_AutoStackManager;
113 }
114 #endif // if NN_PLATFORM_HAS_MMU
115
116
SetDefaultAutoStackManager()117 void SetDefaultAutoStackManager()
118 {
119 #if NN_PLATFORM_HAS_MMU
120 nn::os::Thread::SetAutoStackManager(&s_AutoStackManager);
121 #endif // if NN_PLATFORM_HAS_MMU
122 }
123
124
125
126 }}
127