Changeset d054ad3 in mainline for uspace/lib/c/generic/ipc.c
- Timestamp:
- 2018-07-09T18:36:33Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2d56e2e
- Parents:
- 87337dc5
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-05 16:39:15)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-09 18:36:33)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/ipc.c
r87337dc5 rd054ad3 50 50 #include <macros.h> 51 51 52 /**53 * Structures of this type are used for keeping track of sent asynchronous calls.54 */55 typedef struct async_call {56 ipc_async_callback_t callback;57 void *private;58 59 struct {60 ipc_call_t data;61 } msg;62 } async_call_t;63 64 /** Prologue for ipc_call_async_*() functions.65 *66 * @param private Argument for the answer/error callback.67 * @param callback Answer/error callback.68 *69 * @return New, partially initialized async_call structure or NULL.70 *71 */72 static inline async_call_t *ipc_prepare_async(void *private,73 ipc_async_callback_t callback)74 {75 async_call_t *call =76 (async_call_t *) malloc(sizeof(async_call_t));77 if (!call) {78 if (callback)79 callback(private, ENOMEM, NULL);80 81 return NULL;82 }83 84 call->callback = callback;85 call->private = private;86 87 return call;88 }89 90 /** Epilogue for ipc_call_async_*() functions.91 *92 * @param rc Value returned by the SYS_IPC_CALL_ASYNC_* syscall.93 * @param call Structure returned by ipc_prepare_async().94 */95 static inline void ipc_finish_async(errno_t rc, async_call_t *call)96 {97 if (!call) {98 /* Nothing to do regardless if failed or not */99 return;100 }101 102 if (rc != EOK) {103 /* Call asynchronous handler with error code */104 if (call->callback)105 call->callback(call->private, ENOENT, NULL);106 107 free(call);108 return;109 }110 }111 112 52 /** Fast asynchronous call. 113 53 * … … 126 66 * @param arg2 Service-defined payload argument. 127 67 * @param arg3 Service-defined payload argument. 128 * @param private Argument to be passed to the answer/error callback. 129 * @param callback Answer or error callback. 130 */ 131 void ipc_call_async_fast(cap_phone_handle_t phandle, sysarg_t imethod, 132 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, void *private, 133 ipc_async_callback_t callback) 134 { 135 async_call_t *call = ipc_prepare_async(private, callback); 136 if (!call) 137 return; 138 139 errno_t rc = (errno_t) __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, 68 * @param label A value to set to the label field of the answer. 69 */ 70 errno_t ipc_call_async_fast(cap_phone_handle_t phandle, sysarg_t imethod, 71 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, void *label) 72 { 73 return __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, 140 74 CAP_HANDLE_RAW(phandle), imethod, arg1, arg2, arg3, 141 (sysarg_t) call); 142 143 ipc_finish_async(rc, call); 75 (sysarg_t) label); 144 76 } 145 77 … … 159 91 * @param arg4 Service-defined payload argument. 160 92 * @param arg5 Service-defined payload argument. 161 * @param private Argument to be passed to the answer/error callback. 162 * @param callback Answer or error callback. 163 */ 164 void ipc_call_async_slow(cap_phone_handle_t phandle, sysarg_t imethod, 93 * @param label A value to set to the label field of the answer. 94 */ 95 errno_t ipc_call_async_slow(cap_phone_handle_t phandle, sysarg_t imethod, 165 96 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 166 void *private, ipc_async_callback_t callback) 167 { 168 async_call_t *call = ipc_prepare_async(private, callback); 169 if (!call) 170 return; 171 172 IPC_SET_IMETHOD(call->msg.data, imethod); 173 IPC_SET_ARG1(call->msg.data, arg1); 174 IPC_SET_ARG2(call->msg.data, arg2); 175 IPC_SET_ARG3(call->msg.data, arg3); 176 IPC_SET_ARG4(call->msg.data, arg4); 177 IPC_SET_ARG5(call->msg.data, arg5); 178 179 errno_t rc = (errno_t) __SYSCALL3(SYS_IPC_CALL_ASYNC_SLOW, 180 CAP_HANDLE_RAW(phandle), (sysarg_t) &call->msg.data, 181 (sysarg_t) call); 182 183 ipc_finish_async(rc, call); 97 void *label) 98 { 99 ipc_call_t data; 100 101 IPC_SET_IMETHOD(data, imethod); 102 IPC_SET_ARG1(data, arg1); 103 IPC_SET_ARG2(data, arg2); 104 IPC_SET_ARG3(data, arg3); 105 IPC_SET_ARG4(data, arg4); 106 IPC_SET_ARG5(data, arg5); 107 108 return __SYSCALL3(SYS_IPC_CALL_ASYNC_SLOW, 109 CAP_HANDLE_RAW(phandle), (sysarg_t) &data, 110 (sysarg_t) label); 184 111 } 185 112 … … 237 164 } 238 165 239 /** Handle received answer.240 *241 * @param data Call data of the answer.242 */243 static void handle_answer(ipc_call_t *data)244 {245 async_call_t *call = data->label;246 247 if (!call)248 return;249 250 if (call->callback)251 call->callback(call->private, IPC_GET_RETVAL(*data), data);252 free(call);253 }254 255 /** Wait for first IPC call to come.256 *257 * @param[out] call Storage for the received call.258 * @param[in] usec Timeout in microseconds259 * @param[in[ flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).260 *261 * @return Error code.262 */263 errno_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec, unsigned int flags)264 {265 errno_t rc = (errno_t) __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec,266 flags);267 268 /* Handle received answers */269 if ((rc == EOK) && (call->cap_handle == CAP_NIL) &&270 (call->flags & IPC_CALL_ANSWERED)) {271 handle_answer(call);272 }273 274 return rc;275 }276 277 166 /** Interrupt one thread of this task from waiting for IPC. 278 167 * … … 283 172 } 284 173 285 /** Wait for first IPC call to come. 286 * 287 * Only requests are returned, answers are processed internally. 288 * 289 * @param call Incoming call storage. 290 * @param usec Timeout in microseconds 291 * 292 * @return Error code. 293 * 294 */ 295 errno_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec) 296 { 297 errno_t rc; 298 299 do { 300 rc = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE); 301 } while ((rc == EOK) && (call->cap_handle == CAP_NIL) && 302 (call->flags & IPC_CALL_ANSWERED)); 303 304 return rc; 305 } 306 307 /** Check if there is an IPC call waiting to be picked up. 308 * 309 * Only requests are returned, answers are processed internally. 310 * 311 * @param call Incoming call storage. 312 * 313 * @return Error code. 314 * 315 */ 316 errno_t ipc_trywait_for_call(ipc_call_t *call) 317 { 318 errno_t rc; 319 320 do { 321 rc = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, 322 SYNCH_FLAGS_NON_BLOCKING); 323 } while ((rc == EOK) && (call->cap_handle == CAP_NIL) && 324 (call->flags & IPC_CALL_ANSWERED)); 325 326 return rc; 174 errno_t ipc_wait(ipc_call_t *call, sysarg_t usec, unsigned int flags) 175 { 176 // TODO: Use expiration time instead of timeout. 177 return __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 327 178 } 328 179
Note:
See TracChangeset
for help on using the changeset viewer.