Changeset da1bafb in mainline for kernel/generic/src/ipc
- Timestamp:
- 2010-05-24T18:57:31Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0095368
- Parents:
- 666f492
- Location:
- kernel/generic/src/ipc
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r666f492 rda1bafb 137 137 IPC_SET_ARG5(call->data, a5); 138 138 139 ipl_t ipl = interrupts_disable(); 140 spinlock_lock(&events[evno].answerbox->irq_lock); 139 irq_spinlock_lock(&events[evno].answerbox->irq_lock, true); 141 140 list_append(&call->link, &events[evno].answerbox->irq_notifs); 142 spinlock_unlock(&events[evno].answerbox->irq_lock); 143 interrupts_restore(ipl); 141 irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true); 144 142 145 143 waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST); -
kernel/generic/src/ipc/ipc.c
r666f492 rda1bafb 66 66 /** Initialize a call structure. 67 67 * 68 * @param call Call structure to be initialized. 68 * @param call Call structure to be initialized. 69 * 69 70 */ 70 71 static void _ipc_call_init(call_t *call) … … 77 78 78 79 /** Allocate and initialize a call structure. 79 * 80 * 80 81 * The call is initialized, so that the reply will be directed to 81 82 * TASK->answerbox. 82 83 * 83 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 84 * 85 * @return If flags permit it, return NULL, or initialized kernel 86 * call structure. 87 */ 88 call_t *ipc_call_alloc(int flags) 89 { 90 call_t *call; 91 92 call = slab_alloc(ipc_call_slab, flags); 84 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 85 * 86 * @return If flags permit it, return NULL, or initialized kernel 87 * call structure. 88 * 89 */ 90 call_t *ipc_call_alloc(unsigned int flags) 91 { 92 call_t *call = slab_alloc(ipc_call_slab, flags); 93 93 if (call) 94 94 _ipc_call_init(call); 95 95 96 96 return call; 97 97 } … … 99 99 /** Deallocate a call structure. 100 100 * 101 * @param call Call structure to be freed. 101 * @param call Call structure to be freed. 102 * 102 103 */ 103 104 void ipc_call_free(call_t *call) … … 111 112 /** Initialize an answerbox structure. 112 113 * 113 * @param box Answerbox structure to be initialized. 114 * @param task Task to which the answerbox belongs. 114 * @param box Answerbox structure to be initialized. 115 * @param task Task to which the answerbox belongs. 116 * 115 117 */ 116 118 void ipc_answerbox_init(answerbox_t *box, task_t *task) 117 119 { 118 spinlock_initialize(&box->lock, "ipc_box_lock");119 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");120 irq_spinlock_initialize(&box->lock, "ipc.box.lock"); 121 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock"); 120 122 waitq_initialize(&box->wq); 121 123 link_initialize(&box->sync_box_link); … … 131 133 /** Connect a phone to an answerbox. 132 134 * 133 * @param phone Initialized phone structure. 134 * @param box Initialized answerbox structure. 135 * @param phone Initialized phone structure. 136 * @param box Initialized answerbox structure. 137 * 135 138 */ 136 139 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 137 140 { 138 141 mutex_lock(&phone->lock); 139 142 140 143 phone->state = IPC_PHONE_CONNECTED; 141 144 phone->callee = box; 142 143 spinlock_lock(&box->lock);145 146 irq_spinlock_lock(&box->lock, true); 144 147 list_append(&phone->link, &box->connected_phones); 145 spinlock_unlock(&box->lock);146 148 irq_spinlock_unlock(&box->lock, true); 149 147 150 mutex_unlock(&phone->lock); 148 151 } … … 150 153 /** Initialize a phone structure. 151 154 * 152 * @param phone Phone structure to be initialized. 155 * @param phone Phone structure to be initialized. 156 * 153 157 */ 154 158 void ipc_phone_init(phone_t *phone) … … 162 166 /** Helper function to facilitate synchronous calls. 163 167 * 164 * @param phone Destination kernel phone structure. 165 * @param request Call structure with request. 166 * 167 * @return EOK on success or EINTR if the sleep was interrupted. 168 * @param phone Destination kernel phone structure. 169 * @param request Call structure with request. 170 * 171 * @return EOK on success or EINTR if the sleep was interrupted. 172 * 168 173 */ 169 174 int ipc_call_sync(phone_t *phone, call_t *request) 170 175 { 171 answerbox_t *sync_box; 172 ipl_t ipl; 173 174 sync_box = slab_alloc(ipc_answerbox_slab, 0); 176 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0); 175 177 ipc_answerbox_init(sync_box, TASK); 176 178 177 179 /* 178 180 * Put the answerbox on the TASK's list of synchronous answerboxes so 179 181 * that it can be cleaned up if the call is interrupted. 180 182 */ 181 ipl = interrupts_disable(); 182 spinlock_lock(&TASK->lock); 183 irq_spinlock_lock(&TASK->lock, true); 183 184 list_append(&sync_box->sync_box_link, &TASK->sync_box_head); 184 spinlock_unlock(&TASK->lock); 185 interrupts_restore(ipl); 186 185 irq_spinlock_unlock(&TASK->lock, true); 186 187 187 /* We will receive data in a special box. */ 188 188 request->callerbox = sync_box; 189 189 190 190 ipc_call(phone, request); 191 191 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT, 192 192 SYNCH_FLAGS_INTERRUPTIBLE)) { 193 193 /* The answerbox and the call will be freed by ipc_cleanup(). */ 194 194 return EINTR; 195 195 } 196 196 197 197 /* 198 198 * The answer arrived without interruption so we can remove the 199 199 * answerbox from the TASK's list of synchronous answerboxes. 200 200 */ 201 (void) interrupts_disable(); 202 spinlock_lock(&TASK->lock); 201 irq_spinlock_lock(&TASK->lock, true); 203 202 list_remove(&sync_box->sync_box_link); 204 spinlock_unlock(&TASK->lock); 205 interrupts_restore(ipl); 206 203 irq_spinlock_unlock(&TASK->lock, true); 204 207 205 slab_free(ipc_answerbox_slab, sync_box); 208 206 return EOK; … … 211 209 /** Answer a message which was not dispatched and is not listed in any queue. 212 210 * 213 * @param call Call structure to be answered. 214 * @param selflocked If true, then TASK->answebox is locked. 211 * @param call Call structure to be answered. 212 * @param selflocked If true, then TASK->answebox is locked. 213 * 215 214 */ 216 215 static void _ipc_answer_free_call(call_t *call, bool selflocked) … … 218 217 answerbox_t *callerbox = call->callerbox; 219 218 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 220 ipl_t ipl; 221 219 222 220 /* Count sent answer */ 223 ipl = interrupts_disable(); 224 spinlock_lock(&TASK->lock); 221 irq_spinlock_lock(&TASK->lock, true); 225 222 TASK->ipc_info.answer_sent++; 226 spinlock_unlock(&TASK->lock); 227 interrupts_restore(ipl); 228 223 irq_spinlock_unlock(&TASK->lock, true); 224 229 225 call->flags |= IPC_CALL_ANSWERED; 230 226 231 227 if (call->flags & IPC_CALL_FORWARDED) { 232 228 if (call->caller_phone) { … … 235 231 } 236 232 } 237 233 238 234 if (do_lock) 239 spinlock_lock(&callerbox->lock); 235 irq_spinlock_lock(&callerbox->lock, true); 236 240 237 list_append(&call->link, &callerbox->answers); 238 241 239 if (do_lock) 242 spinlock_unlock(&callerbox->lock); 240 irq_spinlock_unlock(&callerbox->lock, true); 241 243 242 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 244 243 } … … 246 245 /** Answer a message which is in a callee queue. 247 246 * 248 * @param box Answerbox that is answering the message. 249 * @param call Modified request that is being sent back. 247 * @param box Answerbox that is answering the message. 248 * @param call Modified request that is being sent back. 249 * 250 250 */ 251 251 void ipc_answer(answerbox_t *box, call_t *call) 252 252 { 253 253 /* Remove from active box */ 254 spinlock_lock(&box->lock);254 irq_spinlock_lock(&box->lock, true); 255 255 list_remove(&call->link); 256 spinlock_unlock(&box->lock); 256 irq_spinlock_unlock(&box->lock, true); 257 257 258 /* Send back answer */ 258 259 _ipc_answer_free_call(call, false); … … 264 265 * message and sending it as a normal answer. 265 266 * 266 * @param phone Phone structure the call should appear to come from. 267 * @param call Call structure to be answered. 268 * @param err Return value to be used for the answer. 267 * @param phone Phone structure the call should appear to come from. 268 * @param call Call structure to be answered. 269 * @param err Return value to be used for the answer. 270 * 269 271 */ 270 272 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) … … 278 280 /** Unsafe unchecking version of ipc_call. 279 281 * 280 * @param phone Phone structure the call comes from. 281 * @param box Destination answerbox structure. 282 * @param call Call structure with request. 282 * @param phone Phone structure the call comes from. 283 * @param box Destination answerbox structure. 284 * @param call Call structure with request. 285 * 283 286 */ 284 287 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 285 288 { 286 ipl_t ipl;287 288 289 /* Count sent ipc call */ 289 ipl = interrupts_disable(); 290 spinlock_lock(&TASK->lock); 290 irq_spinlock_lock(&TASK->lock, true); 291 291 TASK->ipc_info.call_sent++; 292 spinlock_unlock(&TASK->lock); 293 interrupts_restore(ipl); 294 292 irq_spinlock_unlock(&TASK->lock, true); 293 295 294 if (!(call->flags & IPC_CALL_FORWARDED)) { 296 295 atomic_inc(&phone->active_calls); 297 296 call->data.phone = phone; 298 297 } 299 300 spinlock_lock(&box->lock);298 299 irq_spinlock_lock(&box->lock, true); 301 300 list_append(&call->link, &box->calls); 302 spinlock_unlock(&box->lock); 301 irq_spinlock_unlock(&box->lock, true); 302 303 303 waitq_wakeup(&box->wq, WAKEUP_FIRST); 304 304 } … … 306 306 /** Send an asynchronous request using a phone to an answerbox. 307 307 * 308 * @param phone Phone structure the call comes from and which is 309 * connected to the destination answerbox. 310 * @param call Call structure with request. 311 * 312 * @return Return 0 on success, ENOENT on error. 308 * @param phone Phone structure the call comes from and which is 309 * connected to the destination answerbox. 310 * @param call Call structure with request. 311 * 312 * @return Return 0 on success, ENOENT on error. 313 * 313 314 */ 314 315 int ipc_call(phone_t *phone, call_t *call) 315 316 { 316 answerbox_t *box;317 318 317 mutex_lock(&phone->lock); 319 318 if (phone->state != IPC_PHONE_CONNECTED) { … … 328 327 ipc_backsend_err(phone, call, ENOENT); 329 328 } 329 330 330 return ENOENT; 331 331 } 332 box = phone->callee; 332 333 answerbox_t *box = phone->callee; 333 334 _ipc_call(phone, box, call); 334 335 … … 342 343 * lazily later. 343 344 * 344 * @param phone Phone structure to be hung up. 345 * 346 * @return Return 0 if the phone is disconnected. 347 * Return -1 if the phone was already disconnected. 345 * @param phone Phone structure to be hung up. 346 * 347 * @return 0 if the phone is disconnected. 348 * @return -1 if the phone was already disconnected. 349 * 348 350 */ 349 351 int ipc_phone_hangup(phone_t *phone) 350 352 { 351 answerbox_t *box;352 call_t *call;353 354 353 mutex_lock(&phone->lock); 355 354 if (phone->state == IPC_PHONE_FREE || … … 359 358 return -1; 360 359 } 361 box = phone->callee; 360 361 answerbox_t *box = phone->callee; 362 362 if (phone->state != IPC_PHONE_SLAMMED) { 363 363 /* Remove myself from answerbox */ 364 spinlock_lock(&box->lock);364 irq_spinlock_lock(&box->lock, true); 365 365 list_remove(&phone->link); 366 spinlock_unlock(&box->lock);367 368 call = ipc_call_alloc(0);366 irq_spinlock_unlock(&box->lock, true); 367 368 call_t *call = ipc_call_alloc(0); 369 369 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 370 370 call->flags |= IPC_CALL_DISCARD_ANSWER; 371 371 _ipc_call(phone, box, call); 372 372 } 373 373 374 374 phone->state = IPC_PHONE_HUNGUP; 375 375 mutex_unlock(&phone->lock); 376 376 377 377 return 0; 378 378 } … … 380 380 /** Forwards call from one answerbox to another one. 381 381 * 382 * @param call 383 * @param newphone 384 * @param oldbox 385 * @param mode 386 * 387 * @return Return0 if forwarding succeeded or an error code if388 * there waserror.389 * 382 * @param call Call structure to be redirected. 383 * @param newphone Phone structure to target answerbox. 384 * @param oldbox Old answerbox structure. 385 * @param mode Flags that specify mode of the forward operation. 386 * 387 * @return 0 if forwarding succeeded or an error code if 388 * there was an error. 389 * 390 390 * The return value serves only as an information for the forwarder, 391 391 * the original caller is notified automatically with EFORWARD. 392 * /393 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 394 { 395 ipl_t ipl; 396 392 * 393 */ 394 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, 395 unsigned int mode) 396 { 397 397 /* Count forwarded calls */ 398 ipl = interrupts_disable(); 399 spinlock_lock(&TASK->lock); 398 irq_spinlock_lock(&TASK->lock, true); 400 399 TASK->ipc_info.forwarded++; 401 spinlock_unlock(&TASK->lock); 402 interrupts_restore(ipl); 403 404 spinlock_lock(&oldbox->lock); 400 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 405 401 list_remove(&call->link); 406 spinlock_unlock(&oldbox->lock);407 402 irq_spinlock_unlock(&oldbox->lock, true); 403 408 404 if (mode & IPC_FF_ROUTE_FROM_ME) { 409 405 if (!call->caller_phone) … … 411 407 call->data.phone = newphone; 412 408 } 413 409 414 410 return ipc_call(newphone, call); 415 411 } … … 418 414 /** Wait for a phone call. 419 415 * 420 * @param box Answerbox expecting the call. 421 * @param usec Timeout in microseconds. See documentation for 422 * waitq_sleep_timeout() for decription of its special 423 * meaning. 424 * @param flags Select mode of sleep operation. See documentation for 425 * waitq_sleep_timeout() for description of its special 426 * meaning. 427 * @return Recived call structure or NULL. 428 * 416 * @param box Answerbox expecting the call. 417 * @param usec Timeout in microseconds. See documentation for 418 * waitq_sleep_timeout() for decription of its special 419 * meaning. 420 * @param flags Select mode of sleep operation. See documentation for 421 * waitq_sleep_timeout() for description of its special 422 * meaning. 423 * 424 * @return Recived call structure or NULL. 425 * 429 426 * To distinguish between a call and an answer, have a look at call->flags. 430 */ 431 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 427 * 428 */ 429 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags) 432 430 { 433 431 call_t *request; 434 ipl_t ipl;435 432 uint64_t irq_cnt = 0; 436 433 uint64_t answer_cnt = 0; 437 434 uint64_t call_cnt = 0; 438 435 int rc; 439 436 440 437 restart: 441 438 rc = waitq_sleep_timeout(&box->wq, usec, flags); … … 443 440 return NULL; 444 441 445 spinlock_lock(&box->lock);442 irq_spinlock_lock(&box->lock, true); 446 443 if (!list_empty(&box->irq_notifs)) { 447 444 /* Count recieved IRQ notification */ 448 irq_cnt++; 449 450 ipl = interrupts_disable(); 451 spinlock_lock(&box->irq_lock); 452 445 irq_cnt++; 446 447 irq_spinlock_lock(&box->irq_lock, false); 448 453 449 request = list_get_instance(box->irq_notifs.next, call_t, link); 454 450 list_remove(&request->link); 455 456 spinlock_unlock(&box->irq_lock); 457 interrupts_restore(ipl); 451 452 irq_spinlock_unlock(&box->irq_lock, false); 458 453 } else if (!list_empty(&box->answers)) { 459 454 /* Count recieved answer */ 460 455 answer_cnt++; 461 456 462 457 /* Handle asynchronous answers */ 463 458 request = list_get_instance(box->answers.next, call_t, link); … … 467 462 /* Count recieved call */ 468 463 call_cnt++; 469 464 470 465 /* Handle requests */ 471 466 request = list_get_instance(box->calls.next, call_t, link); 472 467 list_remove(&request->link); 468 473 469 /* Append request to dispatch queue */ 474 470 list_append(&request->link, &box->dispatched_calls); 475 471 } else { 476 472 /* This can happen regularly after ipc_cleanup */ 477 spinlock_unlock(&box->lock);473 irq_spinlock_unlock(&box->lock, true); 478 474 goto restart; 479 475 } 480 spinlock_unlock(&box->lock); 481 482 ipl = interrupts_disable(); 483 spinlock_lock(&TASK->lock); 476 477 irq_spinlock_pass(&box->lock, &TASK->lock); 478 484 479 TASK->ipc_info.irq_notif_recieved += irq_cnt; 485 480 TASK->ipc_info.answer_recieved += answer_cnt; 486 481 TASK->ipc_info.call_recieved += call_cnt; 487 spinlock_unlock(&TASK->lock);488 i nterrupts_restore(ipl);489 482 483 irq_spinlock_unlock(&TASK->lock, true); 484 490 485 return request; 491 486 } … … 493 488 /** Answer all calls from list with EHANGUP answer. 494 489 * 495 * @param lst Head of the list to be cleaned up. 490 * @param lst Head of the list to be cleaned up. 491 * 496 492 */ 497 493 void ipc_cleanup_call_list(link_t *lst) 498 494 { 499 call_t *call;500 501 495 while (!list_empty(lst)) { 502 call = list_get_instance(lst->next, call_t, link);496 call_t *call = list_get_instance(lst->next, call_t, link); 503 497 if (call->buffer) 504 498 free(call->buffer); 499 505 500 list_remove(&call->link); 506 501 507 502 IPC_SET_RETVAL(call->data, EHANGUP); 508 503 _ipc_answer_free_call(call, true); … … 512 507 /** Disconnects all phones connected to an answerbox. 513 508 * 514 * @param box Answerbox to disconnect phones from. 515 * @param notify_box If true, the answerbox will get a hangup message for 516 * each disconnected phone. 509 * @param box Answerbox to disconnect phones from. 510 * @param notify_box If true, the answerbox will get a hangup message for 511 * each disconnected phone. 512 * 517 513 */ 518 514 void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) … … 520 516 phone_t *phone; 521 517 DEADLOCK_PROBE_INIT(p_phonelck); 522 ipl_t ipl; 523 call_t *call; 524 525 call = notify_box ? ipc_call_alloc(0) : NULL; 526 518 519 call_t *call = notify_box ? ipc_call_alloc(0) : NULL; 520 527 521 /* Disconnect all phones connected to our answerbox */ 528 522 restart_phones: 529 ipl = interrupts_disable(); 530 spinlock_lock(&box->lock); 523 irq_spinlock_lock(&box->lock, true); 531 524 while (!list_empty(&box->connected_phones)) { 532 525 phone = list_get_instance(box->connected_phones.next, 533 526 phone_t, link); 534 527 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 535 spinlock_unlock(&box->lock); 536 interrupts_restore(ipl); 528 irq_spinlock_unlock(&box->lock, true); 537 529 DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); 538 530 goto restart_phones; … … 541 533 /* Disconnect phone */ 542 534 ASSERT(phone->state == IPC_PHONE_CONNECTED); 543 535 544 536 list_remove(&phone->link); 545 537 phone->state = IPC_PHONE_SLAMMED; 546 538 547 539 if (notify_box) { 548 540 mutex_unlock(&phone->lock); 549 spinlock_unlock(&box->lock); 550 interrupts_restore(ipl); 551 541 irq_spinlock_unlock(&box->lock, true); 542 552 543 /* 553 544 * Send one message to the answerbox for each … … 559 550 call->flags |= IPC_CALL_DISCARD_ANSWER; 560 551 _ipc_call(phone, box, call); 561 552 562 553 /* Allocate another call in advance */ 563 554 call = ipc_call_alloc(0); 564 555 565 556 /* Must start again */ 566 557 goto restart_phones; 567 558 } 568 559 569 560 mutex_unlock(&phone->lock); 570 561 } 571 572 spinlock_unlock(&box->lock); 573 interrupts_restore(ipl); 574 562 563 irq_spinlock_unlock(&box->lock, true); 564 575 565 /* Free unused call */ 576 566 if (call) … … 578 568 } 579 569 580 /** Clean sup all IPC communication of the current task.570 /** Clean up all IPC communication of the current task. 581 571 * 582 572 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 583 573 * have to change it as well if you want to cleanup other tasks than TASK. 574 * 584 575 */ 585 576 void ipc_cleanup(void) 586 577 { 587 int i;588 call_t *call;589 ipl_t ipl;590 591 578 /* Disconnect all our phones ('ipc_phone_hangup') */ 579 size_t i; 592 580 for (i = 0; i < IPC_MAX_PHONES; i++) 593 581 ipc_phone_hangup(&TASK->phones[i]); 594 582 595 583 /* Unsubscribe from any event notifications. */ 596 584 event_cleanup_answerbox(&TASK->answerbox); 597 585 598 586 /* Disconnect all connected irqs */ 599 587 ipc_irq_cleanup(&TASK->answerbox); 600 588 601 589 /* Disconnect all phones connected to our regular answerbox */ 602 590 ipc_answerbox_slam_phones(&TASK->answerbox, false); 603 591 604 592 #ifdef CONFIG_UDEBUG 605 593 /* Clean up kbox thread and communications */ 606 594 ipc_kbox_cleanup(); 607 595 #endif 608 596 609 597 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 610 spinlock_lock(&TASK->answerbox.lock);598 irq_spinlock_lock(&TASK->answerbox.lock, true); 611 599 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 612 600 ipc_cleanup_call_list(&TASK->answerbox.calls); 613 spinlock_unlock(&TASK->answerbox.lock);601 irq_spinlock_unlock(&TASK->answerbox.lock, true); 614 602 615 603 /* Wait for all answers to interrupted synchronous calls to arrive */ 616 ipl = interrupts_disable();604 ipl_t ipl = interrupts_disable(); 617 605 while (!list_empty(&TASK->sync_box_head)) { 618 606 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 619 607 answerbox_t, sync_box_link); 620 608 621 609 list_remove(&box->sync_box_link); 622 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,610 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 623 611 SYNCH_FLAGS_NONE); 624 612 ipc_call_free(call); … … 626 614 } 627 615 interrupts_restore(ipl); 628 616 629 617 /* Wait for all answers to asynchronous calls to arrive */ 630 while (1) { 631 /* Go through all phones, until all are FREE... */ 632 /* Locking not needed, no one else should modify 633 * it, when we are in cleanup */ 618 while (true) { 619 /* 620 * Go through all phones, until they are all FREE 621 * Locking is not needed, no one else should modify 622 * it when we are in cleanup 623 */ 634 624 for (i = 0; i < IPC_MAX_PHONES; i++) { 635 625 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && … … 639 629 } 640 630 641 /* Just for sure, we might have had some 642 * IPC_PHONE_CONNECTING phones */ 631 /* 632 * Just for sure, we might have had some 633 * IPC_PHONE_CONNECTING phones 634 */ 643 635 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 644 636 ipc_phone_hangup(&TASK->phones[i]); 645 /* If the hangup succeeded, it has sent a HANGUP 637 638 /* 639 * If the hangup succeeded, it has sent a HANGUP 646 640 * message, the IPC is now in HUNGUP state, we 647 * wait for the reply to come */ 641 * wait for the reply to come 642 */ 648 643 649 644 if (TASK->phones[i].state != IPC_PHONE_FREE) 650 645 break; 651 646 } 652 /* Voila, got into cleanup */ 647 648 /* Got into cleanup */ 653 649 if (i == IPC_MAX_PHONES) 654 650 break; 655 651 656 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,652 call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 657 653 SYNCH_FLAGS_NONE); 658 654 ASSERT((call->flags & IPC_CALL_ANSWERED) || … … 666 662 if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) 667 663 atomic_dec(&TASK->active_calls); 664 668 665 ipc_call_free(call); 669 666 } 670 667 } 671 668 672 673 /** Initilize IPC subsystem */ 669 /** Initilize IPC subsystem 670 * 671 */ 674 672 void ipc_init(void) 675 673 { … … 680 678 } 681 679 682 683 680 /** List answerbox contents. 684 681 * 685 * @param taskid Task ID. 682 * @param taskid Task ID. 683 * 686 684 */ 687 685 void ipc_print_task(task_id_t taskid) 688 686 { 689 task_t *task; 690 int i; 691 call_t *call; 692 link_t *tmp; 693 ipl_t ipl; 694 695 ipl = interrupts_disable(); 696 spinlock_lock(&tasks_lock); 697 task = task_find_by_id(taskid); 698 if (task) 699 spinlock_lock(&task->lock); 700 spinlock_unlock(&tasks_lock); 687 irq_spinlock_lock(&tasks_lock, true); 688 task_t *task = task_find_by_id(taskid); 689 701 690 if (!task) { 702 i nterrupts_restore(ipl);691 irq_spinlock_unlock(&tasks_lock, true); 703 692 return; 704 693 } 705 694 695 /* Hand-over-hand locking */ 696 irq_spinlock_exchange(&tasks_lock, &task->lock); 697 706 698 /* Print opened phones & details */ 707 699 printf("PHONE:\n"); 700 701 size_t i; 708 702 for (i = 0; i < IPC_MAX_PHONES; i++) { 709 703 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { … … 711 705 continue; 712 706 } 707 713 708 if (task->phones[i].state != IPC_PHONE_FREE) { 714 printf("%d: ", i); 709 printf("%" PRIs ": ", i); 710 715 711 switch (task->phones[i].state) { 716 712 case IPC_PHONE_CONNECTING: … … 718 714 break; 719 715 case IPC_PHONE_CONNECTED: 720 printf("connected to: %p ", 721 716 printf("connected to: %p ", 717 task->phones[i].callee); 722 718 break; 723 719 case IPC_PHONE_SLAMMED: 724 720 printf("slammed by: %p ", 725 721 task->phones[i].callee); 726 722 break; 727 723 case IPC_PHONE_HUNGUP: 728 724 printf("hung up - was: %p ", 729 725 task->phones[i].callee); 730 726 break; 731 727 default: 732 728 break; 733 729 } 734 printf("active: %ld\n", 730 731 printf("active: %" PRIun "\n", 735 732 atomic_get(&task->phones[i].active_calls)); 736 733 } 734 737 735 mutex_unlock(&task->phones[i].lock); 738 736 } 739 740 737 738 irq_spinlock_lock(&task->answerbox.lock, false); 739 740 link_t *cur; 741 741 742 /* Print answerbox - calls */ 742 spinlock_lock(&task->answerbox.lock);743 743 printf("ABOX - CALLS:\n"); 744 for ( tmp = task->answerbox.calls.next; tmp!= &task->answerbox.calls;745 tmp = tmp->next) {746 call = list_get_instance(tmp, call_t, link);744 for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls; 745 cur = cur->next) { 746 call_t *call = list_get_instance(cur, call_t, link); 747 747 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 748 748 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 754 754 call->flags); 755 755 } 756 /* Print answerbox - calls */ 756 757 /* Print answerbox - dispatched calls */ 757 758 printf("ABOX - DISPATCHED CALLS:\n"); 758 for ( tmp= task->answerbox.dispatched_calls.next;759 tmp != &task->answerbox.dispatched_calls;760 tmp = tmp->next) {761 call = list_get_instance(tmp, call_t, link);759 for (cur = task->answerbox.dispatched_calls.next; 760 cur != &task->answerbox.dispatched_calls; 761 cur = cur->next) { 762 call_t *call = list_get_instance(cur, call_t, link); 762 763 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 763 764 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 769 770 call->flags); 770 771 } 771 /* Print answerbox - calls */ 772 773 /* Print answerbox - answers */ 772 774 printf("ABOX - ANSWERS:\n"); 773 for ( tmp= task->answerbox.answers.next;774 tmp!= &task->answerbox.answers;775 tmp = tmp->next) {776 call = list_get_instance(tmp, call_t, link);775 for (cur = task->answerbox.answers.next; 776 cur != &task->answerbox.answers; 777 cur = cur->next) { 778 call_t *call = list_get_instance(cur, call_t, link); 777 779 printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun 778 780 " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", … … 782 784 call->flags); 783 785 } 784 785 spinlock_unlock(&task->answerbox.lock); 786 spinlock_unlock(&task->lock); 787 interrupts_restore(ipl); 786 787 irq_spinlock_unlock(&task->answerbox.lock, false); 788 irq_spinlock_unlock(&task->lock, true); 788 789 } 789 790 -
kernel/generic/src/ipc/ipcrsc.c
r666f492 rda1bafb 45 45 * - hangup phone (the caller has hung up) 46 46 * - hangup phone (the answerbox is exiting) 47 * 47 * 48 48 * Locking strategy 49 49 * … … 85 85 * 86 86 * Phone hangup 87 * 87 * 88 88 * *** The caller hangs up (sys_ipc_hangup) *** 89 89 * - The phone is disconnected (no more messages can be sent over this phone), … … 99 99 * 100 100 * Call forwarding 101 * 101 * 102 102 * The call can be forwarded, so that the answer to call is passed directly 103 103 * to the original sender. However, this poses special problems regarding … … 114 114 * 115 115 * Cleanup strategy 116 * 116 * 117 117 * 1) Disconnect all our phones ('ipc_phone_hangup'). 118 118 * … … 123 123 * 124 124 * 4) Wait for all async answers to arrive and dispose of them. 125 * 125 * 126 126 */ 127 127 … … 137 137 * @todo Some speedup (hash table?) 138 138 * 139 * @param callid Userspace hash of the call. Currently it is the call 140 * structure kernel address. 141 * 142 * @return NULL on not found, otherwise pointer to the call 143 * structure. 139 * @param callid Userspace hash of the call. Currently it is the call 140 * structure kernel address. 141 * 142 * @return NULL on not found, otherwise pointer to the call 143 * structure. 144 * 144 145 */ 145 146 call_t *get_call(unative_t callid) 146 147 { 147 148 link_t *lst; 148 call_t * call, *result = NULL;149 150 spinlock_lock(&TASK->answerbox.lock);149 call_t *result = NULL; 150 151 irq_spinlock_lock(&TASK->answerbox.lock, true); 151 152 for (lst = TASK->answerbox.dispatched_calls.next; 152 153 lst != &TASK->answerbox.dispatched_calls; lst = lst->next) { 153 call = list_get_instance(lst, call_t, link);154 call_t *call = list_get_instance(lst, call_t, link); 154 155 if ((unative_t) call == callid) { 155 156 result = call; … … 157 158 } 158 159 } 159 spinlock_unlock(&TASK->answerbox.lock); 160 161 irq_spinlock_unlock(&TASK->answerbox.lock, true); 160 162 return result; 161 163 } … … 163 165 /** Allocate new phone slot in the specified task. 164 166 * 165 * @param t Task for which to allocate a new phone. 166 * 167 * @return New phone handle or -1 if the phone handle limit is 168 * exceeded. 169 */ 170 int phone_alloc(task_t *t) 171 { 172 int i; 173 174 spinlock_lock(&t->lock); 167 * @param task Task for which to allocate a new phone. 168 * 169 * @return New phone handle or -1 if the phone handle limit is 170 * exceeded. 171 * 172 */ 173 int phone_alloc(task_t *task) 174 { 175 irq_spinlock_lock(&task->lock, true); 176 177 size_t i; 175 178 for (i = 0; i < IPC_MAX_PHONES; i++) { 176 if ( t->phones[i].state == IPC_PHONE_HUNGUP&&177 atomic_get(&t->phones[i].active_calls) == 0)178 t ->phones[i].state = IPC_PHONE_FREE;179 180 if (t ->phones[i].state == IPC_PHONE_FREE) {181 t ->phones[i].state = IPC_PHONE_CONNECTING;179 if ((task->phones[i].state == IPC_PHONE_HUNGUP) && 180 (atomic_get(&task->phones[i].active_calls) == 0)) 181 task->phones[i].state = IPC_PHONE_FREE; 182 183 if (task->phones[i].state == IPC_PHONE_FREE) { 184 task->phones[i].state = IPC_PHONE_CONNECTING; 182 185 break; 183 186 } 184 187 } 185 spinlock_unlock(&t->lock); 186 188 189 irq_spinlock_unlock(&task->lock, true); 190 187 191 if (i == IPC_MAX_PHONES) 188 192 return -1; 189 193 190 194 return i; 191 195 } … … 193 197 /** Mark a phone structure free. 194 198 * 195 * @param phone Phone structure to be marked free. 199 * @param phone Phone structure to be marked free. 200 * 196 201 */ 197 202 static void phone_deallocp(phone_t *phone) … … 199 204 ASSERT(phone->state == IPC_PHONE_CONNECTING); 200 205 201 /* atomic operation */206 /* Atomic operation */ 202 207 phone->state = IPC_PHONE_FREE; 203 208 } … … 207 212 * All already sent messages will be correctly processed. 208 213 * 209 * @param phoneid Phone handle of the phone to be freed. 214 * @param phoneid Phone handle of the phone to be freed. 215 * 210 216 */ 211 217 void phone_dealloc(int phoneid) … … 216 222 /** Connect phone to a given answerbox. 217 223 * 218 * @param phoneid 219 * @param box 224 * @param phoneid Phone handle to be connected. 225 * @param box Answerbox to which to connect the phone handle. 220 226 * 221 227 * The procedure _enforces_ that the user first marks the phone 222 228 * busy (e.g. via phone_alloc) and then connects the phone, otherwise 223 229 * race condition may appear. 230 * 224 231 */ 225 232 void phone_connect(int phoneid, answerbox_t *box) -
kernel/generic/src/ipc/irq.c
r666f492 rda1bafb 31 31 * @{ 32 32 */ 33 33 34 /** 34 35 * @file … … 67 68 * structure are finished. Because we hold the hash table lock, we prevent new 68 69 * IRQs from taking new references to the IRQ structure. 70 * 69 71 */ 70 72 … … 81 83 /** Free the top-half pseudocode. 82 84 * 83 * @param code Pointer to the top-half pseudocode. 85 * @param code Pointer to the top-half pseudocode. 86 * 84 87 */ 85 88 static void code_free(irq_code_t *code) … … 93 96 /** Copy the top-half pseudocode from userspace into the kernel. 94 97 * 95 * @param ucode Userspace address of the top-half pseudocode. 96 * 97 * @return Kernel address of the copied pseudocode. 98 * @param ucode Userspace address of the top-half pseudocode. 99 * 100 * @return Kernel address of the copied pseudocode. 101 * 98 102 */ 99 103 static irq_code_t *code_from_uspace(irq_code_t *ucode) 100 104 { 101 irq_code_t *code; 102 irq_cmd_t *ucmds; 103 int rc; 104 105 code = malloc(sizeof(*code), 0); 106 rc = copy_from_uspace(code, ucode, sizeof(*code)); 105 irq_code_t *code = malloc(sizeof(*code), 0); 106 int rc = copy_from_uspace(code, ucode, sizeof(*code)); 107 107 if (rc != 0) { 108 108 free(code); … … 114 114 return NULL; 115 115 } 116 ucmds = code->cmds; 116 117 irq_cmd_t *ucmds = code->cmds; 117 118 code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 118 119 rc = copy_from_uspace(code->cmds, ucmds, … … 123 124 return NULL; 124 125 } 125 126 126 127 return code; 127 128 } … … 141 142 unative_t method, irq_code_t *ucode) 142 143 { 143 ipl_t ipl;144 irq_code_t *code;145 irq_t *irq;146 link_t *hlp;147 144 unative_t key[] = { 148 145 (unative_t) inr, … … 150 147 }; 151 148 149 irq_code_t *code; 152 150 if (ucode) { 153 151 code = code_from_uspace(ucode); 154 152 if (!code) 155 153 return EBADMEM; 156 } else {154 } else 157 155 code = NULL; 158 }159 156 160 157 /* 161 158 * Allocate and populate the IRQ structure. 162 159 */ 163 irq = malloc(sizeof(irq_t), 0); 160 irq_t *irq = malloc(sizeof(irq_t), 0); 161 164 162 irq_initialize(irq); 165 163 irq->devno = devno; … … 177 175 * answerbox's list. 178 176 */ 179 i pl = interrupts_disable();180 spinlock_lock(&irq_uspace_hash_table_lock);181 hlp = hash_table_find(&irq_uspace_hash_table, key);177 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 178 179 link_t *hlp = hash_table_find(&irq_uspace_hash_table, key); 182 180 if (hlp) { 183 irq_t *hirq __attribute__((unused)) 184 = hash_table_get_instance(hlp, irq_t, link); 181 irq_t *hirq = hash_table_get_instance(hlp, irq_t, link); 185 182 186 183 /* hirq is locked */ 187 spinlock_unlock(&hirq->lock);184 irq_spinlock_unlock(&hirq->lock, false); 188 185 code_free(code); 189 spinlock_unlock(&irq_uspace_hash_table_lock); 186 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 187 190 188 free(irq); 191 interrupts_restore(ipl);192 189 return EEXISTS; 193 190 } 194 191 195 spinlock_lock(&irq->lock); /* Not really necessary, but paranoid */ 196 spinlock_lock(&box->irq_lock); 192 /* Locking is not really necessary, but paranoid */ 193 irq_spinlock_lock(&irq->lock, false); 194 irq_spinlock_lock(&box->irq_lock, false); 195 197 196 hash_table_insert(&irq_uspace_hash_table, key, &irq->link); 198 197 list_append(&irq->notif_cfg.link, &box->irq_head); 199 spinlock_unlock(&box->irq_lock);200 spinlock_unlock(&irq->lock);201 spinlock_unlock(&irq_uspace_hash_table_lock);202 203 interrupts_restore(ipl);198 199 irq_spinlock_unlock(&box->irq_lock, false); 200 irq_spinlock_unlock(&irq->lock, false); 201 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 202 204 203 return EOK; 205 204 } … … 207 206 /** Unregister task from IRQ notification. 208 207 * 209 * @param box Answerbox associated with the notification. 210 * @param inr IRQ number. 211 * @param devno Device number. 208 * @param box Answerbox associated with the notification. 209 * @param inr IRQ number. 210 * @param devno Device number. 211 * 212 212 */ 213 213 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) 214 214 { 215 ipl_t ipl;216 215 unative_t key[] = { 217 216 (unative_t) inr, 218 217 (unative_t) devno 219 218 }; 220 link_t *lnk; 221 irq_t *irq; 222 223 ipl = interrupts_disable(); 224 spinlock_lock(&irq_uspace_hash_table_lock); 225 lnk = hash_table_find(&irq_uspace_hash_table, key); 219 220 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 221 link_t *lnk = hash_table_find(&irq_uspace_hash_table, key); 226 222 if (!lnk) { 227 spinlock_unlock(&irq_uspace_hash_table_lock); 228 interrupts_restore(ipl); 223 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 229 224 return ENOENT; 230 225 } 231 irq = hash_table_get_instance(lnk, irq_t, link); 226 227 irq_t *irq = hash_table_get_instance(lnk, irq_t, link); 228 232 229 /* irq is locked */ 233 spinlock_lock(&box->irq_lock);230 irq_spinlock_lock(&box->irq_lock, false); 234 231 235 232 ASSERT(irq->notif_cfg.answerbox == box); … … 237 234 /* Free up the pseudo code and associated structures. */ 238 235 code_free(irq->notif_cfg.code); 239 240 /* Remove the IRQ from the answerbox's list. */ 236 237 /* Remove the IRQ from the answerbox's list. */ 241 238 list_remove(&irq->notif_cfg.link); 242 239 243 240 /* 244 241 * We need to drop the IRQ lock now because hash_table_remove() will try … … 248 245 * the meantime. 249 246 */ 250 spinlock_unlock(&irq->lock);251 247 irq_spinlock_unlock(&irq->lock, false); 248 252 249 /* Remove the IRQ from the uspace IRQ hash table. */ 253 250 hash_table_remove(&irq_uspace_hash_table, key, 2); 254 251 255 spinlock_unlock(&irq_uspace_hash_table_lock);256 spinlock_unlock(&box->irq_lock);252 irq_spinlock_unlock(&box->irq_lock, false); 253 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 257 254 258 255 /* Free up the IRQ structure. */ 259 256 free(irq); 260 257 261 interrupts_restore(ipl);262 258 return EOK; 263 259 } 264 265 260 266 261 /** Disconnect all IRQ notifications from an answerbox. … … 270 265 * send notifications to it. 271 266 * 272 * @param box Answerbox for which we want to carry out the cleanup. 267 * @param box Answerbox for which we want to carry out the cleanup. 268 * 273 269 */ 274 270 void ipc_irq_cleanup(answerbox_t *box) 275 271 { 276 ipl_t ipl;277 278 272 loop: 279 ipl = interrupts_disable(); 280 spinlock_lock(&irq_uspace_hash_table_lock); 281 spinlock_lock(&box->irq_lock); 273 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 274 irq_spinlock_lock(&box->irq_lock, false); 282 275 283 276 while (box->irq_head.next != &box->irq_head) { 284 link_t *cur = box->irq_head.next;285 irq_t *irq;286 277 DEADLOCK_PROBE_INIT(p_irqlock); 287 unative_t key[2]; 288 289 irq = list_get_instance(cur, irq_t, notif_cfg.link); 290 if (!spinlock_trylock(&irq->lock)) { 278 279 irq_t *irq = list_get_instance(box->irq_head.next, irq_t, 280 notif_cfg.link); 281 282 if (!irq_spinlock_trylock(&irq->lock)) { 291 283 /* 292 284 * Avoid deadlock by trying again. 293 285 */ 294 spinlock_unlock(&box->irq_lock); 295 spinlock_unlock(&irq_uspace_hash_table_lock); 296 interrupts_restore(ipl); 286 irq_spinlock_unlock(&box->irq_lock, false); 287 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 297 288 DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD); 298 289 goto loop; 299 290 } 291 292 unative_t key[2]; 300 293 key[0] = irq->inr; 301 294 key[1] = irq->devno; 302 303 295 304 296 ASSERT(irq->notif_cfg.answerbox == box); … … 317 309 * didn't drop the hash table lock in the meantime. 318 310 */ 319 spinlock_unlock(&irq->lock);311 irq_spinlock_unlock(&irq->lock, false); 320 312 321 313 /* Remove from the hash table. */ … … 325 317 } 326 318 327 spinlock_unlock(&box->irq_lock); 328 spinlock_unlock(&irq_uspace_hash_table_lock); 329 interrupts_restore(ipl); 319 irq_spinlock_unlock(&box->irq_lock, false); 320 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 330 321 } 331 322 332 323 /** Add a call to the proper answerbox queue. 333 324 * 334 * Assume irq->lock is locked. 335 * 336 * @param irq IRQ structure referencing the target answerbox. 337 * @param call IRQ notification call. 325 * Assume irq->lock is locked and interrupts disabled. 326 * 327 * @param irq IRQ structure referencing the target answerbox. 328 * @param call IRQ notification call. 329 * 338 330 */ 339 331 static void send_call(irq_t *irq, call_t *call) 340 332 { 341 spinlock_lock(&irq->notif_cfg.answerbox->irq_lock);333 irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false); 342 334 list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs); 343 spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock);344 335 irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false); 336 345 337 waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST); 346 338 } … … 348 340 /** Apply the top-half pseudo code to find out whether to accept the IRQ or not. 349 341 * 350 * @param irq IRQ structure. 351 * 352 * @return IRQ_ACCEPT if the interrupt is accepted by the 353 * pseudocode. IRQ_DECLINE otherwise. 342 * @param irq IRQ structure. 343 * 344 * @return IRQ_ACCEPT if the interrupt is accepted by the 345 * pseudocode, IRQ_DECLINE otherwise. 346 * 354 347 */ 355 348 irq_ownership_t ipc_irq_top_half_claim(irq_t *irq) 356 349 { 357 unsigned int i;358 unative_t dstval;359 350 irq_code_t *code = irq->notif_cfg.code; 360 unative_t *scratch = irq->notif_cfg.scratch; 361 351 uint32_t *scratch = irq->notif_cfg.scratch; 362 352 363 353 if (!irq->notif_cfg.notify) … … 367 357 return IRQ_DECLINE; 368 358 359 size_t i; 369 360 for (i = 0; i < code->cmdcount; i++) { 370 unsigned int srcarg = code->cmds[i].srcarg; 371 unsigned int dstarg = code->cmds[i].dstarg; 361 uint32_t dstval; 362 uintptr_t srcarg = code->cmds[i].srcarg; 363 uintptr_t dstarg = code->cmds[i].dstarg; 372 364 373 365 if (srcarg >= IPC_CALL_LEN) 374 366 break; 367 375 368 if (dstarg >= IPC_CALL_LEN) 376 369 break; … … 405 398 break; 406 399 case CMD_BTEST: 407 if ( srcarg && dstarg) {400 if ((srcarg) && (dstarg)) { 408 401 dstval = scratch[srcarg] & code->cmds[i].value; 409 402 scratch[dstarg] = dstval; … … 411 404 break; 412 405 case CMD_PREDICATE: 413 if ( srcarg && !scratch[srcarg]) {406 if ((srcarg) && (!scratch[srcarg])) { 414 407 i += code->cmds[i].value; 415 408 continue; … … 427 420 } 428 421 429 430 422 /* IRQ top-half handler. 431 423 * 432 424 * We expect interrupts to be disabled and the irq->lock already held. 433 425 * 434 * @param irq IRQ structure. 426 * @param irq IRQ structure. 427 * 435 428 */ 436 429 void ipc_irq_top_half_handler(irq_t *irq) 437 430 { 438 431 ASSERT(irq); 439 432 440 433 if (irq->notif_cfg.answerbox) { 441 call_t *call; 442 443 call = ipc_call_alloc(FRAME_ATOMIC); 434 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 444 435 if (!call) 445 436 return; … … 448 439 /* Put a counter to the message */ 449 440 call->priv = ++irq->notif_cfg.counter; 450 441 451 442 /* Set up args */ 452 443 IPC_SET_METHOD(call->data, irq->notif_cfg.method); … … 456 447 IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]); 457 448 IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]); 458 449 459 450 send_call(irq, call); 460 451 } … … 463 454 /** Send notification message. 464 455 * 465 * @param irq IRQ structure. 466 * @param a1 Driver-specific payload argument. 467 * @param a2 Driver-specific payload argument. 468 * @param a3 Driver-specific payload argument. 469 * @param a4 Driver-specific payload argument. 470 * @param a5 Driver-specific payload argument. 456 * @param irq IRQ structure. 457 * @param a1 Driver-specific payload argument. 458 * @param a2 Driver-specific payload argument. 459 * @param a3 Driver-specific payload argument. 460 * @param a4 Driver-specific payload argument. 461 * @param a5 Driver-specific payload argument. 462 * 471 463 */ 472 464 void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3, 473 465 unative_t a4, unative_t a5) 474 466 { 475 call_t *call; 476 477 spinlock_lock(&irq->lock); 478 467 irq_spinlock_lock(&irq->lock, true); 468 479 469 if (irq->notif_cfg.answerbox) { 480 call = ipc_call_alloc(FRAME_ATOMIC);470 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 481 471 if (!call) { 482 spinlock_unlock(&irq->lock);472 irq_spinlock_unlock(&irq->lock, true); 483 473 return; 484 474 } 475 485 476 call->flags |= IPC_CALL_NOTIF; 486 477 /* Put a counter to the message */ 487 478 call->priv = ++irq->notif_cfg.counter; 488 479 489 480 IPC_SET_METHOD(call->data, irq->notif_cfg.method); 490 481 IPC_SET_ARG1(call->data, a1); … … 496 487 send_call(irq, call); 497 488 } 498 spinlock_unlock(&irq->lock); 489 490 irq_spinlock_unlock(&irq->lock, true); 499 491 } 500 492 -
kernel/generic/src/ipc/kbox.c
r666f492 rda1bafb 47 47 void ipc_kbox_cleanup(void) 48 48 { 49 bool have_kb_thread; 50 51 /* 49 /* 52 50 * Only hold kb.cleanup_lock while setting kb.finished - 53 51 * this is enough. … … 56 54 TASK->kb.finished = true; 57 55 mutex_unlock(&TASK->kb.cleanup_lock); 58 59 have_kb_thread = (TASK->kb.thread != NULL);60 56 57 bool have_kb_thread = (TASK->kb.thread != NULL); 58 61 59 /* 62 60 * From now on nobody will try to connect phones or attach 63 61 * kbox threads 64 62 */ 65 63 66 64 /* 67 65 * Disconnect all phones connected to our kbox. Passing true for … … 71 69 */ 72 70 ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread); 73 74 /* 71 72 /* 75 73 * If the task was being debugged, clean up debugging session. 76 74 * This is necessarry as slamming the phones won't force … … 80 78 udebug_task_cleanup(TASK); 81 79 mutex_unlock(&TASK->udebug.lock); 82 80 83 81 if (have_kb_thread) { 84 82 LOG("Join kb.thread."); … … 88 86 TASK->kb.thread = NULL; 89 87 } 90 88 91 89 /* Answer all messages in 'calls' and 'dispatched_calls' queues. */ 92 spinlock_lock(&TASK->kb.box.lock);90 irq_spinlock_lock(&TASK->kb.box.lock, true); 93 91 ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls); 94 92 ipc_cleanup_call_list(&TASK->kb.box.calls); 95 spinlock_unlock(&TASK->kb.box.lock);93 irq_spinlock_unlock(&TASK->kb.box.lock, true); 96 94 } 97 95 98 96 /** Handle hangup message in kbox. 99 97 * 100 * @param call The IPC_M_PHONE_HUNGUP call structure. 101 * @param last Output, the function stores @c true here if 102 * this was the last phone, @c false otherwise. 103 **/ 98 * @param call The IPC_M_PHONE_HUNGUP call structure. 99 * @param last Output, the function stores @c true here if 100 * this was the last phone, @c false otherwise. 101 * 102 */ 104 103 static void kbox_proc_phone_hungup(call_t *call, bool *last) 105 104 { 106 ipl_t ipl;107 108 105 /* Was it our debugger, who hung up? */ 109 106 if (call->sender == TASK->udebug.debugger) { 110 107 /* Terminate debugging session (if any). */ 111 108 LOG("Terminate debugging session."); 112 ipl = interrupts_disable(); 113 spinlock_lock(&TASK->lock); 109 irq_spinlock_lock(&TASK->lock, true); 114 110 udebug_task_cleanup(TASK); 115 spinlock_unlock(&TASK->lock); 116 interrupts_restore(ipl); 111 irq_spinlock_unlock(&TASK->lock, true); 117 112 } else { 118 113 LOG("Was not debugger."); 119 114 } 120 115 121 116 LOG("Continue with hangup message."); 122 117 IPC_SET_RETVAL(call->data, 0); 123 118 ipc_answer(&TASK->kb.box, call); 124 119 125 120 mutex_lock(&TASK->kb.cleanup_lock); 126 127 ipl = interrupts_disable(); 128 spinlock_lock(&TASK->lock); 129 spinlock_lock(&TASK->kb.box.lock); 121 122 irq_spinlock_lock(&TASK->lock, true); 123 irq_spinlock_lock(&TASK->kb.box.lock, false); 130 124 if (list_empty(&TASK->kb.box.connected_phones)) { 131 125 /* … … 133 127 * gets freed and signal to the caller. 134 128 */ 135 129 136 130 /* Only detach kbox thread unless already terminating. */ 137 131 if (TASK->kb.finished == false) { … … 140 134 TASK->kb.thread = NULL; 141 135 } 142 136 143 137 LOG("Phone list is empty."); 144 138 *last = true; 145 } else {139 } else 146 140 *last = false; 147 } 148 149 spinlock_unlock(&TASK->kb.box.lock); 150 spinlock_unlock(&TASK->lock); 151 interrupts_restore(ipl); 152 141 142 irq_spinlock_unlock(&TASK->kb.box.lock, true); 143 irq_spinlock_unlock(&TASK->lock, false); 144 153 145 mutex_unlock(&TASK->kb.cleanup_lock); 154 146 } … … 159 151 * when all phones are disconnected from the kbox. 160 152 * 161 * @param arg Ignored. 153 * @param arg Ignored. 154 * 162 155 */ 163 156 static void kbox_thread_proc(void *arg) 164 157 { 165 call_t *call; 166 bool done; 167 168 (void)arg; 158 (void) arg; 169 159 LOG("Starting."); 170 done = false;171 160 bool done = false; 161 172 162 while (!done) { 173 call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,163 call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT, 174 164 SYNCH_FLAGS_NONE); 175 165 176 166 if (call == NULL) 177 continue; 178 167 continue; /* Try again. */ 168 179 169 switch (IPC_GET_METHOD(call->data)) { 180 170 181 171 case IPC_M_DEBUG_ALL: 182 172 /* Handle debug call. */ 183 173 udebug_call_receive(call); 184 174 break; 185 175 186 176 case IPC_M_PHONE_HUNGUP: 187 177 /* … … 192 182 kbox_proc_phone_hungup(call, &done); 193 183 break; 194 184 195 185 default: 196 186 /* Ignore */ … … 198 188 } 199 189 } 200 190 201 191 LOG("Exiting."); 202 192 } 203 193 204 194 205 /** 206 * Connect phone to a task kernel-box specified by id. 195 /** Connect phone to a task kernel-box specified by id. 207 196 * 208 197 * Note that this is not completely atomic. For optimisation reasons, the task … … 211 200 * cleanup code. 212 201 * 213 * @return Phone id on success, or negative error code. 202 * @return Phone id on success, or negative error code. 203 * 214 204 */ 215 205 int ipc_connect_kbox(task_id_t taskid) 216 206 { 217 int newphid; 218 task_t *ta; 219 thread_t *kb_thread; 220 ipl_t ipl; 221 222 ipl = interrupts_disable(); 223 spinlock_lock(&tasks_lock); 224 225 ta = task_find_by_id(taskid); 226 if (ta == NULL) { 227 spinlock_unlock(&tasks_lock); 228 interrupts_restore(ipl); 207 irq_spinlock_lock(&tasks_lock, true); 208 209 task_t *task = task_find_by_id(taskid); 210 if (task == NULL) { 211 irq_spinlock_unlock(&tasks_lock, true); 229 212 return ENOENT; 230 213 } 231 232 atomic_inc(&ta->refcount); 233 234 spinlock_unlock(&tasks_lock); 235 interrupts_restore(ipl); 236 237 mutex_lock(&ta->kb.cleanup_lock); 238 239 if (atomic_predec(&ta->refcount) == 0) { 240 mutex_unlock(&ta->kb.cleanup_lock); 241 task_destroy(ta); 214 215 atomic_inc(&task->refcount); 216 217 irq_spinlock_unlock(&tasks_lock, true); 218 219 mutex_lock(&task->kb.cleanup_lock); 220 221 if (atomic_predec(&task->refcount) == 0) { 222 mutex_unlock(&task->kb.cleanup_lock); 223 task_destroy(task); 242 224 return ENOENT; 243 225 } 244 245 if (ta ->kb.finished != false) {246 mutex_unlock(&ta ->kb.cleanup_lock);226 227 if (task->kb.finished != false) { 228 mutex_unlock(&task->kb.cleanup_lock); 247 229 return EINVAL; 248 230 } 249 250 newphid = phone_alloc(TASK);231 232 int newphid = phone_alloc(TASK); 251 233 if (newphid < 0) { 252 mutex_unlock(&ta ->kb.cleanup_lock);234 mutex_unlock(&task->kb.cleanup_lock); 253 235 return ELIMIT; 254 236 } 255 237 256 238 /* Connect the newly allocated phone to the kbox */ 257 ipc_phone_connect(&TASK->phones[newphid], &ta ->kb.box);258 259 if (ta ->kb.thread != NULL) {260 mutex_unlock(&ta ->kb.cleanup_lock);239 ipc_phone_connect(&TASK->phones[newphid], &task->kb.box); 240 241 if (task->kb.thread != NULL) { 242 mutex_unlock(&task->kb.cleanup_lock); 261 243 return newphid; 262 244 } 263 245 264 246 /* Create a kbox thread */ 265 kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0,247 thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0, 266 248 "kbox", false); 267 249 if (!kb_thread) { 268 mutex_unlock(&ta ->kb.cleanup_lock);250 mutex_unlock(&task->kb.cleanup_lock); 269 251 return ENOMEM; 270 252 } 271 272 ta ->kb.thread = kb_thread;253 254 task->kb.thread = kb_thread; 273 255 thread_ready(kb_thread); 274 275 mutex_unlock(&ta ->kb.cleanup_lock);276 256 257 mutex_unlock(&task->kb.cleanup_lock); 258 277 259 return newphid; 278 260 } -
kernel/generic/src/ipc/sysipc.c
r666f492 rda1bafb 56 56 * requests. 57 57 */ 58 #define DATA_XFER_LIMIT (64 * 1024) 58 #define DATA_XFER_LIMIT (64 * 1024) 59 60 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src))) 59 61 60 62 /** Get phone from the current task by ID. 61 63 * 62 * @param phoneid Phone ID. 63 * @param phone Place to store pointer to phone. 64 * @return EOK on success, EINVAL if ID is invalid. 64 * @param phoneid Phone ID. 65 * @param phone Place to store pointer to phone. 66 * 67 * @return EOK on success, EINVAL if ID is invalid. 68 * 65 69 */ 66 70 static int phone_get(unative_t phoneid, phone_t **phone) … … 68 72 if (phoneid >= IPC_MAX_PHONES) 69 73 return EINVAL; 70 74 71 75 *phone = &TASK->phones[phoneid]; 72 76 return EOK; 73 77 } 74 78 75 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src)))76 77 79 /** Decide if the method is a system method. 78 80 * 79 * @param method 80 * 81 * @return Return 1if the method is a system method.82 * Otherwise return 0.83 */ 84 static inline intmethod_is_system(unative_t method)81 * @param method Method to be decided. 82 * 83 * @return true if the method is a system method. 84 * 85 */ 86 static inline bool method_is_system(unative_t method) 85 87 { 86 88 if (method <= IPC_M_LAST_SYSTEM) 87 return 1; 88 return 0; 89 return true; 90 91 return false; 89 92 } 90 93 … … 94 97 * it is useless 95 98 * 96 * @param method 97 * 98 * @return Return 1if the method is forwardable.99 * Otherwise return 0.100 */ 101 static inline intmethod_is_forwardable(unative_t method)99 * @param method Method to be decided. 100 * 101 * @return true if the method is forwardable. 102 * 103 */ 104 static inline bool method_is_forwardable(unative_t method) 102 105 { 103 106 switch (method) { … … 106 109 case IPC_M_PHONE_HUNGUP: 107 110 /* This message is meant only for the original recipient. */ 108 return 0;111 return false; 109 112 default: 110 return 1;113 return true; 111 114 } 112 115 } … … 116 119 * - some system messages may be forwarded but their content cannot be altered 117 120 * 118 * @param method 119 * 120 * @return Return 1if the method is immutable on forward.121 * Otherwise return 0.122 */ 123 static inline intmethod_is_immutable(unative_t method)121 * @param method Method to be decided. 122 * 123 * @return true if the method is immutable on forward. 124 * 125 */ 126 static inline bool method_is_immutable(unative_t method) 124 127 { 125 128 switch (method) { … … 128 131 case IPC_M_DATA_WRITE: 129 132 case IPC_M_DATA_READ: 130 return 1;133 return true; 131 134 default: 132 return 0;135 return false; 133 136 } 134 137 } … … 142 145 * for answer_preprocess(). 143 146 * 144 * @param call 145 * 146 * @return Return 1if the old call contents should be saved.147 * Return 0 otherwise.148 */ 149 static inline intanswer_need_old(call_t *call)147 * @param call Call structure to be decided. 148 * 149 * @return true if the old call contents should be saved. 150 * 151 */ 152 static inline bool answer_need_old(call_t *call) 150 153 { 151 154 switch (IPC_GET_METHOD(call->data)) { … … 158 161 case IPC_M_DATA_WRITE: 159 162 case IPC_M_DATA_READ: 160 return 1;163 return true; 161 164 default: 162 return 0;165 return false; 163 166 } 164 167 } … … 168 171 * This function is called directly after sys_ipc_answer(). 169 172 * 170 * @param answer Call structure with the answer. 171 * @param olddata Saved data of the request. 172 * 173 * @return Return 0 on success or an error code. 173 * @param answer Call structure with the answer. 174 * @param olddata Saved data of the request. 175 * 176 * @return Return 0 on success or an error code. 177 * 174 178 */ 175 179 static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) 176 180 { 177 int phoneid;178 179 181 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 180 182 /* In case of forward, hangup the forwared phone, … … 182 184 */ 183 185 mutex_lock(&answer->data.phone->lock); 184 spinlock_lock(&TASK->answerbox.lock);186 irq_spinlock_lock(&TASK->answerbox.lock, true); 185 187 if (answer->data.phone->state == IPC_PHONE_CONNECTED) { 186 188 list_remove(&answer->data.phone->link); 187 189 answer->data.phone->state = IPC_PHONE_SLAMMED; 188 190 } 189 spinlock_unlock(&TASK->answerbox.lock);191 irq_spinlock_unlock(&TASK->answerbox.lock, true); 190 192 mutex_unlock(&answer->data.phone->lock); 191 193 } 192 194 193 195 if (!olddata) 194 196 return 0; 195 197 196 198 if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) { 197 phoneid = IPC_GET_ARG1(*olddata); 198 phone_t *phone = &TASK->phones[phoneid]; 199 int phoneid = IPC_GET_ARG1(*olddata); 200 phone_t *phone = &TASK->phones[phoneid]; 201 199 202 if (IPC_GET_RETVAL(answer->data) != EOK) { 200 203 /* … … 208 211 mutex_lock(&phone->lock); 209 212 if (phone->state == IPC_PHONE_CONNECTED) { 210 spinlock_lock(&phone->callee->lock);213 irq_spinlock_lock(&phone->callee->lock, true); 211 214 list_remove(&phone->link); 212 215 phone->state = IPC_PHONE_SLAMMED; 213 spinlock_unlock(&phone->callee->lock);216 irq_spinlock_unlock(&phone->callee->lock, true); 214 217 } 215 218 mutex_unlock(&phone->lock); 216 219 } 217 220 } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) { 218 phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata); 221 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 222 219 223 if (IPC_GET_RETVAL(answer->data) != EOK) { 220 224 /* … … 226 230 mutex_lock(&phone->lock); 227 231 if (phone->state == IPC_PHONE_CONNECTED) { 228 spinlock_lock(&phone->callee->lock);232 irq_spinlock_lock(&phone->callee->lock, true); 229 233 list_remove(&phone->link); 230 234 phone->state = IPC_PHONE_SLAMMED; 231 spinlock_unlock(&phone->callee->lock);235 irq_spinlock_unlock(&phone->callee->lock, true); 232 236 } 233 237 mutex_unlock(&phone->lock); 234 238 } 235 239 } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { 236 phoneid = IPC_GET_ARG5(*olddata); 240 int phoneid = IPC_GET_ARG5(*olddata); 241 237 242 if (IPC_GET_RETVAL(answer->data) != EOK) { 238 243 /* The connection was not accepted */ … … 254 259 if (!IPC_GET_RETVAL(answer->data)) { 255 260 /* Accepted, handle as_area receipt */ 256 ipl_t ipl;257 int rc;258 as_t *as;259 261 260 ipl = interrupts_disable(); 261 spinlock_lock(&answer->sender->lock); 262 as = answer->sender->as; 263 spinlock_unlock(&answer->sender->lock); 264 interrupts_restore(ipl); 262 irq_spinlock_lock(&answer->sender->lock, true); 263 as_t *as = answer->sender->as; 264 irq_spinlock_unlock(&answer->sender->lock, true); 265 265 266 rc = as_area_share(as, IPC_GET_ARG1(*olddata),266 int rc = as_area_share(as, IPC_GET_ARG1(*olddata), 267 267 IPC_GET_ARG2(*olddata), AS, 268 268 IPC_GET_ARG1(answer->data), IPC_GET_ARG3(*olddata)); … … 272 272 } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_IN) { 273 273 if (!IPC_GET_RETVAL(answer->data)) { 274 i pl_t ipl;275 as_t *as ;276 i nt rc;274 irq_spinlock_lock(&answer->sender->lock, true); 275 as_t *as = answer->sender->as; 276 irq_spinlock_unlock(&answer->sender->lock, true); 277 277 278 ipl = interrupts_disable(); 279 spinlock_lock(&answer->sender->lock); 280 as = answer->sender->as; 281 spinlock_unlock(&answer->sender->lock); 282 interrupts_restore(ipl); 283 284 rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 278 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 285 279 IPC_GET_ARG2(*olddata), as, IPC_GET_ARG1(*olddata), 286 280 IPC_GET_ARG2(answer->data)); … … 301 295 */ 302 296 IPC_SET_ARG1(answer->data, dst); 303 297 304 298 answer->buffer = malloc(size, 0); 305 299 int rc = copy_from_uspace(answer->buffer, … … 320 314 if (!IPC_GET_RETVAL(answer->data)) { 321 315 /* The recipient agreed to receive data. */ 322 int rc; 323 uintptr_t dst; 324 size_t size; 325 size_t max_size; 326 327 dst = (uintptr_t)IPC_GET_ARG1(answer->data); 328 size = (size_t)IPC_GET_ARG2(answer->data); 329 max_size = (size_t)IPC_GET_ARG2(*olddata); 330 316 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 317 size_t size = (size_t)IPC_GET_ARG2(answer->data); 318 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 319 331 320 if (size <= max_size) { 332 rc = copy_to_uspace((void *) dst,321 int rc = copy_to_uspace((void *) dst, 333 322 answer->buffer, size); 334 323 if (rc) … … 341 330 answer->buffer = NULL; 342 331 } 332 343 333 return 0; 344 334 } … … 352 342 mutex_lock(&p2->lock); 353 343 mutex_lock(&p1->lock); 354 } else {344 } else 355 345 mutex_lock(&p1->lock); 356 }357 346 } 358 347 … … 366 355 /** Called before the request is sent. 367 356 * 368 * @param call Call structure with the request. 369 * @param phone Phone that the call will be sent through. 370 * 371 * @return Return 0 on success, ELIMIT or EPERM on error. 357 * @param call Call structure with the request. 358 * @param phone Phone that the call will be sent through. 359 * 360 * @return Return 0 on success, ELIMIT or EPERM on error. 361 * 372 362 */ 373 363 static int request_preprocess(call_t *call, phone_t *phone) 374 364 { 375 int newphid;376 size_t size;377 uintptr_t src;378 int rc;379 380 365 switch (IPC_GET_METHOD(call->data)) { 381 366 case IPC_M_CONNECTION_CLONE: { 382 367 phone_t *cloned_phone; 383 384 368 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 385 369 return ENOENT; 370 386 371 phones_lock(cloned_phone, phone); 387 372 388 373 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 389 374 phone->state != IPC_PHONE_CONNECTED) { … … 391 376 return EINVAL; 392 377 } 378 393 379 /* 394 380 * We can be pretty sure now that both tasks exist and we are … … 396 382 * we are effectively preventing them from finishing their 397 383 * potential cleanup. 384 * 398 385 */ 399 newphid = phone_alloc(phone->callee->task);386 int newphid = phone_alloc(phone->callee->task); 400 387 if (newphid < 0) { 401 388 phones_unlock(cloned_phone, phone); 402 389 return ELIMIT; 403 390 } 391 404 392 ipc_phone_connect(&phone->callee->task->phones[newphid], 405 393 cloned_phone->callee); 406 394 phones_unlock(cloned_phone, phone); 395 407 396 /* Set the new phone for the callee. */ 408 397 IPC_SET_ARG1(call->data, newphid); … … 412 401 IPC_SET_ARG5(call->data, (unative_t) phone); 413 402 break; 414 case IPC_M_CONNECT_ME_TO: 415 newphid = phone_alloc(TASK);403 case IPC_M_CONNECT_ME_TO: { 404 int newphid = phone_alloc(TASK); 416 405 if (newphid < 0) 417 406 return ELIMIT; 407 418 408 /* Set arg5 for server */ 419 409 IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]); … … 421 411 call->priv = newphid; 422 412 break; 423 case IPC_M_SHARE_OUT: 424 size = as_area_get_size(IPC_GET_ARG1(call->data)); 413 } 414 case IPC_M_SHARE_OUT: { 415 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 425 416 if (!size) 426 417 return EPERM; 418 427 419 IPC_SET_ARG2(call->data, size); 428 420 break; 429 case IPC_M_DATA_READ: 430 size = IPC_GET_ARG2(call->data); 421 } 422 case IPC_M_DATA_READ: { 423 size_t size = IPC_GET_ARG2(call->data); 431 424 if ((size <= 0 || (size > DATA_XFER_LIMIT))) 432 425 return ELIMIT; 426 433 427 break; 434 case IPC_M_DATA_WRITE: 435 src = IPC_GET_ARG1(call->data); 436 size = IPC_GET_ARG2(call->data); 428 } 429 case IPC_M_DATA_WRITE: { 430 uintptr_t src = IPC_GET_ARG1(call->data); 431 size_t size = IPC_GET_ARG2(call->data); 437 432 438 433 if (size > DATA_XFER_LIMIT) … … 440 435 441 436 call->buffer = (uint8_t *) malloc(size, 0); 442 rc = copy_from_uspace(call->buffer, (void *) src, size);437 int rc = copy_from_uspace(call->buffer, (void *) src, size); 443 438 if (rc != 0) { 444 439 free(call->buffer); 445 440 return rc; 446 441 } 442 447 443 break; 444 } 448 445 #ifdef CONFIG_UDEBUG 449 446 case IPC_M_DEBUG_ALL: … … 453 450 break; 454 451 } 452 455 453 return 0; 456 454 } … … 462 460 /** Do basic kernel processing of received call answer. 463 461 * 464 * @param call Call structure with the answer. 462 * @param call Call structure with the answer. 463 * 465 464 */ 466 465 static void process_answer(call_t *call) … … 469 468 (call->flags & IPC_CALL_FORWARDED)) 470 469 IPC_SET_RETVAL(call->data, EFORWARD); 471 470 472 471 if (call->flags & IPC_CALL_CONN_ME_TO) { 473 472 if (IPC_GET_RETVAL(call->data)) … … 476 475 IPC_SET_ARG5(call->data, call->priv); 477 476 } 478 477 479 478 if (call->buffer) { 480 /* This must be an affirmative answer to IPC_M_DATA_READ. */ 481 /* or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... */ 479 /* 480 * This must be an affirmative answer to IPC_M_DATA_READ 481 * or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ... 482 * 483 */ 482 484 uintptr_t dst = IPC_GET_ARG1(call->data); 483 485 size_t size = IPC_GET_ARG2(call->data); … … 492 494 /** Do basic kernel processing of received call request. 493 495 * 494 * @param box Destination answerbox structure. 495 * @param call Call structure with the request. 496 * 497 * @return Return 0 if the call should be passed to userspace. 498 * Return -1 if the call should be ignored. 496 * @param box Destination answerbox structure. 497 * @param call Call structure with the request. 498 * 499 * @return 0 if the call should be passed to userspace. 500 * @return -1 if the call should be ignored. 501 * 499 502 */ 500 503 static int process_request(answerbox_t *box, call_t *call) 501 504 { 502 int phoneid;503 504 505 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) { 505 phoneid = phone_alloc(TASK);506 int phoneid = phone_alloc(TASK); 506 507 if (phoneid < 0) { /* Failed to allocate phone */ 507 508 IPC_SET_RETVAL(call->data, ELIMIT); … … 509 510 return -1; 510 511 } 512 511 513 IPC_SET_ARG5(call->data, phoneid); 512 514 } 515 513 516 switch (IPC_GET_METHOD(call->data)) { 514 517 case IPC_M_DEBUG_ALL: … … 517 520 break; 518 521 } 522 519 523 return 0; 520 524 } … … 525 529 * the generic function (i.e. sys_ipc_call_sync_slow()). 526 530 * 527 * @param phoneid Phone handle for the call. 528 * @param method Method of the call. 529 * @param arg1 Service-defined payload argument. 530 * @param arg2 Service-defined payload argument. 531 * @param arg3 Service-defined payload argument. 532 * @param data Address of userspace structure where the reply call will 533 * be stored. 534 * 535 * @return Returns 0 on success. 536 * Return ENOENT if there is no such phone handle. 531 * @param phoneid Phone handle for the call. 532 * @param method Method of the call. 533 * @param arg1 Service-defined payload argument. 534 * @param arg2 Service-defined payload argument. 535 * @param arg3 Service-defined payload argument. 536 * @param data Address of userspace structure where the reply call will 537 * be stored. 538 * 539 * @return 0 on success. 540 * @return ENOENT if there is no such phone handle. 541 * 537 542 */ 538 543 unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method, 539 544 unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data) 540 545 { 541 call_t *call;542 546 phone_t *phone; 543 int res;544 int rc;545 546 547 if (phone_get(phoneid, &phone) != EOK) 547 548 return ENOENT; 548 549 549 call = ipc_call_alloc(0);550 call_t *call = ipc_call_alloc(0); 550 551 IPC_SET_METHOD(call->data, method); 551 552 IPC_SET_ARG1(call->data, arg1); 552 553 IPC_SET_ARG2(call->data, arg2); 553 554 IPC_SET_ARG3(call->data, arg3); 555 554 556 /* 555 557 * To achieve deterministic behavior, zero out arguments that are beyond … … 558 560 IPC_SET_ARG4(call->data, 0); 559 561 IPC_SET_ARG5(call->data, 0); 560 561 if (!(res = request_preprocess(call, phone))) { 562 563 int res = request_preprocess(call, phone); 564 int rc; 565 566 if (!res) { 562 567 #ifdef CONFIG_UDEBUG 563 568 udebug_stoppable_begin(); … … 567 572 udebug_stoppable_end(); 568 573 #endif 574 569 575 if (rc != EOK) { 570 576 /* The call will be freed by ipc_cleanup(). */ 571 577 return rc; 572 578 } 579 573 580 process_answer(call); 574 575 } else {581 582 } else 576 583 IPC_SET_RETVAL(call->data, res); 577 }584 578 585 rc = STRUCT_TO_USPACE(&data->args, &call->data.args); 579 586 ipc_call_free(call); 580 587 if (rc != 0) 581 588 return rc; 582 589 583 590 return 0; 584 591 } … … 586 593 /** Make a synchronous IPC call allowing to transmit the entire payload. 587 594 * 588 * @param phoneid Phone handle for the call. 589 * @param question Userspace address of call data with the request. 590 * @param reply Userspace address of call data where to store the 591 * answer. 592 * 593 * @return Zero on success or an error code. 595 * @param phoneid Phone handle for the call. 596 * @param question Userspace address of call data with the request. 597 * @param reply Userspace address of call data where to store the 598 * answer. 599 * 600 * @return Zero on success or an error code. 601 * 594 602 */ 595 603 unative_t sys_ipc_call_sync_slow(unative_t phoneid, ipc_data_t *question, 596 604 ipc_data_t *reply) 597 605 { 598 call_t *call;599 606 phone_t *phone; 600 int res;601 int rc;602 603 607 if (phone_get(phoneid, &phone) != EOK) 604 608 return ENOENT; 605 609 606 call = ipc_call_alloc(0);607 rc = copy_from_uspace(&call->data.args, &question->args,610 call_t *call = ipc_call_alloc(0); 611 int rc = copy_from_uspace(&call->data.args, &question->args, 608 612 sizeof(call->data.args)); 609 613 if (rc != 0) { … … 611 615 return (unative_t) rc; 612 616 } 613 614 615 if (!(res = request_preprocess(call, phone))) { 617 618 int res = request_preprocess(call, phone); 619 620 if (!res) { 616 621 #ifdef CONFIG_UDEBUG 617 622 udebug_stoppable_begin(); … … 621 626 udebug_stoppable_end(); 622 627 #endif 628 623 629 if (rc != EOK) { 624 630 /* The call will be freed by ipc_cleanup(). */ 625 631 return rc; 626 632 } 633 627 634 process_answer(call); 628 } else 635 } else 629 636 IPC_SET_RETVAL(call->data, res); 630 637 631 638 rc = STRUCT_TO_USPACE(&reply->args, &call->data.args); 632 639 ipc_call_free(call); 633 640 if (rc != 0) 634 641 return rc; 635 642 636 643 return 0; 637 644 } … … 639 646 /** Check that the task did not exceed the allowed limit of asynchronous calls. 640 647 * 641 * @return Return 0 if limit not reached or -1 if limit exceeded. 648 * @return 0 if limit not reached or -1 if limit exceeded. 649 * 642 650 */ 643 651 static int check_call_limit(void) … … 647 655 return -1; 648 656 } 657 649 658 return 0; 650 659 } … … 655 664 * the generic function sys_ipc_call_async_slow(). 656 665 * 657 * @param phoneid Phone handle for the call. 658 * @param method Method of the call. 659 * @param arg1 Service-defined payload argument. 660 * @param arg2 Service-defined payload argument. 661 * @param arg3 Service-defined payload argument. 662 * @param arg4 Service-defined payload argument. 663 * 664 * @return Return call hash on success. 665 * Return IPC_CALLRET_FATAL in case of a fatal error and 666 * IPC_CALLRET_TEMPORARY if there are too many pending 667 * asynchronous requests; answers should be handled first. 666 * @param phoneid Phone handle for the call. 667 * @param method Method of the call. 668 * @param arg1 Service-defined payload argument. 669 * @param arg2 Service-defined payload argument. 670 * @param arg3 Service-defined payload argument. 671 * @param arg4 Service-defined payload argument. 672 * 673 * @return Call hash on success. 674 * @return IPC_CALLRET_FATAL in case of a fatal error. 675 * @return IPC_CALLRET_TEMPORARY if there are too many pending 676 * asynchronous requests; answers should be handled first. 677 * 668 678 */ 669 679 unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method, 670 680 unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4) 671 681 { 672 call_t *call;673 phone_t *phone;674 int res;675 676 682 if (check_call_limit()) 677 683 return IPC_CALLRET_TEMPORARY; 678 684 685 phone_t *phone; 679 686 if (phone_get(phoneid, &phone) != EOK) 680 687 return IPC_CALLRET_FATAL; 681 682 call = ipc_call_alloc(0);688 689 call_t *call = ipc_call_alloc(0); 683 690 IPC_SET_METHOD(call->data, method); 684 691 IPC_SET_ARG1(call->data, arg1); … … 686 693 IPC_SET_ARG3(call->data, arg3); 687 694 IPC_SET_ARG4(call->data, arg4); 695 688 696 /* 689 697 * To achieve deterministic behavior, zero out arguments that are beyond … … 691 699 */ 692 700 IPC_SET_ARG5(call->data, 0); 693 694 if (!(res = request_preprocess(call, phone))) 701 702 int res = request_preprocess(call, phone); 703 704 if (!res) 695 705 ipc_call(phone, call); 696 706 else 697 707 ipc_backsend_err(phone, call, res); 698 708 699 709 return (unative_t) call; 700 710 } … … 702 712 /** Make an asynchronous IPC call allowing to transmit the entire payload. 703 713 * 704 * @param phoneid Phone handle for the call. 705 * @param data Userspace address of call data with the request. 706 * 707 * @return See sys_ipc_call_async_fast(). 714 * @param phoneid Phone handle for the call. 715 * @param data Userspace address of call data with the request. 716 * 717 * @return See sys_ipc_call_async_fast(). 718 * 708 719 */ 709 720 unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data) 710 721 { 711 call_t *call;712 phone_t *phone;713 int res;714 int rc;715 716 722 if (check_call_limit()) 717 723 return IPC_CALLRET_TEMPORARY; 718 724 725 phone_t *phone; 719 726 if (phone_get(phoneid, &phone) != EOK) 720 727 return IPC_CALLRET_FATAL; 721 728 722 call = ipc_call_alloc(0);723 rc = copy_from_uspace(&call->data.args, &data->args,729 call_t *call = ipc_call_alloc(0); 730 int rc = copy_from_uspace(&call->data.args, &data->args, 724 731 sizeof(call->data.args)); 725 732 if (rc != 0) { … … 727 734 return (unative_t) rc; 728 735 } 729 if (!(res = request_preprocess(call, phone))) 736 737 int res = request_preprocess(call, phone); 738 739 if (!res) 730 740 ipc_call(phone, call); 731 741 else 732 742 ipc_backsend_err(phone, call, res); 733 743 734 744 return (unative_t) call; 735 745 } 736 746 737 /** Forward a received call to another destination - common code for both the 738 * fast and the slow version. 739 * 740 * @param callid Hash of the call to forward. 741 * @param phoneid Phone handle to use for forwarding. 742 * @param method New method to use for the forwarded call. 743 * @param arg1 New value of the first argument for the forwarded call. 744 * @param arg2 New value of the second argument for the forwarded call. 745 * @param arg3 New value of the third argument for the forwarded call. 746 * @param arg4 New value of the fourth argument for the forwarded call. 747 * @param arg5 New value of the fifth argument for the forwarded call. 748 * @param mode Flags that specify mode of the forward operation. 749 * @param slow If true, arg3, arg4 and arg5 are considered. Otherwise 750 * the function considers only the fast version arguments: 751 * i.e. arg1 and arg2. 752 * 753 * @return Return 0 on succes, otherwise return an error code. 754 * 755 * Warning: Make sure that ARG5 is not rewritten for certain system IPC 747 /** Forward a received call to another destination 748 * 749 * Common code for both the fast and the slow version. 750 * 751 * @param callid Hash of the call to forward. 752 * @param phoneid Phone handle to use for forwarding. 753 * @param method New method to use for the forwarded call. 754 * @param arg1 New value of the first argument for the forwarded call. 755 * @param arg2 New value of the second argument for the forwarded call. 756 * @param arg3 New value of the third argument for the forwarded call. 757 * @param arg4 New value of the fourth argument for the forwarded call. 758 * @param arg5 New value of the fifth argument for the forwarded call. 759 * @param mode Flags that specify mode of the forward operation. 760 * @param slow If true, arg3, arg4 and arg5 are considered. Otherwise 761 * the function considers only the fast version arguments: 762 * i.e. arg1 and arg2. 763 * 764 * @return 0 on succes, otherwise an error code. 765 * 766 * Warning: Make sure that ARG5 is not rewritten for certain system IPC 767 * 756 768 */ 757 769 static unative_t sys_ipc_forward_common(unative_t callid, unative_t phoneid, 758 770 unative_t method, unative_t arg1, unative_t arg2, unative_t arg3, 759 unative_t arg4, unative_t arg5, int mode, bool slow) 760 { 761 call_t *call; 762 phone_t *phone; 763 764 call = get_call(callid); 771 unative_t arg4, unative_t arg5, unsigned int mode, bool slow) 772 { 773 call_t *call = get_call(callid); 765 774 if (!call) 766 775 return ENOENT; 767 776 768 777 call->flags |= IPC_CALL_FORWARDED; 769 778 779 phone_t *phone; 770 780 if (phone_get(phoneid, &phone) != EOK) { 771 781 IPC_SET_RETVAL(call->data, EFORWARD); … … 773 783 return ENOENT; 774 784 } 775 785 776 786 if (!method_is_forwardable(IPC_GET_METHOD(call->data))) { 777 787 IPC_SET_RETVAL(call->data, EFORWARD); … … 779 789 return EPERM; 780 790 } 781 791 782 792 /* 783 793 * Userspace is not allowed to change method of system methods on … … 790 800 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) 791 801 phone_dealloc(IPC_GET_ARG5(call->data)); 792 802 793 803 IPC_SET_ARG1(call->data, method); 794 804 IPC_SET_ARG2(call->data, arg1); 795 805 IPC_SET_ARG3(call->data, arg2); 806 796 807 if (slow) { 797 808 IPC_SET_ARG4(call->data, arg3); … … 812 823 } 813 824 } 814 825 815 826 return ipc_forward(call, phone, &TASK->answerbox, mode); 816 827 } 817 828 818 829 /** Forward a received call to another destination - fast version. 819 *820 * @param callid Hash of the call to forward.821 * @param phoneid Phone handle to use for forwarding.822 * @param method New method to use for the forwarded call.823 * @param arg1 New value of the first argument for the forwarded call.824 * @param arg2 New value of the second argument for the forwarded call.825 * @param mode Flags that specify mode of the forward operation.826 *827 * @return Return 0 on succes, otherwise return an error code.828 830 * 829 831 * In case the original method is a system method, ARG1, ARG2 and ARG3 are … … 833 835 * is a set of immutable methods, for which the new method and arguments are not 834 836 * set and these values are ignored. 837 * 838 * @param callid Hash of the call to forward. 839 * @param phoneid Phone handle to use for forwarding. 840 * @param method New method to use for the forwarded call. 841 * @param arg1 New value of the first argument for the forwarded call. 842 * @param arg2 New value of the second argument for the forwarded call. 843 * @param mode Flags that specify mode of the forward operation. 844 * 845 * @return 0 on succes, otherwise an error code. 846 * 835 847 */ 836 848 unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid, 837 unative_t method, unative_t arg1, unative_t arg2, int mode)849 unative_t method, unative_t arg1, unative_t arg2, unsigned int mode) 838 850 { 839 851 return sys_ipc_forward_common(callid, phoneid, method, arg1, arg2, 0, 0, … … 842 854 843 855 /** Forward a received call to another destination - slow version. 844 *845 * @param callid Hash of the call to forward.846 * @param phoneid Phone handle to use for forwarding.847 * @param data Userspace address of the new IPC data.848 * @param mode Flags that specify mode of the forward operation.849 *850 * @return Return 0 on succes, otherwise return an error code.851 856 * 852 857 * This function is the slow verision of the sys_ipc_forward_fast interface. … … 856 861 * methods, it additionally stores the new value of arg3, arg4 and arg5, 857 862 * respectively, to ARG3, ARG4 and ARG5, respectively. 863 * 864 * @param callid Hash of the call to forward. 865 * @param phoneid Phone handle to use for forwarding. 866 * @param data Userspace address of the new IPC data. 867 * @param mode Flags that specify mode of the forward operation. 868 * 869 * @return 0 on succes, otherwise an error code. 870 * 858 871 */ 859 872 unative_t sys_ipc_forward_slow(unative_t callid, unative_t phoneid, 860 ipc_data_t *data, int mode)873 ipc_data_t *data, unsigned int mode) 861 874 { 862 875 ipc_data_t newdata; 863 int rc; 864 865 rc = copy_from_uspace(&newdata.args, &data->args, 876 int rc = copy_from_uspace(&newdata.args, &data->args, 866 877 sizeof(newdata.args)); 867 if (rc != 0) 878 if (rc != 0) 868 879 return (unative_t) rc; 869 880 870 881 return sys_ipc_forward_common(callid, phoneid, 871 882 IPC_GET_METHOD(newdata), IPC_GET_ARG1(newdata), … … 879 890 * than the generic sys_ipc_answer(). 880 891 * 881 * @param callid Hash of the call to be answered. 882 * @param retval Return value of the answer. 883 * @param arg1 Service-defined return value. 884 * @param arg2 Service-defined return value. 885 * @param arg3 Service-defined return value. 886 * @param arg4 Service-defined return value. 887 * 888 * @return Return 0 on success, otherwise return an error code. 892 * @param callid Hash of the call to be answered. 893 * @param retval Return value of the answer. 894 * @param arg1 Service-defined return value. 895 * @param arg2 Service-defined return value. 896 * @param arg3 Service-defined return value. 897 * @param arg4 Service-defined return value. 898 * 899 * @return 0 on success, otherwise an error code. 900 * 889 901 */ 890 902 unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval, 891 903 unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4) 892 904 { 893 call_t *call;894 ipc_data_t saved_data;895 int saveddata = 0;896 int rc;897 898 905 /* Do not answer notification callids */ 899 906 if (callid & IPC_CALLID_NOTIFICATION) 900 907 return 0; 901 902 call = get_call(callid);908 909 call_t *call = get_call(callid); 903 910 if (!call) 904 911 return ENOENT; 905 912 913 ipc_data_t saved_data; 914 bool saved; 915 906 916 if (answer_need_old(call)) { 907 917 memcpy(&saved_data, &call->data, sizeof(call->data)); 908 saveddata = 1; 909 } 910 918 saved = true; 919 } else 920 saved = false; 921 911 922 IPC_SET_RETVAL(call->data, retval); 912 923 IPC_SET_ARG1(call->data, arg1); … … 914 925 IPC_SET_ARG3(call->data, arg3); 915 926 IPC_SET_ARG4(call->data, arg4); 927 916 928 /* 917 929 * To achieve deterministic behavior, zero out arguments that are beyond … … 919 931 */ 920 932 IPC_SET_ARG5(call->data, 0); 921 rc = answer_preprocess(call, saveddata? &saved_data : NULL);922 933 int rc = answer_preprocess(call, saved ? &saved_data : NULL); 934 923 935 ipc_answer(&TASK->answerbox, call); 924 936 return rc; … … 927 939 /** Answer an IPC call. 928 940 * 929 * @param callid Hash of the call to be answered. 930 * @param data Userspace address of call data with the answer. 931 * 932 * @return Return 0 on success, otherwise return an error code. 941 * @param callid Hash of the call to be answered. 942 * @param data Userspace address of call data with the answer. 943 * 944 * @return 0 on success, otherwise an error code. 945 * 933 946 */ 934 947 unative_t sys_ipc_answer_slow(unative_t callid, ipc_data_t *data) 935 948 { 936 call_t *call;937 ipc_data_t saved_data;938 int saveddata = 0;939 int rc;940 941 949 /* Do not answer notification callids */ 942 950 if (callid & IPC_CALLID_NOTIFICATION) 943 951 return 0; 944 945 call = get_call(callid);952 953 call_t *call = get_call(callid); 946 954 if (!call) 947 955 return ENOENT; 948 956 957 ipc_data_t saved_data; 958 bool saved; 959 949 960 if (answer_need_old(call)) { 950 961 memcpy(&saved_data, &call->data, sizeof(call->data)); 951 saveddata = 1; 952 } 953 rc = copy_from_uspace(&call->data.args, &data->args, 962 saved = true; 963 } else 964 saved = false; 965 966 int rc = copy_from_uspace(&call->data.args, &data->args, 954 967 sizeof(call->data.args)); 955 968 if (rc != 0) 956 969 return rc; 957 958 rc = answer_preprocess(call, saved data? &saved_data : NULL);970 971 rc = answer_preprocess(call, saved ? &saved_data : NULL); 959 972 960 973 ipc_answer(&TASK->answerbox, call); 961 962 974 return rc; 963 975 } … … 965 977 /** Hang up a phone. 966 978 * 967 * @param Phone handle of the phone to be hung up. 968 * 969 * @return Return 0 on success or an error code. 979 * @param Phone handle of the phone to be hung up. 980 * 981 * @return 0 on success or an error code. 982 * 970 983 */ 971 984 unative_t sys_ipc_hangup(unative_t phoneid) 972 985 { 973 986 phone_t *phone; 974 987 975 988 if (phone_get(phoneid, &phone) != EOK) 976 989 return ENOENT; 977 990 978 991 if (ipc_phone_hangup(phone)) 979 992 return -1; 980 993 981 994 return 0; 982 995 } … … 984 997 /** Wait for an incoming IPC call or an answer. 985 998 * 986 * @param calldata Pointer to buffer where the call/answer data is stored. 987 * @param usec Timeout. See waitq_sleep_timeout() for explanation. 988 * @param flags Select mode of sleep operation. See waitq_sleep_timeout() 989 * for explanation. 990 * 991 * @return Hash of the call. 992 * If IPC_CALLID_NOTIFICATION bit is set in the hash, the 993 * call is a notification. IPC_CALLID_ANSWERED denotes an 994 * answer. 995 */ 996 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags) 999 * @param calldata Pointer to buffer where the call/answer data is stored. 1000 * @param usec Timeout. See waitq_sleep_timeout() for explanation. 1001 * @param flags Select mode of sleep operation. See waitq_sleep_timeout() 1002 * for explanation. 1003 * 1004 * @return Hash of the call. 1005 * If IPC_CALLID_NOTIFICATION bit is set in the hash, the 1006 * call is a notification. IPC_CALLID_ANSWERED denotes an 1007 * answer. 1008 * 1009 */ 1010 unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, 1011 unsigned int flags) 997 1012 { 998 1013 call_t *call; 999 1014 1000 1015 restart: 1001 1016 1002 1017 #ifdef CONFIG_UDEBUG 1003 1018 udebug_stoppable_begin(); 1004 #endif 1019 #endif 1020 1005 1021 call = ipc_wait_for_call(&TASK->answerbox, usec, 1006 1022 flags | SYNCH_FLAGS_INTERRUPTIBLE); 1007 1023 1008 1024 #ifdef CONFIG_UDEBUG 1009 1025 udebug_stoppable_end(); 1010 1026 #endif 1027 1011 1028 if (!call) 1012 1029 return 0; 1013 1030 1014 1031 if (call->flags & IPC_CALL_NOTIF) { 1015 1032 /* Set in_phone_hash to the interrupt counter */ … … 1017 1034 1018 1035 STRUCT_TO_USPACE(calldata, &call->data); 1019 1036 1020 1037 ipc_call_free(call); 1021 1038 1022 1039 return ((unative_t) call) | IPC_CALLID_NOTIFICATION; 1023 1040 } 1024 1041 1025 1042 if (call->flags & IPC_CALL_ANSWERED) { 1026 1043 process_answer(call); 1027 1044 1028 1045 if (call->flags & IPC_CALL_DISCARD_ANSWER) { 1029 1046 ipc_call_free(call); … … 1037 1054 atomic_dec(&TASK->active_calls); 1038 1055 } 1039 1056 1040 1057 STRUCT_TO_USPACE(&calldata->args, &call->data.args); 1041 1058 ipc_call_free(call); 1042 1059 1043 1060 return ((unative_t) call) | IPC_CALLID_ANSWERED; 1044 1061 } 1045 1062 1046 1063 if (process_request(&TASK->answerbox, call)) 1047 1064 goto restart; 1048 1065 1049 1066 /* Include phone address('id') of the caller in the request, 1050 1067 * copy whole call->data, not only call->data.args */ … … 1055 1072 */ 1056 1073 ipc_data_t saved_data; 1057 int saveddata = 0;1058 1074 bool saved; 1075 1059 1076 if (answer_need_old(call)) { 1060 1077 memcpy(&saved_data, &call->data, sizeof(call->data)); 1061 saveddata = 1; 1062 } 1078 saved = true; 1079 } else 1080 saved = false; 1063 1081 1064 1082 IPC_SET_RETVAL(call->data, EPARTY); 1065 (void) answer_preprocess(call, saved data? &saved_data : NULL);1083 (void) answer_preprocess(call, saved ? &saved_data : NULL); 1066 1084 ipc_answer(&TASK->answerbox, call); 1067 1085 return 0; 1068 1086 } 1069 return (unative_t)call; 1070 } 1071 1072 /** Interrupt one thread from sys_ipc_wait_for_call(). */ 1087 1088 return (unative_t) call; 1089 } 1090 1091 /** Interrupt one thread from sys_ipc_wait_for_call(). 1092 * 1093 */ 1073 1094 unative_t sys_ipc_poke(void) 1074 1095 { 1075 waitq_unsleep(&TASK->answerbox.wq); 1096 waitq_unsleep(&TASK->answerbox.wq); 1076 1097 return EOK; 1077 1098 } … … 1079 1100 /** Connect an IRQ handler to a task. 1080 1101 * 1081 * @param inr IRQ number. 1082 * @param devno Device number. 1083 * @param method Method to be associated with the notification. 1084 * @param ucode Uspace pointer to the top-half pseudocode. 1085 * 1086 * @return EPERM or a return code returned by ipc_irq_register(). 1102 * @param inr IRQ number. 1103 * @param devno Device number. 1104 * @param method Method to be associated with the notification. 1105 * @param ucode Uspace pointer to the top-half pseudocode. 1106 * 1107 * @return EPERM or a return code returned by ipc_irq_register(). 1108 * 1087 1109 */ 1088 1110 unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, … … 1091 1113 if (!(cap_get(TASK) & CAP_IRQ_REG)) 1092 1114 return EPERM; 1093 1115 1094 1116 return ipc_irq_register(&TASK->answerbox, inr, devno, method, ucode); 1095 1117 } … … 1097 1119 /** Disconnect an IRQ handler from a task. 1098 1120 * 1099 * @param inr IRQ number. 1100 * @param devno Device number. 1101 * 1102 * @return Zero on success or EPERM on error.. 1121 * @param inr IRQ number. 1122 * @param devno Device number. 1123 * 1124 * @return Zero on success or EPERM on error. 1125 * 1103 1126 */ 1104 1127 unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno) … … 1106 1129 if (!(cap_get(TASK) & CAP_IRQ_REG)) 1107 1130 return EPERM; 1108 1131 1109 1132 ipc_irq_unregister(&TASK->answerbox, inr, devno); 1110 1133 1111 1134 return 0; 1112 1135 } … … 1114 1137 #include <console/console.h> 1115 1138 1116 /** 1117 * Syscall connect to a task by id.1118 * 1119 * @return Phone id on success, or negative error code.1139 /** Syscall connect to a task by id. 1140 * 1141 * @return Phone id on success, or negative error code. 1142 * 1120 1143 */ 1121 1144 unative_t sys_ipc_connect_kbox(sysarg64_t *uspace_taskid_arg) … … 1123 1146 #ifdef CONFIG_UDEBUG 1124 1147 sysarg64_t taskid_arg; 1125 int rc; 1126 1127 rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); 1148 int rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); 1128 1149 if (rc != 0) 1129 1150 return (unative_t) rc; 1130 1151 1131 1152 LOG("sys_ipc_connect_kbox(%" PRIu64 ")\n", taskid_arg.value); 1132 1153 1133 1154 return ipc_connect_kbox(taskid_arg.value); 1134 1155 #else
Note:
See TracChangeset
for help on using the changeset viewer.