1 /*---------------------------------------------------------------------------*
2   Project:     OS Library
3   File:        OSSync.h
4 
5   Copyright (C) 2010-2011 Nintendo.  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  *---------------------------------------------------------------------------*/
14 
15 #ifndef __OSSYNC_H__
16 #define __OSSYNC_H__
17 
18 #include <types.h>
19 #include <cafe/os/OSCore.h>
20 #include <cafe/os/OSTime.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #define OS_CORE_MAIN (1)
27 #define OS_CORE_SUB1 (0)
28 #define OS_CORE_SUB2 (2)
29 
30 #define OS_CORE_SUB1_MASK (1 << 0)
31 #define OS_CORE_MAIN_MASK (1 << 1)
32 #define OS_CORE_SUB2_MASK (1 << 2)
33 #define OS_CORE_ALL_MASK  (OS_CORE_SUB1_MASK | OS_CORE_MAIN_MASK | OS_CORE_SUB2_MASK)
34 
35 #define OS_WAIT_CORE_SUB1 (1 << 0)
36 #define OS_WAIT_CORE_MAIN (1 << 1)
37 #define OS_WAIT_CORE_SUB2 (1 << 2)
38 
39 #define OS_WAIT_CORE_NONE (0)
40 #define OS_WAIT_CORE_ALL (OS_WAIT_CORE_SUB1 | OS_WAIT_CORE_MAIN | OS_WAIT_CORE_SUB2)
41 
42 //
43 // Basic synchonization types
44 //
45 
46 typedef u32 OSSpinLockID;
47 typedef u32 OSEventID;
48 typedef u32 OSRendezvousID;
49 
50 //
51 // SpinLocks
52 //
53 SET_STRUCT_ALIGN(16)
54 typedef struct
55 {
56     u32           spinlock;
57     OSSpinLockID  spinlock_id;
58     u32           recursionCount; // allow recursive locking
59     u32           interrupts_enabled;
60 } ATTRIB_STRUCT_ALIGN(16) OSSpinLock;
61 SET_STRUCT_ALIGN(1)
62 
63 void OSInitSpinLock(OSSpinLock *spinlock);
64 BOOL OSAcquireSpinLock(OSSpinLock *spinlock);
65 BOOL OSTryAcquireSpinLock(OSSpinLock *spinlock);
66 BOOL OSTryAcquireSpinLockWithTimeout(OSSpinLock *spinlock, OSTimeNanoseconds timeout);
67 BOOL OSReleaseSpinLock(OSSpinLock *spinlock);
68 
69 //
70 // OSUninterruptibleSpinLock
71 // Spinlocks which disable then re-enable interrupts to prevent priority inversion problems.
72 //
73 // (1) Upon return from the "Acquire" functions, if the result is TRUE then interrupts are
74 //     DISABLED.
75 //
76 // (2) It is EXTREMELY IMPORTANT that code which follows the uninterruptible spinlock acquire
77 //     not run for long periods of time. No more than 1000 cycles would be a good rule-of-thumb.
78 //
79 // (3) DO NOT switch threads (or call functions which switch threads) with interrupts
80 //     disabled because interrupt-disabling is per-thread and this is usually not
81 //     what the originating thread intends to happen.
82 
83 BOOL OSUninterruptibleSpinLock_Acquire(OSSpinLock *inSpinlock);
84 BOOL OSUninterruptibleSpinLock_TryAcquire(OSSpinLock *inSpinLock);
85 BOOL OSUninterruptibleSpinLock_TryAcquireWithTimeout(OSSpinLock *inSpinLock, OSTimeNanoseconds timeout);
86 BOOL OSUninterruptibleSpinLock_Release(OSSpinLock *inSpinlock);
87 
88 //
89 // Rendezvous
90 //
91 
92 typedef struct
93 {
94     volatile u32    core[MAX_SYSTEM_CORES];
95     OSRendezvousID  rendezvous_id;
96 } OSRendezvous;
97 
98 void OSInitRendezvous(OSRendezvous *ren);
99 BOOL OSWaitRendezvous(OSRendezvous *ren, u32 wmask);
100 BOOL OSWaitRendezvousWithTimeout(OSRendezvous *ren, u32 wmask, OSTimeNanoseconds timeout);
101 
102 
103 //
104 // Misc.
105 //
106 
107 // Wait until all memory writes have flushed to ram
108 // (Extremely expensive, can be many 100s of cycles)
109 void OSMemoryBarrier(void);
110 
111 // Wait until all memory writes have flushed to other cores
112 void OSCoherencyBarrier(void);
113 
114 #ifdef __cplusplus
115 }
116 #endif
117 
118 #endif // __OSSYNC_H__
119 
120