1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_Synchronization.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: 46347 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/os/os_Synchronization.h>
17 #include <nn/os/os_Result.h>
18 #include <nn/assert.h>
19 #include <nn/Handle.h>
20 #include <nn/svc/svc_Stub.h>
21 #include <nn/util/util_StaticAssert.h>
22 //---------------------------------------------------------------------------
23 
24 using namespace nn;
25 //using namespace nn::svc;
26 
27 namespace nn{ namespace os{
28 
29 // TODO: Must move to ARM
30 namespace {
31 
32     struct WaitMultipleObjectsArgs {
33         s32* pOut;
34         WaitObject** objs;
35         s32 numHandles;
36         bool waitAll;
37         u8 padding[3];
38         s64* timeout;
39     };
40 
WaitMultipleImpl(WaitMultipleObjectsArgs * args,nn::Handle * handles)41     nn::Result WaitMultipleImpl(WaitMultipleObjectsArgs* args, nn::Handle* handles)
42     {
43         for (int i = 0; i < args->numHandles; ++i)
44         {
45             handles[i] = args->objs[i]->GetHandle();
46         }
47         return nn::svc::WaitSynchronization(args->pOut, handles, args->numHandles, args->waitAll, *args->timeout);
48     }
49 
50     NN_STATIC_ASSERT(sizeof(nn::Handle) == 4);
WaitMultipleImplWithAlloca(WaitMultipleObjectsArgs *,s32,nn::Result (*)(WaitMultipleObjectsArgs *,nn::Handle *))51     asm nn::Result WaitMultipleImplWithAlloca(WaitMultipleObjectsArgs*, s32, nn::Result (*)(WaitMultipleObjectsArgs*, nn::Handle*))
52     {
53         ARM
54         PRESERVE8
55 
56         push  {lr}
57 
58         bics  r3, r1, #1
59         addne r1, r1, #1 // Add 1 if r1 is odd (for 8-byte alignment)
60 
61         mov   r3, r1, LSL #2
62 
63         sub   sp, sp, r3
64         mov   r1, sp
65 
66         push  {r3}
67 
68         blx   r2
69 
70         pop   {r3}
71         add   sp, sp, r3
72 
73         pop   {pc}
74     }
75 
76 }
77 
WaitMultiple(s32 * pOut,WaitObject * objs[],s32 numHandles,bool waitAll,s64 timeout)78 nn::Result WaitObject::WaitMultiple(s32* pOut, WaitObject* objs[], s32 numHandles, bool waitAll, s64 timeout)
79 {
80     // TORIAEZU: If there are about 10 it is usually enough.
81     const s32 STATIC_ALLOCATE_SIZE = 10;
82     if (numHandles <= STATIC_ALLOCATE_SIZE)
83     {
84         nn::Handle handles[STATIC_ALLOCATE_SIZE];
85         for (int i = 0; i < numHandles; ++i)
86         {
87             handles[i] = objs[i]->GetHandle();
88         }
89         return nn::svc::WaitSynchronization(pOut, handles, numHandles, waitAll, timeout);
90     }
91     else
92     {
93         WaitMultipleObjectsArgs args;
94         args.pOut = pOut;
95         args.objs = objs;
96         args.numHandles = numHandles;
97         args.waitAll = waitAll;
98         args.timeout = &timeout;
99         return WaitMultipleImplWithAlloca(&args, numHandles, &WaitMultipleImpl);
100     }
101 }
102 
103 }} // namespace nn::os
104 
105 
106 using namespace nn::os;
107 
108 extern "C" {
109 
nnosWaitObjectWaitOne(nnosWaitObject * p,s64 nanoSecondsTimeout)110 bool nnosWaitObjectWaitOne(nnosWaitObject* p, s64 nanoSecondsTimeout)
111 {
112     WaitObject* pWaitObject = reinterpret_cast<WaitObject*>(p);
113     return pWaitObject->WaitOne(nn::fnd::TimeSpan::FromNanoSeconds(nanoSecondsTimeout));
114 }
115 
nnosWaitObjectWaitAll(nnosWaitObject * objs[],s32 numObjects,s64 nanoSecondsTimeout)116 bool nnosWaitObjectWaitAll(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout)
117 {
118     WaitObject** pWaitObjects = reinterpret_cast<WaitObject**>(objs);
119     return WaitObject::WaitAll(pWaitObjects, numObjects, nn::fnd::TimeSpan::FromNanoSeconds(nanoSecondsTimeout));
120 }
121 
nnosWaitObjectWaitAny(nnosWaitObject * objs[],s32 numObjects,s64 nanoSecondsTimeout)122 s32 nnosWaitObjectWaitAny(nnosWaitObject* objs[], s32 numObjects, s64 nanoSecondsTimeout)
123 {
124     WaitObject** pWaitObjects = reinterpret_cast<WaitObject**>(objs);
125     return WaitObject::WaitAny(pWaitObjects, numObjects, nn::fnd::TimeSpan::FromNanoSeconds(nanoSecondsTimeout));
126 }
127 
128 }
129