-
Notifications
You must be signed in to change notification settings - Fork 44
/
atomic.h
50 lines (46 loc) · 2.67 KB
/
atomic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifndef __ATOMIC_H
#define __ATOMIC_H
#include <stdint.h>
// The following macros create a spinlock with name <name>. A spinlock is a
// 16-bit integer. To lock the spinlock, call <name>_lock. To release the
// spinlock, call <name>_unlock. To try to lock the spinlock and return
// true if locking succeeded, call <name>_trylock. This will return true if the
// lock was not locked before (lock was acquired). To reset the spinlock, call
// <name>_reset. This forcefully sets the lock to 0. Spinlocks must be located
// in the near data space. The lock status is held in the uppermost bit (bit15)
// and the lower bits may be used to hold other information. This _H macro
// should be placed in header files. The following _C macro must be placed in
// ONLY ONE source file. If a spinlock is not public to other modules, use both
// the _C and _H macros in the source file.
#define DECLARE_SPINLOCK_H(name) \
extern uint16_t __attribute__((near)) _##name##_raw_lock; \
static inline void name##_reset(void) { \
_##name##_raw_lock = 0; \
} \
static inline void name##_unlock(void) { \
__asm__ volatile ( \
"bclr %0, #15" \
:: "U" (_##name##_raw_lock) \
); \
} \
static inline unsigned char name##_trylock(void) { \
unsigned char ret; \
__asm__ volatile ( \
"btsts %1, #15\n" \
"bra z, 0f\n" \
"clr %0\n" \
"bra 1f\n" \
"0: setm %0\n" \
"1:" \
: "=d" (ret) \
: "U" (_##name##_raw_lock) \
: "cc" \
); \
return ret; \
} \
static void name##_lock(void) { \
while(!name##_trylock()); \
}
#define DECLARE_SPINLOCK_C(name) \
uint16_t __attribute__((near)) _##name##_raw_lock;
#endif