hermit/syscalls/
spinlock.rs1use alloc::boxed::Box;
2
3use hermit_sync::{InterruptTicketMutex, InterruptTicketMutexGuard, TicketMutex, TicketMutexGuard};
4
5use crate::errno::*;
6
7pub struct SpinlockContainer<'a> {
8 lock: TicketMutex<()>,
9 guard: Option<TicketMutexGuard<'a, ()>>,
10}
11
12pub struct SpinlockIrqSaveContainer<'a> {
13 lock: InterruptTicketMutex<()>,
14 guard: Option<InterruptTicketMutexGuard<'a, ()>>,
15}
16
17#[hermit_macro::system]
18#[unsafe(no_mangle)]
19pub unsafe extern "C" fn sys_spinlock_init(lock: *mut *mut SpinlockContainer<'_>) -> i32 {
20 if lock.is_null() {
21 return -EINVAL;
22 }
23
24 let boxed_container = Box::new(SpinlockContainer {
25 lock: TicketMutex::new(()),
26 guard: None,
27 });
28 unsafe {
29 *lock = Box::into_raw(boxed_container);
30 }
31 0
32}
33
34#[hermit_macro::system]
35#[unsafe(no_mangle)]
36pub unsafe extern "C" fn sys_spinlock_destroy(lock: *mut SpinlockContainer<'_>) -> i32 {
37 if lock.is_null() {
38 return -EINVAL;
39 }
40
41 unsafe {
43 drop(Box::from_raw(lock));
44 }
45 0
46}
47
48#[hermit_macro::system]
49#[unsafe(no_mangle)]
50pub unsafe extern "C" fn sys_spinlock_lock(lock: *mut SpinlockContainer<'_>) -> i32 {
51 if lock.is_null() {
52 return -EINVAL;
53 }
54
55 let container = unsafe { &mut *lock };
56 assert!(
57 container.guard.is_none(),
58 "Called sys_spinlock_lock when a lock is already held!"
59 );
60 container.guard = Some(container.lock.lock());
61 0
62}
63
64#[hermit_macro::system]
65#[unsafe(no_mangle)]
66pub unsafe extern "C" fn sys_spinlock_unlock(lock: *mut SpinlockContainer<'_>) -> i32 {
67 if lock.is_null() {
68 return -EINVAL;
69 }
70
71 let container = unsafe { &mut *lock };
72 assert!(
73 container.guard.is_some(),
74 "Called sys_spinlock_unlock when no lock is currently held!"
75 );
76 container.guard = None;
77 0
78}
79
80#[hermit_macro::system]
81#[unsafe(no_mangle)]
82pub unsafe extern "C" fn sys_spinlock_irqsave_init(
83 lock: *mut *mut SpinlockIrqSaveContainer<'_>,
84) -> i32 {
85 if lock.is_null() {
86 return -EINVAL;
87 }
88
89 let boxed_container = Box::new(SpinlockIrqSaveContainer {
90 lock: InterruptTicketMutex::new(()),
91 guard: None,
92 });
93 unsafe {
94 *lock = Box::into_raw(boxed_container);
95 }
96 0
97}
98
99#[hermit_macro::system]
100#[unsafe(no_mangle)]
101pub unsafe extern "C" fn sys_spinlock_irqsave_destroy(
102 lock: *mut SpinlockIrqSaveContainer<'_>,
103) -> i32 {
104 if lock.is_null() {
105 return -EINVAL;
106 }
107
108 unsafe {
110 drop(Box::from_raw(lock));
111 }
112 0
113}
114
115#[hermit_macro::system]
116#[unsafe(no_mangle)]
117pub unsafe extern "C" fn sys_spinlock_irqsave_lock(lock: *mut SpinlockIrqSaveContainer<'_>) -> i32 {
118 if lock.is_null() {
119 return -EINVAL;
120 }
121
122 let container = unsafe { &mut *lock };
123 assert!(
124 container.guard.is_none(),
125 "Called sys_spinlock_irqsave_lock when a lock is already held!"
126 );
127 container.guard = Some(container.lock.lock());
128 0
129}
130
131#[hermit_macro::system]
132#[unsafe(no_mangle)]
133pub unsafe extern "C" fn sys_spinlock_irqsave_unlock(
134 lock: *mut SpinlockIrqSaveContainer<'_>,
135) -> i32 {
136 if lock.is_null() {
137 return -EINVAL;
138 }
139
140 let container = unsafe { &mut *lock };
141 assert!(
142 container.guard.is_some(),
143 "Called sys_spinlock_irqsave_unlock when no lock is currently held!"
144 );
145 container.guard = None;
146 0
147}