Skip to content

Commit b78a51c

Browse files
Anway-Agtelind
andauthored
Anway shmdt syscall (#317)
* initial comments * comments * tests added * tests added * tests * minor changes * comments for shmat * comments added * tests and comments * comments added * typo fixed --------- Co-authored-by: lind <lind@nyu.edu>
1 parent ae72129 commit b78a51c

File tree

1 file changed

+97
-15
lines changed

1 file changed

+97
-15
lines changed

src/safeposix/syscalls/fs_calls.rs

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5492,82 +5492,164 @@ impl Cage {
54925492
shmid
54935493
}
54945494

5495-
//------------------SHMAT SYSCALL------------------
5496-
5495+
/// ### Description
5496+
///
5497+
/// The `shmat_syscall` maps the shared memory segment associated with the
5498+
/// shared memory identifer onto the address space of the calling Cage
5499+
/// object. The address to which the segment is mapped is given by the
5500+
/// `shmaddr` parameter of this function.
5501+
///
5502+
/// ### Arguments
5503+
///
5504+
/// `shmid` : identifier of the memory segment to be mapped
5505+
/// `shmaddr` : Address in the address space of the calling Cage where the
5506+
/// segment is to be mapped `shmflag` : Flag which indicates if the
5507+
/// memory segment to be mapped is readonly or not
5508+
///
5509+
/// ### Returns
5510+
///
5511+
/// Returns the address at which the memory segment has been mapped into
5512+
///
5513+
/// ### Errors
5514+
///
5515+
/// * `EINVAL` : If the shmid passed as an argument is an invalid identifier
5516+
///
5517+
/// ### Panics
5518+
///
5519+
/// Currently there are no scenarios where the function panics
5520+
///
5521+
/// For more information - refer the documentation at [https://man7.org/linux/man-pages/man3/shmat.3p.html]
54975522
pub fn shmat_syscall(&self, shmid: i32, shmaddr: *mut u8, shmflg: i32) -> i32 {
5523+
// Get shm table
54985524
let metadata = &SHM_METADATA;
54995525
let prot: i32;
5526+
// Check if the shmid passed points to a valid table entry
55005527
if let Some(mut segment) = metadata.shmtable.get_mut(&shmid) {
5528+
// Check if the readonly flag is set or not
55015529
if 0 != (shmflg & SHM_RDONLY) {
55025530
prot = PROT_READ;
55035531
} else {
55045532
prot = PROT_READ | PROT_WRITE;
55055533
}
5534+
// Aquire a mutex lock on the reverse memory mappings
55065535
let mut rev_shm = self.rev_shm.lock();
5536+
// Push a reverse mapping of shmaddr -> shmid the processes's reverse mapping
5537+
// table
55075538
rev_shm.push((shmaddr as u32, shmid));
55085539
drop(rev_shm);
55095540

5510-
// update semaphores
5541+
// Clone semaphores that the memory segment holds into the current calling
5542+
// process
55115543
if !segment.semaphor_offsets.is_empty() {
5512-
// lets just look at the first cage in the set, since we only need to grab the
5513-
// ref from one
5544+
// Since all processes that share this segment hold all the semaphores - we only
5545+
// need to grab them from one cage
55145546
if let Some(cageid) = segment
55155547
.attached_cages
55165548
.clone()
55175549
.into_read_only()
55185550
.keys()
55195551
.next()
55205552
{
5553+
// Get the first cage associated with the memory segment
55215554
let cage2 = interface::cagetable_getref(*cageid);
5555+
// Get the reverse memory mappings
55225556
let cage2_rev_shm = cage2.rev_shm.lock();
5523-
let addrs = Self::rev_shm_find_addrs_by_shmid(&cage2_rev_shm, shmid); // find all the addresses assoc. with shmid
5557+
// Find all addresses associated with the shmid of the memory segment
5558+
let addrs = Self::rev_shm_find_addrs_by_shmid(&cage2_rev_shm, shmid);
5559+
// Add each semaphore at its appropriate offset - only need to index the first
5560+
// address Since semaphores are consistent across all cages
5561+
// and all addresses within the cages
55245562
for offset in segment.semaphor_offsets.iter() {
5525-
let sementry = cage2.sem_table.get(&(addrs[0] + *offset)).unwrap().clone(); //add semaphors into semtable at addr + offsets
5563+
let sementry = cage2.sem_table.get(&(addrs[0] + *offset)).unwrap().clone();
55265564
self.sem_table.insert(shmaddr as u32 + *offset, sementry);
55275565
}
55285566
}
55295567
}
55305568

5569+
// Map the shared segment onto the current cage using `map_shm` function
55315570
segment.map_shm(shmaddr, prot, self.cageid)
55325571
} else {
55335572
syscall_error(Errno::EINVAL, "shmat", "Invalid shmid value")
55345573
}
55355574
}
55365575

5537-
//------------------SHMDT SYSCALL------------------
5538-
5576+
///------------------SHMDT SYSCALL------------------
5577+
/// ### Description
5578+
///
5579+
/// This syscall can be viewed as a reversal of the `shmat_syscall`
5580+
/// 'shmat_syscall` attaches a particular memory shared memory segment to a
5581+
/// `shmaddr` passed as an argument
5582+
/// `shmdt` unmaps the shared memory segment that is currently mapped at the
5583+
/// address specified by the `shmaddr` argument.
5584+
///
5585+
/// ### Arguments
5586+
///
5587+
/// `shmaddr` : The address within the address space of the calling Cage to
5588+
/// unmap
5589+
///
5590+
/// ### Returns
5591+
///
5592+
/// Returns the id of the memory segment that has been unmapped
5593+
///
5594+
/// ### Errors
5595+
///
5596+
/// This function can result in the following errors
5597+
///
5598+
/// * EINVAL : If there is no memory segment with the address specified
5599+
///
5600+
///
5601+
/// ### Panics
5602+
///
5603+
/// This function panics if there is no memory segment associated with the specified `shmaddr`
5604+
///
5605+
/// For more information please refer - [https://man7.org/linux/man-pages/man3/shmdt.3p.html]
55395606
pub fn shmdt_syscall(&self, shmaddr: *mut u8) -> i32 {
55405607
let metadata = &SHM_METADATA;
55415608
let mut rm = false;
5609+
// Acquire the lock of the reverse memory mappings of the Cage object
55425610
let mut rev_shm = self.rev_shm.lock();
5611+
// This function returns the index where the pair of (shmaddr, shmid) is stored
5612+
// within the vector That holds these mappings
55435613
let rev_shm_index = Self::rev_shm_find_index_by_addr(&rev_shm, shmaddr as u32);
55445614

5615+
// Check if the index is valid
55455616
if let Some(index) = rev_shm_index {
5617+
// Get the second element of the (shmaddr,shmid) pair which gives us the id of
5618+
// the memory segment
55465619
let shmid = rev_shm[index].1;
5620+
// Get the memory segment from the shmtable which corresponds to the shmid
5621+
// extracted above
55475622
match metadata.shmtable.entry(shmid) {
5623+
// If the memory segment is occupied
55485624
interface::RustHashEntry::Occupied(mut occupied) => {
5625+
// Get the mutex for the memory segment
55495626
let segment = occupied.get_mut();
5550-
5551-
// update semaphores
5627+
// Loop through each semaphore that the segment hold and remove it from the semaphore table
55525628
for offset in segment.semaphor_offsets.iter() {
55535629
self.sem_table.remove(&(shmaddr as u32 + *offset));
55545630
}
5555-
5631+
// Use the unmap helper function to unmap the shmaddr from the current cage object
55565632
segment.unmap_shm(shmaddr, self.cageid);
55575633

5634+
// Check if segment has been removed previously by the `shmctl_syscall`
5635+
// and that the number of processess attached to the segment are zero
55585636
if segment.rmid && segment.shminfo.shm_nattch == 0 {
55595637
rm = true;
55605638
}
5639+
5640+
// Remove the reverse mapping from the mappings of the current cage object
55615641
rev_shm.swap_remove(index);
55625642

5643+
// If segment has been removed previously
5644+
// and has no processess attached to it
5645+
// we delete the memory segment from the shmtable
55635646
if rm {
55645647
let key = segment.key;
55655648
occupied.remove_entry();
55665649
metadata.shmkeyidtable.remove(&key);
55675650
}
5568-
5569-
return shmid; //NaCl relies on this non-posix behavior of
5570-
// returning the shmid on success
5651+
5652+
return shmid;
55715653
}
55725654
interface::RustHashEntry::Vacant(_) => {
55735655
panic!("Inode not created for some reason");

0 commit comments

Comments
 (0)