1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_SimpleAutoStackManagerBase.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:$
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/config.h>
17 #if NN_PLATFORM_HAS_MMU
18 
19 #include <nn/os.h>
20 #include <nn/fnd.h>
21 #include <nn/math.h>
22 
23 namespace nn { namespace os {
24 
25     namespace
26     {
27         struct DataOnStack
28         {
29             void*           pHead;
30         };
31     }
32 
~SimpleAutoStackManagerBase()33     SimpleAutoStackManagerBase::~SimpleAutoStackManagerBase()
34     {
35         Finalize();
36     }
37 
Initialize(fnd::IAllocator * pAllocator,uptr stackBottom)38     void SimpleAutoStackManagerBase::Initialize(fnd::IAllocator* pAllocator, uptr stackBottom)
39     {
40         NN_TASSERT_( ! IsInitialized());
41         NN_POINTER_TASSERT_(pAllocator);
42 
43         m_pAllocator = pAllocator;
44         m_DestructorStackBottom = stackBottom;
45         m_DestructorMutex.Initialize();
46     }
47 
Finalize()48     uptr SimpleAutoStackManagerBase::Finalize()
49     {
50         uptr stackBottom = m_DestructorStackBottom;
51 
52         if( IsInitialized() )
53         {
54             m_DestructorStackBottom = NULL;
55             m_DestructorMutex.Finalize();
56         }
57 
58         return stackBottom;
59     }
60 
61 
DestructImpl(void * pStackBottom,uptr returnAddress,bool isError)62     void SimpleAutoStackManagerBase::DestructImpl(void* pStackBottom, uptr returnAddress, bool isError)
63     {
64         NN_TASSERT_(IsInitialized());
65 
66         if( isError )
67         {
68             FreeStack(pStackBottom);
69         }
70         else
71         {
72             // Lock so that multiple threads do not simultaneously execute a process that clears the stack.
73             m_DestructorMutex.Lock();
74 
75             // Destroy the thread stack
76             CallFreeStackOnOtherStack(
77                 pStackBottom,
78                 math::RoundDown(m_DestructorStackBottom, 8),
79                 returnAddress );
80         }
81     }
82 
CallFreeStackOnOtherStack(void * pStackBottom NN_IS_UNUSED_VAR,uptr stackBottom NN_IS_UNUSED_VAR,uptr returnAddress NN_IS_UNUSED_VAR)83     asm void SimpleAutoStackManagerBase::CallFreeStackOnOtherStack(
84         void*   pStackBottom    NN_IS_UNUSED_VAR,
85         uptr    stackBottom     NN_IS_UNUSED_VAR,
86         uptr    returnAddress   NN_IS_UNUSED_VAR )
87     {
88         ARM
89         PRESERVE8
90 
91         // r0: this
92         // r1: pStackBottom
93         // r2: stackBottom
94         // r3: returnAddress
95 
96         mov     sp, r2
97         mov     lr, r3
98 
99         ldr     r2, [r0]
100         ldr     r2, [r2, #__vcall_offsetof_vfunc(SimpleAutoStackManagerBase, FreeStack)]
101 
102         // r0: this
103         // r1: pStackBottom
104         // r2: FreeStack
105         // lr: returnAddr
106 
107         bx      r2
108     }
109 
110 
111 }}  //  namespace nn::os
112 
113 #endif  // if NN_PLATFORM_HAS_MMU
114