1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #ifndef K_SPIN_LOCK_H
6 #define K_SPIN_LOCK_H
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 /** @addtogroup aos_rhino spinlock
13  *  Spinlock can be used for mutual exclusion between multi-cores.
14  *
15  *  @{
16  */
17 
18 /**
19  * spinlock object
20  */
21 typedef struct {
22     volatile uint32_t owner;  /* cpu index of owner */
23 } kspinlock_t;
24 
25 /* Be careful nested spin lock is not supported */
26 #if (RHINO_CONFIG_CPU_NUM > 1)
27 
28 /**
29  * Waiting for all cores.
30  * Can only be used once for multi-core synchronization after initialization.
31  *
32  * @param[in]   NULL
33  *
34  * @return  NULL
35  */
36 extern void k_wait_allcores(void);
37 
38 
39 #define KRHINO_SPINLOCK_FREE_VAL                        0xB33FFFFFu
40 
41 /**
42  * Lock a spinlock, recursive locking is allowed.
43  *
44  * @param[in]   lock    the spinlock
45  *
46  * @return  NULL
47  */
48 #define krhino_spin_lock(lock)                          do {                                            \
49                                                             cpu_spin_lock((lock));                      \
50                                                         } while (0)                                     \
51 
52 /**
53  * Unlock a spinlock, recursive locking is allowed.
54  *
55  * @param[in]   lock    the spinlock
56  *
57  * @return  NULL
58  */
59 #define krhino_spin_unlock(lock)                        do {                                            \
60                                                             cpu_spin_unlock((lock));                    \
61                                                         } while (0)
62 
63 /**
64  * Lock a spinlock and mask interrupt, recursive locking is allowed.
65  *
66  * @param[in]   lock    the spinlock
67  * @param[out]  flags   the irq status before locking
68  *
69  * @return  NULL
70  */
71 #define krhino_spin_lock_irq_save(lock, flags)          do {                                            \
72                                                             flags          = cpu_intrpt_save();         \
73                                                             cpu_spin_lock((lock));                      \
74                                                         } while (0)
75 
76 /**
77  * Unlock a spinlock and restore interrupt masking status, recursive locking is allowed.
78  *
79  * @param[in]   lock    the spinlock
80  * @param[in]   flags   the irq status before locking
81  *
82  * @return  NULL
83  */
84 #define krhino_spin_unlock_irq_restore(lock, flags)     do {                                            \
85                                                             cpu_spin_unlock((lock));                    \
86                                                             cpu_intrpt_restore(flags);                  \
87                                                         } while (0)
88 
89 /**
90  * Init a spinlock.
91  *
92  * @param[in]   lock    the spinlock
93  *
94  * @return  NULL
95  */
96 #define krhino_spin_lock_init(lock)                     do {                                            \
97                                                             kspinlock_t *s = (kspinlock_t *)(lock);     \
98                                                             s->owner       = KRHINO_SPINLOCK_FREE_VAL;  \
99                                                         } while(0)
100 #else
101 /* single-core spinlock */
102 #define krhino_spin_lock(lock)                          krhino_sched_disable();
103 #define krhino_spin_unlock(lock)                        krhino_sched_enable();
104 
105 #define krhino_spin_lock_irq_save(lock, flags)          do {                                            \
106                                                             (void)lock;                                 \
107                                                             flags          = cpu_intrpt_save();         \
108                                                         } while (0)
109 
110 #define krhino_spin_unlock_irq_restore(lock, flags)     do {                                            \
111                                                             (void)lock;                                 \
112                                                             cpu_intrpt_restore(flags);                  \
113                                                         } while (0)
114 
115 #define krhino_spin_lock_init(lock)
116 #endif  /* RHINO_CONFIG_CPU_NUM > 1 */
117 
118 /** @} */
119 
120 #ifdef __cplusplus
121 }
122 #endif
123 
124 #endif  /* K_SPIN_LOCK_H */
125 
126