Changeset 10477601 in mainline
- Timestamp:
- 2011-01-29T19:39:27Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fc5f7a8
- Parents:
- 6119f24
- Location:
- uspace/lib/c
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/ipc.c
r6119f24 r10477601 49 49 50 50 /** 51 * Structures of this type are used for keeping track of sent asynchronous calls52 * and queing unsent calls.51 * Structures of this type are used for keeping track 52 * of sent asynchronous calls and queing unsent calls. 53 53 */ 54 54 typedef struct { 55 55 link_t list; 56 56 57 57 ipc_async_callback_t callback; 58 58 void *private; 59 59 60 union { 60 61 ipc_callid_t callid; … … 64 65 } msg; 65 66 } u; 66 fid_t fid; /**< Fibril waiting for sending this call. */ 67 68 /** Fibril waiting for sending this call. */ 69 fid_t fid; 67 70 } async_call_t; 68 71 … … 71 74 /** List of asynchronous calls that were not accepted by kernel. 72 75 * 73 * It is protected by async_futex, because if the call cannot be sent into the 74 * kernel, the async framework is used automatically. 76 * Protected by async_futex, because if the call is not accepted 77 * by the kernel, the async framework is used automatically. 78 * 75 79 */ 76 80 LIST_INITIALIZE(queued_calls); … … 78 82 static atomic_t ipc_futex = FUTEX_INITIALIZER; 79 83 80 /** Make a fast synchronous call.81 * 82 * Only three payload arguments can be passed using this function. However, this83 * function is faster than the generic ipc_call_sync_slow() because the payload84 * is passed directly in registers.85 * 86 * @param phoneid 87 * @param method 88 * @param arg1 89 * @param arg2 90 * @param arg3 91 * @param result1 92 * @param result2 93 * @param result3 94 * @param result4 95 * @param result5 96 * 97 * @return Negative values represent errors returned by IPC.98 * Otherwise the RETVAL of the answer is returned.99 * /100 int 101 i pc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, sysarg_t arg2,102 sysarg_t arg 3, sysarg_t *result1, sysarg_t *result2, sysarg_t *result3,103 sysarg_t *result 4, sysarg_t *result5)84 /** Fast synchronous call. 85 * 86 * Only three payload arguments can be passed using this function. However, 87 * this function is faster than the generic ipc_call_sync_slow() because 88 * the payload is passed directly in registers. 89 * 90 * @param phoneid Phone handle for the call. 91 * @param method Requested method. 92 * @param arg1 Service-defined payload argument. 93 * @param arg2 Service-defined payload argument. 94 * @param arg3 Service-defined payload argument. 95 * @param result1 If non-NULL, the return ARG1 will be stored there. 96 * @param result2 If non-NULL, the return ARG2 will be stored there. 97 * @param result3 If non-NULL, the return ARG3 will be stored there. 98 * @param result4 If non-NULL, the return ARG4 will be stored there. 99 * @param result5 If non-NULL, the return ARG5 will be stored there. 100 * 101 * @return Negative values representing IPC errors. 102 * @return Otherwise the RETVAL of the answer. 103 * 104 */ 105 int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, 106 sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, 107 sysarg_t *result3, sysarg_t *result4, sysarg_t *result5) 104 108 { 105 109 ipc_call_t resdata; 106 int callres; 107 108 callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 110 int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 109 111 arg2, arg3, (sysarg_t) &resdata); 110 112 if (callres) 111 113 return callres; 114 112 115 if (result1) 113 116 *result1 = IPC_GET_ARG1(resdata); … … 120 123 if (result5) 121 124 *result5 = IPC_GET_ARG5(resdata); 122 125 123 126 return IPC_GET_RETVAL(resdata); 124 127 } 125 128 126 /** Make a synchronous call transmitting 5 arguments of payload.129 /** Synchronous call transmitting 5 arguments of payload. 127 130 * 128 131 * @param phoneid Phone handle for the call. … … 139 142 * @param result5 If non-NULL, storage for the fifth return argument. 140 143 * 141 * @return Negative value means IPC error.142 * 143 * 144 */ 145 int 146 ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,147 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *result1,148 sysarg_t *result 2, sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)144 * @return Negative values representing IPC errors. 145 * @return Otherwise the RETVAL of the answer. 146 * 147 */ 148 int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 149 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 150 sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4, 151 sysarg_t *result5) 149 152 { 150 153 ipc_call_t data; … … 176 179 } 177 180 178 /** S yscall to send asynchronous message.181 /** Send asynchronous message via syscall. 179 182 * 180 183 * @param phoneid Phone handle for the call. … … 184 187 * 185 188 */ 186 static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)189 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data) 187 190 { 188 191 return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data); 189 192 } 190 193 191 /** Prolog to ipc_call_async_*() functions. 192 * 193 * @param private Argument for the answer/error callback. 194 * @param callback Answer/error callback. 195 * 196 * @return New, partially initialized async_call structure or NULL. 194 /** Prolog for ipc_call_async_*() functions. 195 * 196 * @param private Argument for the answer/error callback. 197 * @param callback Answer/error callback. 198 * 199 * @return New, partially initialized async_call structure or NULL. 200 * 197 201 */ 198 202 static inline async_call_t *ipc_prepare_async(void *private, 199 203 ipc_async_callback_t callback) 200 204 { 201 async_call_t *call; 202 203 call = malloc(sizeof(*call)); 205 async_call_t *call = 206 (async_call_t *) malloc(sizeof(async_call_t)); 204 207 if (!call) { 205 208 if (callback) 206 209 callback(private, ENOMEM, NULL); 210 207 211 return NULL; 208 212 } 213 209 214 call->callback = callback; 210 215 call->private = private; 211 216 212 217 return call; 213 218 } 214 219 215 /** Epilogue of ipc_call_async_*() functions. 216 * 217 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 218 * @param phoneid Phone handle through which the call was made. 219 * @param call async_call structure returned by ipc_prepare_async(). 220 * @param can_preempt If non-zero, the current fibril can be preempted in this 221 * call. 220 /** Epilog for ipc_call_async_*() functions. 221 * 222 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 223 * @param phoneid Phone handle through which the call was made. 224 * @param call Structure returned by ipc_prepare_async(). 225 * @param can_preempt If true, the current fibril can be preempted 226 * in this call. 227 * 222 228 */ 223 229 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, 224 async_call_t *call, int can_preempt) 225 { 226 if (!call) { /* Nothing to do regardless if failed or not */ 230 async_call_t *call, bool can_preempt) 231 { 232 if (!call) { 233 /* Nothing to do regardless if failed or not */ 227 234 futex_up(&ipc_futex); 228 235 return; 229 236 } 230 237 231 238 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 232 239 futex_up(&ipc_futex); 240 233 241 /* Call asynchronous handler with error code */ 234 242 if (call->callback) 235 243 call->callback(call->private, ENOENT, NULL); 244 236 245 free(call); 237 246 return; 238 247 } 239 248 240 249 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 241 250 futex_up(&ipc_futex); 242 251 243 252 call->u.msg.phoneid = phoneid; 244 253 245 254 futex_down(&async_futex); 246 255 list_append(&call->list, &queued_calls); 247 256 248 257 if (can_preempt) { 249 258 call->fid = fibril_get_id(); … … 254 263 futex_up(&async_futex); 255 264 } 265 256 266 return; 257 267 } 268 258 269 call->u.callid = callid; 270 259 271 /* Add call to the list of dispatched calls */ 260 272 list_append(&call->list, &dispatched_calls); 261 273 futex_up(&ipc_futex); 262 263 } 264 265 /** Make a fast asynchronous call. 274 } 275 276 /** Fast asynchronous call. 266 277 * 267 278 * This function can only handle four arguments of payload. It is, however, … … 269 280 * 270 281 * Note that this function is a void function. 271 * During normal opertation, answering this call will trigger the callback. 272 * In case of fatal error, call the callback handler with the proper error code. 273 * If the call cannot be temporarily made, queue it. 282 * 283 * During normal operation, answering this call will trigger the callback. 284 * In case of fatal error, the callback handler is called with the proper 285 * error code. If the call cannot be temporarily made, it is queued. 274 286 * 275 287 * @param phoneid Phone handle for the call. … … 281 293 * @param private Argument to be passed to the answer/error callback. 282 294 * @param callback Answer or error callback. 283 * @param can_preempt If non-zero, the current fibril will be preempted in295 * @param can_preempt If true, the current fibril will be preempted in 284 296 * case the kernel temporarily refuses to accept more 285 297 * asynchronous calls. … … 288 300 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1, 289 301 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private, 290 ipc_async_callback_t callback, intcan_preempt)302 ipc_async_callback_t callback, bool can_preempt) 291 303 { 292 304 async_call_t *call = NULL; … … 299 311 300 312 /* 301 * We need to make sure that we get callid before another thread302 * accesses the queue again.313 * We need to make sure that we get callid 314 * before another thread accesses the queue again. 303 315 */ 316 304 317 futex_down(&ipc_futex); 305 318 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, … … 312 325 return; 313 326 } 327 314 328 IPC_SET_IMETHOD(call->u.msg.data, imethod); 315 329 IPC_SET_ARG1(call->u.msg.data, arg1); … … 317 331 IPC_SET_ARG3(call->u.msg.data, arg3); 318 332 IPC_SET_ARG4(call->u.msg.data, arg4); 333 319 334 /* 320 335 * To achieve deterministic behavior, we always zero out the 321 336 * arguments that are beyond the limits of the fast version. 322 337 */ 338 323 339 IPC_SET_ARG5(call->u.msg.data, 0); 324 340 } 341 325 342 ipc_finish_async(callid, phoneid, call, can_preempt); 326 343 } 327 344 328 /** Make an asynchronous call transmitting the entire payload.345 /** Asynchronous call transmitting the entire payload. 329 346 * 330 347 * Note that this function is a void function. 331 * During normal opertation, answering this call will trigger the callback. 332 * In case of fatal error, call the callback handler with the proper error code. 333 * If the call cannot be temporarily made, queue it. 348 * 349 * During normal operation, answering this call will trigger the callback. 350 * In case of fatal error, the callback handler is called with the proper 351 * error code. If the call cannot be temporarily made, it is queued. 334 352 * 335 353 * @param phoneid Phone handle for the call. … … 342 360 * @param private Argument to be passed to the answer/error callback. 343 361 * @param callback Answer or error callback. 344 * @param can_preempt If non-zero, the current fibril will be preempted in362 * @param can_preempt If true, the current fibril will be preempted in 345 363 * case the kernel temporarily refuses to accept more 346 364 * asynchronous calls. … … 349 367 void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 350 368 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private, 351 ipc_async_callback_t callback, int can_preempt) 352 { 353 async_call_t *call; 354 ipc_callid_t callid; 355 356 call = ipc_prepare_async(private, callback); 369 ipc_async_callback_t callback, bool can_preempt) 370 { 371 async_call_t *call = ipc_prepare_async(private, callback); 357 372 if (!call) 358 373 return; 359 374 360 375 IPC_SET_IMETHOD(call->u.msg.data, imethod); 361 376 IPC_SET_ARG1(call->u.msg.data, arg1); … … 364 379 IPC_SET_ARG4(call->u.msg.data, arg4); 365 380 IPC_SET_ARG5(call->u.msg.data, arg5); 381 366 382 /* 367 * We need to make sure that we get callid before another thread368 * accesses the queue again.383 * We need to make sure that we get callid 384 * before another threadaccesses the queue again. 369 385 */ 386 370 387 futex_down(&ipc_futex); 371 callid = _ipc_call_async(phoneid, &call->u.msg.data); 372 388 ipc_callid_t callid = 389 ipc_call_async_internal(phoneid, &call->u.msg.data); 390 373 391 ipc_finish_async(callid, phoneid, call, can_preempt); 374 392 } 375 393 376 377 /** Answer a received call - fast version. 394 /** Answer received call (fast version). 378 395 * 379 396 * The fast answer makes use of passing retval and first four arguments in 380 397 * registers. If you need to return more, use the ipc_answer_slow() instead. 381 398 * 382 * @param callid Hash of the call being answered. 383 * @param retval Return value. 384 * @param arg1 First return argument. 385 * @param arg2 Second return argument. 386 * @param arg3 Third return argument. 387 * @param arg4 Fourth return argument. 388 * 389 * @return Zero on success or a value from @ref errno.h on failure. 399 * @param callid Hash of the call being answered. 400 * @param retval Return value. 401 * @param arg1 First return argument. 402 * @param arg2 Second return argument. 403 * @param arg3 Third return argument. 404 * @param arg4 Fourth return argument. 405 * 406 * @return Zero on success. 407 * @return Value from @ref errno.h on failure. 408 * 390 409 */ 391 410 sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, … … 396 415 } 397 416 398 /** Answer a received call - slow full version. 399 * 400 * @param callid Hash of the call being answered. 401 * @param retval Return value. 402 * @param arg1 First return argument. 403 * @param arg2 Second return argument. 404 * @param arg3 Third return argument. 405 * @param arg4 Fourth return argument. 406 * @param arg5 Fifth return argument. 407 * 408 * @return Zero on success or a value from @ref errno.h on failure. 417 /** Answer received call (entire payload). 418 * 419 * @param callid Hash of the call being answered. 420 * @param retval Return value. 421 * @param arg1 First return argument. 422 * @param arg2 Second return argument. 423 * @param arg3 Third return argument. 424 * @param arg4 Fourth return argument. 425 * @param arg5 Fifth return argument. 426 * 427 * @return Zero on success. 428 * @return Value from @ref errno.h on failure. 429 * 409 430 */ 410 431 sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, … … 412 433 { 413 434 ipc_call_t data; 414 435 415 436 IPC_SET_RETVAL(data, retval); 416 437 IPC_SET_ARG1(data, arg1); … … 419 440 IPC_SET_ARG4(data, arg4); 420 441 IPC_SET_ARG5(data, arg5); 421 442 422 443 return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data); 423 444 } 424 445 425 426 /** Try to dispatch queued calls from the async queue. */ 427 static void try_dispatch_queued_calls(void) 428 { 429 async_call_t *call; 430 ipc_callid_t callid; 431 446 /** Try to dispatch queued calls from the async queue. 447 * 448 */ 449 static void dispatch_queued_calls(void) 450 { 432 451 /** @todo 433 * Integrate intelligently ipc_futex ,so that it is locked during434 * ipc_call_async_*() ,until it is added to dispatched_calls.452 * Integrate intelligently ipc_futex so that it is locked during 453 * ipc_call_async_*() until it is added to dispatched_calls. 435 454 */ 455 436 456 futex_down(&async_futex); 457 437 458 while (!list_empty(&queued_calls)) { 438 call = list_get_instance(queued_calls.next, async_call_t, list); 439 callid = _ipc_call_async(call->u.msg.phoneid, 440 &call->u.msg.data); 441 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 459 async_call_t *call = 460 list_get_instance(queued_calls.next, async_call_t, list); 461 ipc_callid_t callid = 462 ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data); 463 464 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) 442 465 break; 443 }466 444 467 list_remove(&call->list); 445 468 446 469 futex_up(&async_futex); 470 447 471 if (call->fid) 448 472 fibril_add_ready(call->fid); … … 451 475 if (call->callback) 452 476 call->callback(call->private, ENOENT, NULL); 477 453 478 free(call); 454 479 } else { 455 480 call->u.callid = callid; 481 456 482 futex_down(&ipc_futex); 457 483 list_append(&call->list, &dispatched_calls); 458 484 futex_up(&ipc_futex); 459 485 } 486 460 487 futex_down(&async_futex); 461 488 } 489 462 490 futex_up(&async_futex); 463 491 } 464 492 465 /** Handle areceived answer.493 /** Handle received answer. 466 494 * 467 495 * Find the hash of the answer and call the answer callback. 468 496 * 469 * @todo Make it use hash table. 470 * 471 * @param callid Hash of the received answer. 472 * The answer has the same hash as the request OR'ed with 473 * the IPC_CALLID_ANSWERED bit. 474 * @param data Call data of the answer. 497 * The answer has the same hash as the request OR'ed with 498 * the IPC_CALLID_ANSWERED bit. 499 * 500 * @todo Use hash table. 501 * 502 * @param callid Hash of the received answer. 503 * @param data Call data of the answer. 504 * 475 505 */ 476 506 static void handle_answer(ipc_callid_t callid, ipc_call_t *data) 477 507 { 508 callid &= ~IPC_CALLID_ANSWERED; 509 510 futex_down(&ipc_futex); 511 478 512 link_t *item; 479 async_call_t *call;480 481 callid &= ~IPC_CALLID_ANSWERED;482 483 futex_down(&ipc_futex);484 513 for (item = dispatched_calls.next; item != &dispatched_calls; 485 514 item = item->next) { 486 call = list_get_instance(item, async_call_t, list); 515 async_call_t *call = 516 list_get_instance(item, async_call_t, list); 517 487 518 if (call->u.callid == callid) { 488 519 list_remove(&call->list); 520 489 521 futex_up(&ipc_futex); 522 490 523 if (call->callback) 491 call->callback(call->private, 524 call->callback(call->private, 492 525 IPC_GET_RETVAL(*data), data); 526 493 527 free(call); 494 528 return; 495 529 } 496 530 } 531 497 532 futex_up(&ipc_futex); 498 533 } 499 534 500 501 /** Wait for a first call to come. 502 * 503 * @param call Storage where the incoming call data will be stored.504 * @param usec Timeout in microseconds505 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).506 * 507 * @return Hash of the call. Note that certain bits have special508 * meaning. IPC_CALLID_ANSWERED will be set in an answer509 * and IPC_CALLID_NOTIFICATION is used for notifications.510 * 511 */ 512 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec,int flags)513 { 514 ipc_callid_t callid ;515 516 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);535 /** Wait for first IPC call to come. 536 * 537 * @param call Incoming call storage. 538 * @param usec Timeout in microseconds 539 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking). 540 * 541 * @return Hash of the call. Note that certain bits have special 542 * meaning: IPC_CALLID_ANSWERED is set in an answer 543 * and IPC_CALLID_NOTIFICATION is used for notifications. 544 * 545 */ 546 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec, 547 unsigned int flags) 548 { 549 ipc_callid_t callid = 550 __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 551 517 552 /* Handle received answers */ 518 553 if (callid & IPC_CALLID_ANSWERED) { 519 554 handle_answer(callid, call); 520 try_dispatch_queued_calls();555 dispatch_queued_calls(); 521 556 } 522 557 523 558 return callid; 524 559 } 525 560 526 /** Wait some time for an IPC call. 527 * 528 * The call will return after an answer is received. 529 * 530 * @param call Storage where the incoming call data will be stored. 531 * @param usec Timeout in microseconds. 532 * 533 * @return Hash of the answer. 534 */ 535 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec) 561 /** Interrupt one thread of this task from waiting for IPC. 562 * 563 */ 564 void ipc_poke(void) 565 { 566 __SYSCALL0(SYS_IPC_POKE); 567 } 568 569 /** Wait for first IPC call to come. 570 * 571 * Only requests are returned, answers are processed internally. 572 * 573 * @param call Incoming call storage. 574 * @param usec Timeout in microseconds 575 * 576 * @return Hash of the call. 577 * 578 */ 579 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec) 536 580 { 537 581 ipc_callid_t callid; 538 582 539 583 do { 540 584 callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE); 541 585 } while (callid & IPC_CALLID_ANSWERED); 542 586 543 587 return callid; 544 588 } … … 546 590 /** Check if there is an IPC call waiting to be picked up. 547 591 * 548 * @param call Storage where the incoming call will be stored. 549 * @return Hash of the answer. 592 * Only requests are returned, answers are processed internally. 593 * 594 * @param call Incoming call storage. 595 * 596 * @return Hash of the call. 597 * 550 598 */ 551 599 ipc_callid_t ipc_trywait_for_call(ipc_call_t *call) 552 600 { 553 601 ipc_callid_t callid; 554 602 555 603 do { 556 604 callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, 557 605 SYNCH_FLAGS_NON_BLOCKING); 558 606 } while (callid & IPC_CALLID_ANSWERED); 559 607 560 608 return callid; 561 609 } 562 610 563 /** Interrupt one thread of this task from waiting for IPC. */ 564 void ipc_poke(void) 565 { 566 __SYSCALL0(SYS_IPC_POKE); 567 } 568 569 /** Ask destination to do a callback connection. 570 * 571 * @param phoneid Phone handle used for contacting the other side. 572 * @param arg1 Service-defined argument. 573 * @param arg2 Service-defined argument. 574 * @param arg3 Service-defined argument. 575 * @param taskhash Storage where the kernel will store an opaque 576 * identifier of the client task. 577 * @param phonehash Storage where the kernel will store an opaque 578 * identifier of the phone that will be used for incoming 579 * calls. This identifier can be used for connection 580 * tracking. 581 * 582 * @return Zero on success or a negative error code. 583 */ 584 int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, 611 /** Request callback connection. 612 * 613 * The @a taskhash and @a phonehash identifiers returned 614 * by the kernel can be used for connection tracking. 615 * 616 * @param phoneid Phone handle used for contacting the other side. 617 * @param arg1 User defined argument. 618 * @param arg2 User defined argument. 619 * @param arg3 User defined argument. 620 * @param taskhash Opaque identifier of the client task. 621 * @param phonehash Opaque identifier of the phone that will 622 * be used for incoming calls. 623 * 624 * @return Zero on success or a negative error code. 625 * 626 */ 627 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 585 628 sysarg_t *taskhash, sysarg_t *phonehash) 586 629 { … … 589 632 } 590 633 591 /** Ask through phone for a new connection to some service. 592 * 593 * @param phoneid Phone handle used for contacting the other side. 594 * @param arg1 User defined argument. 595 * @param arg2 User defined argument. 596 * @param arg3 User defined argument. 597 * 598 * @return New phone handle on success or a negative error code. 599 */ 600 int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3) 634 /** Request new connection. 635 * 636 * @param phoneid Phone handle used for contacting the other side. 637 * @param arg1 User defined argument. 638 * @param arg2 User defined argument. 639 * @param arg3 User defined argument. 640 * 641 * @return New phone handle on success or a negative error code. 642 * 643 */ 644 int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 601 645 { 602 646 sysarg_t newphid; 603 int res; 604 605 res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 647 int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 606 648 NULL, NULL, NULL, NULL, &newphid); 607 649 if (res) 608 650 return res; 651 609 652 return newphid; 610 653 } 611 654 612 /** Ask through phone for a new connection to some service.655 /** Request new connection (blocking) 613 656 * 614 657 * If the connection is not available at the moment, the 615 * call will block. 616 * 617 * @param phoneid Phone handle used for contacting the other side. 618 * @param arg1 User defined argument. 619 * @param arg2 User defined argument. 620 * @param arg3 User defined argument. 621 * 622 * @return New phone handle on success or a negative error code. 623 */ 624 int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) 658 * call should block. This has to be, however, implemented 659 * on the server side. 660 * 661 * @param phoneid Phone handle used for contacting the other side. 662 * @param arg1 User defined argument. 663 * @param arg2 User defined argument. 664 * @param arg3 User defined argument. 665 * 666 * @return New phone handle on success or a negative error code. 667 * 668 */ 669 int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 670 sysarg_t arg3) 625 671 { 626 672 sysarg_t newphid; 627 int res; 628 629 res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 673 int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 630 674 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 631 675 if (res) 632 676 return res; 677 633 678 return newphid; 634 679 } … … 636 681 /** Hang up a phone. 637 682 * 638 * @param phoneid Handle of the phone to be hung up. 639 * 640 * @return Zero on success or a negative error code. 683 * @param phoneid Handle of the phone to be hung up. 684 * 685 * @return Zero on success or a negative error code. 686 * 641 687 */ 642 688 int ipc_hangup(int phoneid) … … 646 692 647 693 /** Forward a received call to another destination. 694 * 695 * For non-system methods, the old method, arg1 and arg2 are rewritten 696 * by the new values. For system methods, the new method, arg1 and arg2 697 * are written to the old arg1, arg2 and arg3, respectivelly. Calls with 698 * immutable methods are forwarded verbatim. 648 699 * 649 700 * @param callid Hash of the call to forward. … … 656 707 * @return Zero on success or an error code. 657 708 * 658 * For non-system methods, the old method, arg1 and arg2 are rewritten by the 659 * new values. For system methods, the new method, arg1 and arg2 are written 660 * to the old arg1, arg2 and arg3, respectivelly. Calls with immutable 661 * methods are forwarded verbatim. 662 */ 663 int ipc_forward_fast(ipc_callid_t callid, int phoneid, int imethod, 664 sysarg_t arg1, sysarg_t arg2, int mode) 709 */ 710 int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 711 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 665 712 { 666 713 return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1, … … 668 715 } 669 716 670 671 int ipc_forward_slow(ipc_callid_t callid, int phoneid, int imethod, 717 int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 672 718 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 673 int mode)719 unsigned int mode) 674 720 { 675 721 ipc_call_t data; … … 682 728 IPC_SET_ARG5(data, arg5); 683 729 684 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode); 685 } 686 687 /** Wrapper for making IPC_M_SHARE_IN calls. 688 * 689 * @param phoneid Phone that will be used to contact the receiving side. 690 * @param dst Destination address space area base. 691 * @param size Size of the destination address space area. 692 * @param arg User defined argument. 693 * @param flags Storage where the received flags will be stored. Can be 694 * NULL. 695 * 696 * @return Zero on success or a negative error code from errno.h. 730 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, 731 mode); 732 } 733 734 /** Wrapper for IPC_M_SHARE_IN calls. 735 * 736 * @param phoneid Phone that will be used to contact the receiving side. 737 * @param dst Destination address space area base. 738 * @param size Size of the destination address space area. 739 * @param arg User defined argument. 740 * @param flags Storage for received flags. Can be NULL. 741 * 742 * @return Zero on success or a negative error code from errno.h. 743 * 697 744 */ 698 745 int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 699 int *flags)746 unsigned int *flags) 700 747 { 701 748 sysarg_t tmp_flags = 0; … … 704 751 705 752 if (flags) 706 *flags = tmp_flags;753 *flags = (unsigned int) tmp_flags; 707 754 708 755 return res; … … 711 758 /** Wrapper for answering the IPC_M_SHARE_IN calls. 712 759 * 713 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 714 * so that the user doesn't have to remember the meaning of each IPC argument. 715 * 716 * @param callid Hash of the IPC_M_DATA_READ call to answer. 717 * @param src Source address space base. 718 * @param flags Flags to be used for sharing. Bits can be only cleared. 719 * 720 * @return Zero on success or a value from @ref errno.h on failure. 721 */ 722 int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags) 760 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 761 * calls so that the user doesn't have to remember the meaning of each 762 * IPC argument. 763 * 764 * @param callid Hash of the IPC_M_DATA_READ call to answer. 765 * @param src Source address space base. 766 * @param flags Flags to be used for sharing. Bits can be only cleared. 767 * 768 * @return Zero on success or a value from @ref errno.h on failure. 769 * 770 */ 771 int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 723 772 { 724 773 return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags); 725 774 } 726 775 727 /** Wrapper for making IPC_M_SHARE_OUT calls. 728 * 729 * @param phoneid Phone that will be used to contact the receiving side. 730 * @param src Source address space area base address. 731 * @param flags Flags to be used for sharing. Bits can be only cleared. 732 * 733 * @return Zero on success or a negative error code from errno.h. 734 */ 735 int ipc_share_out_start(int phoneid, void *src, int flags) 776 /** Wrapper for IPC_M_SHARE_OUT calls. 777 * 778 * @param phoneid Phone that will be used to contact the receiving side. 779 * @param src Source address space area base address. 780 * @param flags Flags to be used for sharing. Bits can be only cleared. 781 * 782 * @return Zero on success or a negative error code from errno.h. 783 * 784 */ 785 int ipc_share_out_start(int phoneid, void *src, unsigned int flags) 736 786 { 737 787 return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, … … 741 791 /** Wrapper for answering the IPC_M_SHARE_OUT calls. 742 792 * 743 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls 744 * so that the user doesn't have to remember the meaning of each IPC argument. 745 * 746 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 747 * @param dst Destination address space area base address. 748 * 749 * @return Zero on success or a value from @ref errno.h on failure. 793 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 794 * calls so that the user doesn't have to remember the meaning of each 795 * IPC argument. 796 * 797 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 798 * @param dst Destination address space area base address. 799 * 800 * @return Zero on success or a value from @ref errno.h on failure. 801 * 750 802 */ 751 803 int ipc_share_out_finalize(ipc_callid_t callid, void *dst) … … 754 806 } 755 807 756 757 /** Wrapper for making IPC_M_DATA_READ calls. 758 * 759 * @param phoneid Phone that will be used to contact the receiving side.760 * @param dst Address of the beginningof the destination buffer.761 * @param size Size of the destination buffer.762 * 763 * @return Zero on success or a negative error code from errno.h.808 /** Wrapper for IPC_M_DATA_READ calls. 809 * 810 * @param phoneid Phone that will be used to contact the receiving side. 811 * @param dst Address of the beginning of the destination buffer. 812 * @param size Size of the destination buffer. 813 * 814 * @return Zero on success or a negative error code from errno.h. 815 * 764 816 */ 765 817 int ipc_data_read_start(int phoneid, void *dst, size_t size) … … 771 823 /** Wrapper for answering the IPC_M_DATA_READ calls. 772 824 * 773 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 774 * so that the user doesn't have to remember the meaning of each IPC argument. 775 * 776 * @param callid Hash of the IPC_M_DATA_READ call to answer. 777 * @param src Source address for the IPC_M_DATA_READ call. 778 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 779 * the maximum size announced by the sender. 780 * 781 * @return Zero on success or a value from @ref errno.h on failure. 825 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 826 * calls so that the user doesn't have to remember the meaning of each 827 * IPC argument. 828 * 829 * @param callid Hash of the IPC_M_DATA_READ call to answer. 830 * @param src Source address for the IPC_M_DATA_READ call. 831 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 832 * the maximum size announced by the sender. 833 * 834 * @return Zero on success or a value from @ref errno.h on failure. 835 * 782 836 */ 783 837 int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) … … 786 840 } 787 841 788 /** Wrapper for making IPC_M_DATA_WRITE calls. 789 * 790 * @param phoneid Phone that will be used to contact the receiving side. 791 * @param src Address of the beginning of the source buffer. 792 * @param size Size of the source buffer. 793 * 794 * @return Zero on success or a negative error code from errno.h. 842 /** Wrapper for IPC_M_DATA_WRITE calls. 843 * 844 * @param phoneid Phone that will be used to contact the receiving side. 845 * @param src Address of the beginning of the source buffer. 846 * @param size Size of the source buffer. 847 * 848 * @return Zero on success or a negative error code from errno.h. 849 * 795 850 */ 796 851 int ipc_data_write_start(int phoneid, const void *src, size_t size) … … 802 857 /** Wrapper for answering the IPC_M_DATA_WRITE calls. 803 858 * 804 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls 805 * so that the user doesn't have to remember the meaning of each IPC argument. 806 * 807 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 808 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 809 * @param size Final size for the IPC_M_DATA_WRITE call. 810 * 811 * @return Zero on success or a value from @ref errno.h on failure. 859 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 860 * calls so that the user doesn't have to remember the meaning of each 861 * IPC argument. 862 * 863 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 864 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 865 * @param size Final size for the IPC_M_DATA_WRITE call. 866 * 867 * @return Zero on success or a value from @ref errno.h on failure. 868 * 812 869 */ 813 870 int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size) -
uspace/lib/c/include/ipc/ipc.h
r6119f24 r10477601 53 53 * possible, the fast version is used. 54 54 */ 55 55 56 #define ipc_call_sync_0_0(phoneid, method) \ 56 57 ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0) … … 182 183 sysarg_t *); 183 184 184 extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int); 185 extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t); 185 extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, sysarg_t, unsigned int); 186 186 extern void ipc_poke(void); 187 187 188 static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data) 189 { 190 return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT); 191 } 192 188 #define ipc_wait_for_call(data) \ 189 ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT); 190 191 extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, sysarg_t); 193 192 extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *); 194 193 … … 199 198 * to m. 200 199 */ 200 201 201 #define ipc_answer_0(callid, retval) \ 202 202 ipc_answer_fast((callid), (retval), 0, 0, 0, 0) … … 223 223 * to m. 224 224 */ 225 225 226 #define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \ 226 227 ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \ … … 248 249 249 250 extern void ipc_call_async_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, 250 sysarg_t, void *, ipc_async_callback_t, int);251 sysarg_t, void *, ipc_async_callback_t, bool); 251 252 extern void ipc_call_async_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, 252 sysarg_t, sysarg_t, void *, ipc_async_callback_t, int); 253 254 extern int ipc_connect_to_me(int, int, int, int, sysarg_t *, sysarg_t *); 255 extern int ipc_connect_me_to(int, int, int, int); 256 extern int ipc_connect_me_to_blocking(int, int, int, int); 253 sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool); 254 255 extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *, 256 sysarg_t *); 257 extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t); 258 extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t); 259 257 260 extern int ipc_hangup(int); 258 extern int ipc_forward_fast(ipc_callid_t, int, int, sysarg_t, sysarg_t, int); 259 extern int ipc_forward_slow(ipc_callid_t, int, int, sysarg_t, sysarg_t, 260 sysarg_t, sysarg_t, sysarg_t, int); 261 262 extern int ipc_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t, 263 unsigned int); 264 extern int ipc_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t, 265 sysarg_t, sysarg_t, sysarg_t, unsigned int); 261 266 262 267 /* 263 268 * User-friendly wrappers for ipc_share_in_start(). 264 269 */ 270 265 271 #define ipc_share_in_start_0_0(phoneid, dst, size) \ 266 272 ipc_share_in_start((phoneid), (dst), (size), 0, NULL) … … 272 278 ipc_share_in_start((phoneid), (dst), (size), (arg), (flags)) 273 279 274 extern int ipc_share_in_start(int, void *, size_t, sysarg_t, int *);275 extern int ipc_share_in_finalize(ipc_callid_t, void *, int);276 extern int ipc_share_out_start(int, void *, int);280 extern int ipc_share_in_start(int, void *, size_t, sysarg_t, unsigned int *); 281 extern int ipc_share_in_finalize(ipc_callid_t, void *, unsigned int); 282 extern int ipc_share_out_start(int, void *, unsigned int); 277 283 extern int ipc_share_out_finalize(ipc_callid_t, void *); 278 284 extern int ipc_data_read_start(int, void *, size_t);
Note:
See TracChangeset
for help on using the changeset viewer.