Changes in uspace/lib/c/generic/ipc.c [c170438:d7978525] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/ipc.c
rc170438 rd7978525 81 81 LIST_INITIALIZE(queued_calls); 82 82 83 static futex_t ipc_futex = FUTEX_INITIALIZER;83 static atomic_t ipc_futex = FUTEX_INITIALIZER; 84 84 85 85 /** Send asynchronous message via syscall. … … 96 96 } 97 97 98 /** Prolog uefor ipc_call_async_*() functions.98 /** Prolog for ipc_call_async_*() functions. 99 99 * 100 100 * @param private Argument for the answer/error callback. … … 122 122 } 123 123 124 /** Epilog uefor ipc_call_async_*() functions.124 /** Epilog for ipc_call_async_*() functions. 125 125 * 126 126 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 127 127 * @param phoneid Phone handle through which the call was made. 128 128 * @param call Structure returned by ipc_prepare_async(). 129 * @param can_preempt If true, the current fibril can be preempted 130 * in this call. 131 * 129 132 */ 130 133 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, 131 async_call_t *call )134 async_call_t *call, bool can_preempt) 132 135 { 133 136 if (!call) { 134 137 /* Nothing to do regardless if failed or not */ 135 futex_u nlock(&ipc_futex);138 futex_up(&ipc_futex); 136 139 return; 137 140 } 138 141 139 142 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 140 futex_u nlock(&ipc_futex);143 futex_up(&ipc_futex); 141 144 142 145 /* Call asynchronous handler with error code */ … … 149 152 150 153 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 151 futex_u nlock(&ipc_futex);154 futex_up(&ipc_futex); 152 155 153 156 call->u.msg.phoneid = phoneid; … … 156 159 list_append(&call->list, &queued_calls); 157 160 158 call->fid = fibril_get_id(); 159 fibril_switch(FIBRIL_TO_MANAGER); 160 /* Async futex unlocked by previous call */ 161 if (can_preempt) { 162 call->fid = fibril_get_id(); 163 fibril_switch(FIBRIL_TO_MANAGER); 164 /* Async futex unlocked by previous call */ 165 } else { 166 call->fid = 0; 167 futex_up(&async_futex); 168 } 161 169 162 170 return; … … 167 175 /* Add call to the list of dispatched calls */ 168 176 list_append(&call->list, &dispatched_calls); 169 futex_u nlock(&ipc_futex);177 futex_up(&ipc_futex); 170 178 } 171 179 … … 189 197 * @param private Argument to be passed to the answer/error callback. 190 198 * @param callback Answer or error callback. 199 * @param can_preempt If true, the current fibril will be preempted in 200 * case the kernel temporarily refuses to accept more 201 * asynchronous calls. 202 * 191 203 */ 192 204 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1, 193 205 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private, 194 ipc_async_callback_t callback )206 ipc_async_callback_t callback, bool can_preempt) 195 207 { 196 208 async_call_t *call = NULL; … … 207 219 */ 208 220 209 futex_ lock(&ipc_futex);221 futex_down(&ipc_futex); 210 222 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, 211 223 imethod, arg1, arg2, arg3, arg4); … … 214 226 if (!call) { 215 227 call = ipc_prepare_async(private, callback); 216 if (!call) { 217 futex_unlock(&ipc_futex); 228 if (!call) 218 229 return; 219 }220 230 } 221 231 … … 234 244 } 235 245 236 ipc_finish_async(callid, phoneid, call );246 ipc_finish_async(callid, phoneid, call, can_preempt); 237 247 } 238 248 … … 254 264 * @param private Argument to be passed to the answer/error callback. 255 265 * @param callback Answer or error callback. 266 * @param can_preempt If true, the current fibril will be preempted in 267 * case the kernel temporarily refuses to accept more 268 * asynchronous calls. 269 * 256 270 */ 257 271 void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 258 272 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private, 259 ipc_async_callback_t callback )273 ipc_async_callback_t callback, bool can_preempt) 260 274 { 261 275 async_call_t *call = ipc_prepare_async(private, callback); … … 275 289 */ 276 290 277 futex_ lock(&ipc_futex);291 futex_down(&ipc_futex); 278 292 ipc_callid_t callid = 279 293 ipc_call_async_internal(phoneid, &call->u.msg.data); 280 294 281 ipc_finish_async(callid, phoneid, call );295 ipc_finish_async(callid, phoneid, call, can_preempt); 282 296 } 283 297 … … 359 373 futex_up(&async_futex); 360 374 361 assert(call->fid);362 fibril_add_ready(call->fid);375 if (call->fid) 376 fibril_add_ready(call->fid); 363 377 364 378 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { … … 370 384 call->u.callid = callid; 371 385 372 futex_ lock(&ipc_futex);386 futex_down(&ipc_futex); 373 387 list_append(&call->list, &dispatched_calls); 374 futex_u nlock(&ipc_futex);388 futex_up(&ipc_futex); 375 389 } 376 390 … … 398 412 callid &= ~IPC_CALLID_ANSWERED; 399 413 400 futex_ lock(&ipc_futex);414 futex_down(&ipc_futex); 401 415 402 416 link_t *item; … … 409 423 list_remove(&call->list); 410 424 411 futex_u nlock(&ipc_futex);425 futex_up(&ipc_futex); 412 426 413 427 if (call->callback) … … 420 434 } 421 435 422 futex_u nlock(&ipc_futex);436 futex_up(&ipc_futex); 423 437 } 424 438
Note:
See TracChangeset
for help on using the changeset viewer.