Remote call. Wrapper around send_receive syscall
(
handle: &CommHandle,
data1: u64,
data2: MessageData,
data3: MessageData,
expect_rdata1: Option<u64>
)
| 163 | /// Remote call. |
| 164 | /// Wrapper around send_receive syscall |
| 165 | pub fn rcall( |
| 166 | handle: &CommHandle, |
| 167 | data1: u64, |
| 168 | data2: MessageData, |
| 169 | data3: MessageData, |
| 170 | expect_rdata1: Option<u64> |
| 171 | ) -> Result<(u64, MessageData, MessageData), (SyscallError, Message)> { |
| 172 | |
| 173 | let mut message = match (data2, data3) { |
| 174 | (MessageData::Value(value2), MessageData::Value(value3)) => Message::Short(data1, value2, value3), |
| 175 | (data2, data3) => Message::Long(data1, data2, data3) |
| 176 | }; |
| 177 | |
| 178 | const MAX_RETRIES: usize = 100; |
| 179 | |
| 180 | let mut retry = 0; |
| 181 | loop { |
| 182 | // Try sending |
| 183 | let result = syscalls::send_receive( |
| 184 | handle, |
| 185 | message); |
| 186 | |
| 187 | match result { |
| 188 | Err((syscalls::SYSCALL_ERROR_SEND_BLOCKING, ret_message)) | |
| 189 | Err((syscalls::SYSCALL_ERROR_RECV_BLOCKING, ret_message)) => { |
| 190 | // Rendezvous blocked => Wait and try again |
| 191 | |
| 192 | message = ret_message; // Handles may have changed |
| 193 | |
| 194 | retry += 1; |
| 195 | if retry > MAX_RETRIES { |
| 196 | // Give up |
| 197 | return Err((syscalls::SYSCALL_ERROR_SEND_BLOCKING, message)); |
| 198 | } |
| 199 | |
| 200 | // Let another thread run |
| 201 | syscalls::thread_yield(); |
| 202 | |
| 203 | continue; // Go around for another try |
| 204 | } |
| 205 | Err(err_message) => { |
| 206 | return Err(err_message); |
| 207 | } |
| 208 | Ok(Message::Short(ERROR, sys_err, rdata3)) => { |
| 209 | return Err((SyscallError::new(sys_err), Message::Short(ERROR, sys_err, rdata3))); |
| 210 | } |
| 211 | Ok(Message::Short(rdata1, rdata2, rdata3)) => { |
| 212 | if let Some(rd1) = expect_rdata1 { |
| 213 | // Filter on first argument |
| 214 | if rdata1 != rd1 { |
| 215 | return Err((SyscallError::new(0), Message::Short(rdata1, rdata2, rdata3))); |
| 216 | } |
| 217 | } |
| 218 | return Ok((rdata1, rdata2.into(), rdata3.into())); |
| 219 | } |
| 220 | Ok(Message::Long(rdata1, rdata2, rdata3)) => { |
| 221 | if let Some(rd1) = expect_rdata1 { |
| 222 | // Filter on first argument |