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 })?;
56
57 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
58 let cap = get_capability_manager().create_capability(
59 ResourceType::Semaphore,
60 sem_id.as_u64() as usize,
61 CapPermissions {
62 read: true,
63 write: true,
64 execute: false,
65 grant: true,
66 revoke: true,
67 },
68 );
69 let cap_id = unsafe { (&mut *task.process.capabilities.get()).insert(cap) };
70 Ok(cap_id.as_u64())
71}
72
73pub fn sys_sem_wait(handle: u64) -> Result<u64, SyscallError> {
75 let sem_id = resolve_sem(handle, true)?;
76 semaphore::get_semaphore(sem_id)
77 .ok_or(SyscallError::BadHandle)?
78 .wait()
79 .map_err(|e| match e {
80 semaphore::SemaphoreError::WouldBlock => SyscallError::Again,
81 semaphore::SemaphoreError::Destroyed => SyscallError::Pipe,
82 _ => SyscallError::IoError,
83 })?;
84 Ok(0)
85}
86
87pub fn sys_sem_trywait(handle: u64) -> Result<u64, SyscallError> {
89 let sem_id = resolve_sem(handle, true)?;
90 match semaphore::get_semaphore(sem_id)
91 .ok_or(SyscallError::BadHandle)?
92 .try_wait()
93 {
94 Ok(()) => Ok(0),
95 Err(semaphore::SemaphoreError::WouldBlock) => Err(SyscallError::Again),
96 Err(_) => Err(SyscallError::IoError),
97 }
98}
99
100pub fn sys_sem_post(handle: u64) -> Result<u64, SyscallError> {
102 let sem_id = resolve_sem(handle, true)?;
103 semaphore::get_semaphore(sem_id)
104 .ok_or(SyscallError::BadHandle)?
105 .post()
106 .map_err(|e| match e {
107 semaphore::SemaphoreError::WouldBlock => SyscallError::Again,
108 semaphore::SemaphoreError::Destroyed => SyscallError::Pipe,
109 _ => SyscallError::IoError,
110 })?;
111 Ok(0)
112}
113
114pub fn sys_sem_close(handle: u64) -> Result<u64, SyscallError> {
116 crate::silo::enforce_cap_for_current_task(handle)?;
117 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
118 let caps = unsafe { &mut *task.process.capabilities.get() };
119 let cap = caps
120 .get(CapId::from_raw(handle))
121 .ok_or(SyscallError::BadHandle)?;
122 if cap.resource_type != ResourceType::Semaphore {
123 return Err(SyscallError::BadHandle);
124 }
125 let sem_id = SemId::from_u64(cap.resource as u64);
126
127 let cap = caps
128 .remove(CapId::from_raw(handle))
129 .ok_or(SyscallError::BadHandle)?;
130
131 crate::capability::release_capability(&cap, Some(task.id));
132 let _ = semaphore::destroy_semaphore(sem_id);
133 Ok(0)
134}