strat9_kernel/syscall/
semaphore.rs1use super::error::SyscallError;
7use crate::{
8 capability::{get_capability_manager, CapId, CapPermissions, ResourceType},
9 ipc::semaphore::{self, SemId},
10 process::current_task_clone,
11};
12
13fn resolve_sem(handle: u64, require_write: bool) -> Result<SemId, SyscallError> {
14 crate::silo::enforce_cap_for_current_task(handle)?;
15 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
16 let caps = unsafe { &*task.process.capabilities.get() };
17 let required = if require_write {
18 CapPermissions {
19 read: false,
20 write: true,
21 execute: false,
22 grant: false,
23 revoke: false,
24 }
25 } else {
26 CapPermissions {
27 read: true,
28 write: false,
29 execute: false,
30 grant: false,
31 revoke: false,
32 }
33 };
34 let cap = caps
35 .get_with_permissions(CapId::from_raw(handle), required)
36 .ok_or(SyscallError::PermissionDenied)?;
37 if cap.resource_type != ResourceType::Semaphore {
38 return Err(SyscallError::BadHandle);
39 }
40 let sem_id = SemId::from_u64(cap.resource as u64);
41 if semaphore::get_semaphore(sem_id).is_none() {
42 return Err(SyscallError::BadHandle);
43 }
44 Ok(sem_id)
45}
46
47pub fn sys_sem_create(initial: u64) -> Result<u64, SyscallError> {
49 let initial = u32::try_from(initial).map_err(|_| SyscallError::InvalidArgument)?;
50 let sem_id = semaphore::create_semaphore(initial).map_err(|e| match e {
51 semaphore::SemaphoreError::InvalidValue => SyscallError::InvalidArgument,
52 semaphore::SemaphoreError::WouldBlock => SyscallError::Again,
53 semaphore::SemaphoreError::Destroyed => SyscallError::Pipe,
54 semaphore::SemaphoreError::NotFound => SyscallError::NotFound,
55 semaphore::SemaphoreError::Interrupted => SyscallError::Interrupted,
56 })?;
57
58 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
59 let cap = get_capability_manager().create_capability(
60 ResourceType::Semaphore,
61 sem_id.as_u64() as usize,
62 CapPermissions {
63 read: true,
64 write: true,
65 execute: false,
66 grant: true,
67 revoke: true,
68 },
69 );
70 let cap_id = unsafe { (&mut *task.process.capabilities.get()).insert(cap) };
71 Ok(cap_id.as_u64())
72}
73
74pub fn sys_sem_wait(handle: u64) -> Result<u64, SyscallError> {
76 let sem_id = resolve_sem(handle, true)?;
77 semaphore::get_semaphore(sem_id)
78 .ok_or(SyscallError::BadHandle)?
79 .wait()
80 .map_err(|e| match e {
81 semaphore::SemaphoreError::WouldBlock => SyscallError::Again,
82 semaphore::SemaphoreError::Destroyed => SyscallError::Pipe,
83 semaphore::SemaphoreError::Interrupted => SyscallError::Interrupted,
84 _ => SyscallError::IoError,
85 })?;
86 Ok(0)
87}
88
89pub fn sys_sem_trywait(handle: u64) -> Result<u64, SyscallError> {
91 let sem_id = resolve_sem(handle, true)?;
92 match semaphore::get_semaphore(sem_id)
93 .ok_or(SyscallError::BadHandle)?
94 .try_wait()
95 {
96 Ok(()) => Ok(0),
97 Err(semaphore::SemaphoreError::WouldBlock) => Err(SyscallError::Again),
98 Err(_) => Err(SyscallError::IoError),
99 }
100}
101
102pub fn sys_sem_post(handle: u64) -> Result<u64, SyscallError> {
104 let sem_id = resolve_sem(handle, true)?;
105 semaphore::get_semaphore(sem_id)
106 .ok_or(SyscallError::BadHandle)?
107 .post()
108 .map_err(|e| match e {
109 semaphore::SemaphoreError::WouldBlock => SyscallError::Again,
110 semaphore::SemaphoreError::Destroyed => SyscallError::Pipe,
111 _ => SyscallError::IoError,
112 })?;
113 Ok(0)
114}
115
116pub fn sys_sem_close(handle: u64) -> Result<u64, SyscallError> {
118 crate::silo::enforce_cap_for_current_task(handle)?;
119 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
120 let caps = unsafe { &mut *task.process.capabilities.get() };
121 let cap = caps
122 .get(CapId::from_raw(handle))
123 .ok_or(SyscallError::BadHandle)?;
124 if cap.resource_type != ResourceType::Semaphore {
125 return Err(SyscallError::BadHandle);
126 }
127 let sem_id = SemId::from_u64(cap.resource as u64);
128
129 let cap = caps
130 .remove(CapId::from_raw(handle))
131 .ok_or(SyscallError::BadHandle)?;
132
133 crate::capability::release_capability(&cap, Some(task.id));
134 let _ = semaphore::destroy_semaphore(sem_id);
135 Ok(0)
136}