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