Changeset 7c0e1f5 in mainline for uspace/lib/c/generic/ipc.c
- Timestamp:
- 2017-11-23T22:20:17Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b1f36e3
- Parents:
- 40e5d66
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/ipc.c
r40e5d66 r7c0e1f5 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2017 Jakub Jermar 3 4 * All rights reserved. 4 5 * … … 52 53 * Structures of this type are used for keeping track of sent asynchronous calls. 53 54 */ 54 typedef struct { 55 link_t list; 56 55 typedef struct async_call { 57 56 ipc_async_callback_t callback; 58 57 void *private; 59 58 60 union { 61 ipc_callid_t callid; 62 struct { 63 ipc_call_t data; 64 int phoneid; 65 } msg; 66 } u; 59 struct { 60 ipc_call_t data; 61 int phoneid; 62 } msg; 67 63 } async_call_t; 68 69 LIST_INITIALIZE(dispatched_calls);70 71 static futex_t ipc_futex = FUTEX_INITIALIZER;72 73 /** Send asynchronous message via syscall.74 *75 * @param phoneid Phone handle for the call.76 * @param data Call data with the request.77 *78 * @return Hash of the call or an error code.79 *80 */81 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)82 {83 return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);84 }85 64 86 65 /** Prologue for ipc_call_async_*() functions. … … 121 100 if (!call) { 122 101 /* Nothing to do regardless if failed or not */ 123 futex_unlock(&ipc_futex);124 102 return; 125 103 } 126 104 127 105 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 128 futex_unlock(&ipc_futex);129 130 106 /* Call asynchronous handler with error code */ 131 107 if (call->callback) … … 135 111 return; 136 112 } 137 138 call->u.callid = callid;139 140 /* Add call to the list of dispatched calls */141 list_append(&call->list, &dispatched_calls);142 futex_unlock(&ipc_futex);143 113 } 144 114 145 115 /** Fast asynchronous call. 146 116 * 147 * This function can only handle fourarguments of payload. It is, however,117 * This function can only handle three arguments of payload. It is, however, 148 118 * faster than the more generic ipc_call_async_slow(). 149 119 * … … 159 129 * @param arg2 Service-defined payload argument. 160 130 * @param arg3 Service-defined payload argument. 161 * @param arg4 Service-defined payload argument.162 131 * @param private Argument to be passed to the answer/error callback. 163 132 * @param callback Answer or error callback. 164 133 */ 165 134 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1, 166 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private, 167 ipc_async_callback_t callback) 135 sysarg_t arg2, sysarg_t arg3, void *private, ipc_async_callback_t callback) 168 136 { 169 137 async_call_t *call = NULL; … … 175 143 } 176 144 177 /*178 * We need to make sure that we get callid179 * before another thread accesses the queue again.180 */181 182 futex_lock(&ipc_futex);183 145 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, 184 imethod, arg1, arg2, arg3, arg4);146 imethod, arg1, arg2, arg3, (sysarg_t) call); 185 147 186 148 ipc_finish_async(callid, phoneid, call); … … 213 175 return; 214 176 215 IPC_SET_IMETHOD(call->u.msg.data, imethod); 216 IPC_SET_ARG1(call->u.msg.data, arg1); 217 IPC_SET_ARG2(call->u.msg.data, arg2); 218 IPC_SET_ARG3(call->u.msg.data, arg3); 219 IPC_SET_ARG4(call->u.msg.data, arg4); 220 IPC_SET_ARG5(call->u.msg.data, arg5); 221 222 /* 223 * We need to make sure that we get callid 224 * before another threadaccesses the queue again. 225 */ 226 227 futex_lock(&ipc_futex); 228 ipc_callid_t callid = 229 ipc_call_async_internal(phoneid, &call->u.msg.data); 177 IPC_SET_IMETHOD(call->msg.data, imethod); 178 IPC_SET_ARG1(call->msg.data, arg1); 179 IPC_SET_ARG2(call->msg.data, arg2); 180 IPC_SET_ARG3(call->msg.data, arg3); 181 IPC_SET_ARG4(call->msg.data, arg4); 182 IPC_SET_ARG5(call->msg.data, arg5); 183 184 ipc_callid_t callid = __SYSCALL3(SYS_IPC_CALL_ASYNC_SLOW, phoneid, 185 (sysarg_t) &call->msg.data, (sysarg_t) call); 230 186 231 187 ipc_finish_async(callid, phoneid, call); … … 286 242 /** Handle received answer. 287 243 * 288 * Find the hash of the answer and call the answer callback.289 *290 * The answer has the same hash as the request OR'ed with291 * the IPC_CALLID_ANSWERED bit.292 *293 * @todo Use hash table.294 *295 244 * @param callid Hash of the received answer. 296 245 * @param data Call data of the answer. 297 *298 246 */ 299 247 static void handle_answer(ipc_callid_t callid, ipc_call_t *data) 300 248 { 301 callid &= ~IPC_CALLID_ANSWERED; 302 303 futex_lock(&ipc_futex); 304 305 link_t *item; 306 for (item = dispatched_calls.head.next; item != &dispatched_calls.head; 307 item = item->next) { 308 async_call_t *call = 309 list_get_instance(item, async_call_t, list); 310 311 if (call->u.callid == callid) { 312 list_remove(&call->list); 313 314 futex_unlock(&ipc_futex); 315 316 if (call->callback) 317 call->callback(call->private, 318 IPC_GET_RETVAL(*data), data); 319 320 free(call); 321 return; 322 } 323 } 324 325 futex_unlock(&ipc_futex); 249 async_call_t *call = data->label; 250 251 if (!call) 252 return; 253 254 if (call->callback) 255 call->callback(call->private, IPC_GET_RETVAL(*data), data); 256 free(call); 326 257 } 327 258
Note:
See TracChangeset
for help on using the changeset viewer.