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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use super::*;
use crate::error::LxError;
use crate::time::TimeSpec;
use alloc::{collections::BTreeMap, sync::Arc, sync::Weak};
use lazy_static::lazy_static;
use lock::{Mutex, RwLock};
use zircon_object::vm::*;
lazy_static! {
static ref KEY2SHM: RwLock<BTreeMap<u32, Weak<Mutex<ShmGuard>>>> = RwLock::new(BTreeMap::new());
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ShmidDs {
pub perm: IpcPerm,
pub segsz: usize,
pub atime: usize,
pub dtime: usize,
pub ctime: usize,
pub cpid: u32,
pub lpid: u32,
pub nattch: usize,
}
#[derive(Clone)]
pub struct ShmIdentifier {
pub addr: usize,
pub guard: Arc<Mutex<ShmGuard>>,
}
pub struct ShmGuard {
pub shared_guard: Arc<VmObject>,
pub shmid_ds: Mutex<ShmidDs>,
}
impl ShmIdentifier {
pub fn set_addr(&mut self, addr: usize) {
self.addr = addr;
}
pub fn new_shared_guard(
key: u32,
memsize: usize,
flags: usize,
cpid: u32,
) -> Result<Arc<Mutex<ShmGuard>>, LxError> {
let mut key2shm = KEY2SHM.write();
let flag = IpcGetFlag::from_bits_truncate(flags);
if let Some(weak_guard) = key2shm.get(&key) {
if let Some(guard) = weak_guard.upgrade() {
if flag.contains(IpcGetFlag::CREAT) && flag.contains(IpcGetFlag::EXCLUSIVE) {
return Err(LxError::EEXIST);
}
return Ok(guard);
}
}
let shared_guard = Arc::new(Mutex::new(ShmGuard {
shared_guard: VmObject::new_paged(pages(memsize)),
shmid_ds: Mutex::new(ShmidDs {
perm: IpcPerm {
key,
uid: 0,
gid: 0,
cuid: 0,
cgid: 0,
mode: (flags as u32) & 0x1ff,
__seq: 0,
__pad1: 0,
__pad2: 0,
},
segsz: memsize,
atime: 0,
dtime: 0,
ctime: TimeSpec::now().sec,
cpid,
lpid: 0,
nattch: 0,
}),
}));
key2shm.insert(key, Arc::downgrade(&shared_guard));
Ok(shared_guard)
}
}
impl ShmGuard {
pub fn attach(&self, pid: u32) {
let mut ds = self.shmid_ds.lock();
ds.atime = TimeSpec::now().sec;
ds.nattch += 1;
ds.lpid = pid;
}
pub fn detach(&self, pid: u32) {
let mut ds = self.shmid_ds.lock();
ds.dtime = TimeSpec::now().sec;
ds.nattch -= 1;
ds.lpid = pid;
}
pub fn ctime(&self) {
self.shmid_ds.lock().ctime = TimeSpec::now().sec;
}
pub fn set(&self, new: &ShmidDs) {
let mut lock = self.shmid_ds.lock();
lock.perm.uid = new.perm.uid;
lock.perm.gid = new.perm.gid;
lock.perm.mode = new.perm.mode & 0x1ff;
}
pub fn remove(&self) {
let mut key2shm = KEY2SHM.write();
let key = self.shmid_ds.lock().perm.key;
key2shm.remove(&key);
}
}