Changes in kernel/generic/src/ipc/ipc.c [be06914:170332d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
rbe06914 r170332d 66 66 /** Initialize a call structure. 67 67 * 68 * @param call Call structure to be initialized. 69 * 68 * @param call Call structure to be initialized. 70 69 */ 71 70 static void _ipc_call_init(call_t *call) … … 78 77 79 78 /** Allocate and initialize a call structure. 80 * 79 * 81 80 * The call is initialized, so that the reply will be directed to 82 81 * TASK->answerbox. 83 82 * 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); 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); 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. 102 * 101 * @param call Call structure to be freed. 103 102 */ 104 103 void ipc_call_free(call_t *call) … … 112 111 /** Initialize an answerbox structure. 113 112 * 114 * @param box Answerbox structure to be initialized. 115 * @param task Task to which the answerbox belongs. 116 * 113 * @param box Answerbox structure to be initialized. 114 * @param task Task to which the answerbox belongs. 117 115 */ 118 116 void ipc_answerbox_init(answerbox_t *box, task_t *task) 119 117 { 120 irq_spinlock_initialize(&box->lock, "ipc.box.lock");121 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock");118 spinlock_initialize(&box->lock, "ipc_box_lock"); 119 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); 122 120 waitq_initialize(&box->wq); 123 121 link_initialize(&box->sync_box_link); … … 133 131 /** Connect a phone to an answerbox. 134 132 * 135 * @param phone Initialized phone structure. 136 * @param box Initialized answerbox structure. 137 * 133 * @param phone Initialized phone structure. 134 * @param box Initialized answerbox structure. 138 135 */ 139 136 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 140 137 { 141 138 mutex_lock(&phone->lock); 142 139 143 140 phone->state = IPC_PHONE_CONNECTED; 144 141 phone->callee = box; 145 146 irq_spinlock_lock(&box->lock, true);142 143 spinlock_lock(&box->lock); 147 144 list_append(&phone->link, &box->connected_phones); 148 irq_spinlock_unlock(&box->lock, true);149 145 spinlock_unlock(&box->lock); 146 150 147 mutex_unlock(&phone->lock); 151 148 } … … 153 150 /** Initialize a phone structure. 154 151 * 155 * @param phone Phone structure to be initialized. 156 * 152 * @param phone Phone structure to be initialized. 157 153 */ 158 154 void ipc_phone_init(phone_t *phone) … … 166 162 /** Helper function to facilitate synchronous calls. 167 163 * 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 * 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. 173 168 */ 174 169 int ipc_call_sync(phone_t *phone, call_t *request) 175 170 { 176 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0); 171 answerbox_t *sync_box; 172 ipl_t ipl; 173 174 sync_box = slab_alloc(ipc_answerbox_slab, 0); 177 175 ipc_answerbox_init(sync_box, TASK); 178 176 179 177 /* 180 178 * Put the answerbox on the TASK's list of synchronous answerboxes so 181 179 * that it can be cleaned up if the call is interrupted. 182 180 */ 183 irq_spinlock_lock(&TASK->lock, true); 181 ipl = interrupts_disable(); 182 spinlock_lock(&TASK->lock); 184 183 list_append(&sync_box->sync_box_link, &TASK->sync_box_head); 185 irq_spinlock_unlock(&TASK->lock, true); 186 184 spinlock_unlock(&TASK->lock); 185 interrupts_restore(ipl); 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 /* The answerbox and the call will be freed by ipc_cleanup(). */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 irq_spinlock_lock(&TASK->lock, true); 201 (void) interrupts_disable(); 202 spinlock_lock(&TASK->lock); 202 203 list_remove(&sync_box->sync_box_link); 203 irq_spinlock_unlock(&TASK->lock, true); 204 204 spinlock_unlock(&TASK->lock); 205 interrupts_restore(ipl); 206 205 207 slab_free(ipc_answerbox_slab, sync_box); 206 208 return EOK; … … 209 211 /** Answer a message which was not dispatched and is not listed in any queue. 210 212 * 211 * @param call Call structure to be answered. 212 * @param selflocked If true, then TASK->answebox is locked. 213 * 213 * @param call Call structure to be answered. 214 * @param selflocked If true, then TASK->answebox is locked. 214 215 */ 215 216 static void _ipc_answer_free_call(call_t *call, bool selflocked) … … 217 218 answerbox_t *callerbox = call->callerbox; 218 219 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 219 220 ipl_t ipl; 221 220 222 /* Count sent answer */ 221 irq_spinlock_lock(&TASK->lock, true); 223 ipl = interrupts_disable(); 224 spinlock_lock(&TASK->lock); 222 225 TASK->ipc_info.answer_sent++; 223 irq_spinlock_unlock(&TASK->lock, true); 224 226 spinlock_unlock(&TASK->lock); 227 interrupts_restore(ipl); 228 225 229 call->flags |= IPC_CALL_ANSWERED; 226 230 227 231 if (call->flags & IPC_CALL_FORWARDED) { 228 232 if (call->caller_phone) { … … 231 235 } 232 236 } 233 237 234 238 if (do_lock) 235 irq_spinlock_lock(&callerbox->lock, true); 236 239 spinlock_lock(&callerbox->lock); 237 240 list_append(&call->link, &callerbox->answers); 238 239 241 if (do_lock) 240 irq_spinlock_unlock(&callerbox->lock, true); 241 242 spinlock_unlock(&callerbox->lock); 242 243 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 243 244 } … … 245 246 /** Answer a message which is in a callee queue. 246 247 * 247 * @param box Answerbox that is answering the message. 248 * @param call Modified request that is being sent back. 249 * 248 * @param box Answerbox that is answering the message. 249 * @param call Modified request that is being sent back. 250 250 */ 251 251 void ipc_answer(answerbox_t *box, call_t *call) 252 252 { 253 253 /* Remove from active box */ 254 irq_spinlock_lock(&box->lock, true);254 spinlock_lock(&box->lock); 255 255 list_remove(&call->link); 256 irq_spinlock_unlock(&box->lock, true); 257 256 spinlock_unlock(&box->lock); 258 257 /* Send back answer */ 259 258 _ipc_answer_free_call(call, false); … … 265 264 * message and sending it as a normal answer. 266 265 * 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 * 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. 271 269 */ 272 270 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) … … 280 278 /** Unsafe unchecking version of ipc_call. 281 279 * 282 * @param phone Phone structure the call comes from. 283 * @param box Destination answerbox structure. 284 * @param call Call structure with request. 285 * 280 * @param phone Phone structure the call comes from. 281 * @param box Destination answerbox structure. 282 * @param call Call structure with request. 286 283 */ 287 284 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 288 285 { 286 ipl_t ipl; 287 289 288 /* Count sent ipc call */ 290 irq_spinlock_lock(&TASK->lock, true); 289 ipl = interrupts_disable(); 290 spinlock_lock(&TASK->lock); 291 291 TASK->ipc_info.call_sent++; 292 irq_spinlock_unlock(&TASK->lock, true); 293 292 spinlock_unlock(&TASK->lock); 293 interrupts_restore(ipl); 294 294 295 if (!(call->flags & IPC_CALL_FORWARDED)) { 295 296 atomic_inc(&phone->active_calls); 296 297 call->data.phone = phone; 297 298 } 298 299 irq_spinlock_lock(&box->lock, true);299 300 spinlock_lock(&box->lock); 300 301 list_append(&call->link, &box->calls); 301 irq_spinlock_unlock(&box->lock, true); 302 302 spinlock_unlock(&box->lock); 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. 313 * 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. 314 313 */ 315 314 int ipc_call(phone_t *phone, call_t *call) 316 315 { 316 answerbox_t *box; 317 317 318 mutex_lock(&phone->lock); 318 319 if (phone->state != IPC_PHONE_CONNECTED) { … … 327 328 ipc_backsend_err(phone, call, ENOENT); 328 329 } 329 330 330 return ENOENT; 331 331 } 332 333 answerbox_t *box = phone->callee; 332 box = phone->callee; 334 333 _ipc_call(phone, box, call); 335 334 … … 343 342 * lazily later. 344 343 * 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 * 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. 350 348 */ 351 349 int ipc_phone_hangup(phone_t *phone) 352 350 { 351 answerbox_t *box; 352 call_t *call; 353 353 354 mutex_lock(&phone->lock); 354 355 if (phone->state == IPC_PHONE_FREE || … … 358 359 return -1; 359 360 } 360 361 answerbox_t *box = phone->callee; 361 box = phone->callee; 362 362 if (phone->state != IPC_PHONE_SLAMMED) { 363 363 /* Remove myself from answerbox */ 364 irq_spinlock_lock(&box->lock, true);364 spinlock_lock(&box->lock); 365 365 list_remove(&phone->link); 366 irq_spinlock_unlock(&box->lock, true);367 368 call _t *call= ipc_call_alloc(0);366 spinlock_unlock(&box->lock); 367 368 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 0 if forwarding succeeded or an error code if388 * there was anerror.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 Return 0 if forwarding succeeded or an error code if 388 * there was 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 */ 394 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, 395 unsigned int mode) 396 { 392 */ 393 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 394 { 395 ipl_t ipl; 396 397 397 /* Count forwarded calls */ 398 irq_spinlock_lock(&TASK->lock, true); 398 ipl = interrupts_disable(); 399 spinlock_lock(&TASK->lock); 399 400 TASK->ipc_info.forwarded++; 400 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 401 spinlock_unlock(&TASK->lock); 402 interrupts_restore(ipl); 403 404 spinlock_lock(&oldbox->lock); 401 405 list_remove(&call->link); 402 irq_spinlock_unlock(&oldbox->lock, true);403 406 spinlock_unlock(&oldbox->lock); 407 404 408 if (mode & IPC_FF_ROUTE_FROM_ME) { 405 409 if (!call->caller_phone) … … 407 411 call->data.phone = newphone; 408 412 } 409 413 410 414 return ipc_call(newphone, call); 411 415 } … … 414 418 /** Wait for a phone call. 415 419 * 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 * 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 * 426 429 * To distinguish between a call and an answer, have a look at call->flags. 427 * 428 */ 429 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags) 430 */ 431 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 430 432 { 431 433 call_t *request; 434 ipl_t ipl; 432 435 uint64_t irq_cnt = 0; 433 436 uint64_t answer_cnt = 0; 434 437 uint64_t call_cnt = 0; 435 438 int rc; 436 439 437 440 restart: 438 441 rc = waitq_sleep_timeout(&box->wq, usec, flags); … … 440 443 return NULL; 441 444 442 irq_spinlock_lock(&box->lock, true);445 spinlock_lock(&box->lock); 443 446 if (!list_empty(&box->irq_notifs)) { 444 /* Count received IRQ notification */ 445 irq_cnt++; 446 447 irq_spinlock_lock(&box->irq_lock, false); 448 447 /* Count recieved IRQ notification */ 448 irq_cnt++; 449 450 ipl = interrupts_disable(); 451 spinlock_lock(&box->irq_lock); 452 449 453 request = list_get_instance(box->irq_notifs.next, call_t, link); 450 454 list_remove(&request->link); 451 452 irq_spinlock_unlock(&box->irq_lock, false); 455 456 spinlock_unlock(&box->irq_lock); 457 interrupts_restore(ipl); 453 458 } else if (!list_empty(&box->answers)) { 454 /* Count rec eived answer */459 /* Count recieved answer */ 455 460 answer_cnt++; 456 461 457 462 /* Handle asynchronous answers */ 458 463 request = list_get_instance(box->answers.next, call_t, link); … … 460 465 atomic_dec(&request->data.phone->active_calls); 461 466 } else if (!list_empty(&box->calls)) { 462 /* Count rec eived call */467 /* Count recieved call */ 463 468 call_cnt++; 464 469 465 470 /* Handle requests */ 466 471 request = list_get_instance(box->calls.next, call_t, link); 467 472 list_remove(&request->link); 468 469 473 /* Append request to dispatch queue */ 470 474 list_append(&request->link, &box->dispatched_calls); 471 475 } else { 472 476 /* This can happen regularly after ipc_cleanup */ 473 irq_spinlock_unlock(&box->lock, true);477 spinlock_unlock(&box->lock); 474 478 goto restart; 475 479 } 480 spinlock_unlock(&box->lock); 476 481 477 i rq_spinlock_pass(&box->lock, &TASK->lock);478 479 TASK->ipc_info.irq_notif_rec eived += irq_cnt;480 TASK->ipc_info.answer_rec eived += answer_cnt;481 TASK->ipc_info.call_rec eived += call_cnt;482 483 i rq_spinlock_unlock(&TASK->lock, true);484 482 ipl = interrupts_disable(); 483 spinlock_lock(&TASK->lock); 484 TASK->ipc_info.irq_notif_recieved += irq_cnt; 485 TASK->ipc_info.answer_recieved += answer_cnt; 486 TASK->ipc_info.call_recieved += call_cnt; 487 spinlock_unlock(&TASK->lock); 488 interrupts_restore(ipl); 489 485 490 return request; 486 491 } … … 488 493 /** Answer all calls from list with EHANGUP answer. 489 494 * 490 * @param lst Head of the list to be cleaned up. 491 * 495 * @param lst Head of the list to be cleaned up. 492 496 */ 493 497 void ipc_cleanup_call_list(link_t *lst) 494 498 { 499 call_t *call; 500 495 501 while (!list_empty(lst)) { 496 call _t *call= list_get_instance(lst->next, call_t, link);502 call = list_get_instance(lst->next, call_t, link); 497 503 if (call->buffer) 498 504 free(call->buffer); 499 500 505 list_remove(&call->link); 501 506 502 507 IPC_SET_RETVAL(call->data, EHANGUP); 503 508 _ipc_answer_free_call(call, true); … … 507 512 /** Disconnects all phones connected to an answerbox. 508 513 * 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 * 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. 513 517 */ 514 518 void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) … … 516 520 phone_t *phone; 517 521 DEADLOCK_PROBE_INIT(p_phonelck); 518 519 call_t *call = notify_box ? ipc_call_alloc(0) : NULL; 520 522 ipl_t ipl; 523 call_t *call; 524 525 call = notify_box ? ipc_call_alloc(0) : NULL; 526 521 527 /* Disconnect all phones connected to our answerbox */ 522 528 restart_phones: 523 irq_spinlock_lock(&box->lock, true); 529 ipl = interrupts_disable(); 530 spinlock_lock(&box->lock); 524 531 while (!list_empty(&box->connected_phones)) { 525 532 phone = list_get_instance(box->connected_phones.next, 526 533 phone_t, link); 527 534 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 528 irq_spinlock_unlock(&box->lock, true); 535 spinlock_unlock(&box->lock); 536 interrupts_restore(ipl); 529 537 DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); 530 538 goto restart_phones; … … 533 541 /* Disconnect phone */ 534 542 ASSERT(phone->state == IPC_PHONE_CONNECTED); 535 543 536 544 list_remove(&phone->link); 537 545 phone->state = IPC_PHONE_SLAMMED; 538 546 539 547 if (notify_box) { 540 548 mutex_unlock(&phone->lock); 541 irq_spinlock_unlock(&box->lock, true); 542 549 spinlock_unlock(&box->lock); 550 interrupts_restore(ipl); 551 543 552 /* 544 553 * Send one message to the answerbox for each … … 550 559 call->flags |= IPC_CALL_DISCARD_ANSWER; 551 560 _ipc_call(phone, box, call); 552 561 553 562 /* Allocate another call in advance */ 554 563 call = ipc_call_alloc(0); 555 564 556 565 /* Must start again */ 557 566 goto restart_phones; 558 567 } 559 568 560 569 mutex_unlock(&phone->lock); 561 570 } 562 563 irq_spinlock_unlock(&box->lock, true); 564 571 572 spinlock_unlock(&box->lock); 573 interrupts_restore(ipl); 574 565 575 /* Free unused call */ 566 576 if (call) … … 568 578 } 569 579 570 /** Clean up all IPC communication of the current task.580 /** Cleans up all IPC communication of the current task. 571 581 * 572 582 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 573 583 * have to change it as well if you want to cleanup other tasks than TASK. 574 *575 584 */ 576 585 void ipc_cleanup(void) 577 586 { 587 int i; 588 call_t *call; 589 ipl_t ipl; 590 578 591 /* Disconnect all our phones ('ipc_phone_hangup') */ 579 size_t i;580 592 for (i = 0; i < IPC_MAX_PHONES; i++) 581 593 ipc_phone_hangup(&TASK->phones[i]); 582 594 583 595 /* Unsubscribe from any event notifications. */ 584 596 event_cleanup_answerbox(&TASK->answerbox); 585 597 586 598 /* Disconnect all connected irqs */ 587 599 ipc_irq_cleanup(&TASK->answerbox); 588 600 589 601 /* Disconnect all phones connected to our regular answerbox */ 590 602 ipc_answerbox_slam_phones(&TASK->answerbox, false); 591 603 592 604 #ifdef CONFIG_UDEBUG 593 605 /* Clean up kbox thread and communications */ 594 606 ipc_kbox_cleanup(); 595 607 #endif 596 608 597 609 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 598 irq_spinlock_lock(&TASK->answerbox.lock, true);610 spinlock_lock(&TASK->answerbox.lock); 599 611 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 600 612 ipc_cleanup_call_list(&TASK->answerbox.calls); 601 irq_spinlock_unlock(&TASK->answerbox.lock, true);613 spinlock_unlock(&TASK->answerbox.lock); 602 614 603 615 /* Wait for all answers to interrupted synchronous calls to arrive */ 604 ipl _t ipl= interrupts_disable();616 ipl = interrupts_disable(); 605 617 while (!list_empty(&TASK->sync_box_head)) { 606 618 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 607 619 answerbox_t, sync_box_link); 608 620 609 621 list_remove(&box->sync_box_link); 610 call _t *call= ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,622 call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 611 623 SYNCH_FLAGS_NONE); 612 624 ipc_call_free(call); … … 614 626 } 615 627 interrupts_restore(ipl); 616 628 617 629 /* Wait for all answers to asynchronous calls to arrive */ 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 */ 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 */ 624 634 for (i = 0; i < IPC_MAX_PHONES; i++) { 625 635 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && … … 629 639 } 630 640 631 /* 632 * Just for sure, we might have had some 633 * IPC_PHONE_CONNECTING phones 634 */ 641 /* Just for sure, we might have had some 642 * IPC_PHONE_CONNECTING phones */ 635 643 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 636 644 ipc_phone_hangup(&TASK->phones[i]); 637 638 /* 639 * If the hangup succeeded, it has sent a HANGUP 645 /* If the hangup succeeded, it has sent a HANGUP 640 646 * message, the IPC is now in HUNGUP state, we 641 * wait for the reply to come 642 */ 647 * wait for the reply to come */ 643 648 644 649 if (TASK->phones[i].state != IPC_PHONE_FREE) 645 650 break; 646 651 } 647 648 /* Got into cleanup */ 652 /* Voila, got into cleanup */ 649 653 if (i == IPC_MAX_PHONES) 650 654 break; 651 655 652 call _t *call= ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,656 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 653 657 SYNCH_FLAGS_NONE); 654 658 ASSERT((call->flags & IPC_CALL_ANSWERED) || … … 662 666 if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) 663 667 atomic_dec(&TASK->active_calls); 664 665 668 ipc_call_free(call); 666 669 } 667 670 } 668 671 669 /** Initilize IPC subsystem 670 * 671 */ 672 673 /** Initilize IPC subsystem */ 672 674 void ipc_init(void) 673 675 { … … 678 680 } 679 681 682 680 683 /** List answerbox contents. 681 684 * 682 * @param taskid Task ID. 683 * 685 * @param taskid Task ID. 684 686 */ 685 687 void ipc_print_task(task_id_t taskid) 686 688 { 687 irq_spinlock_lock(&tasks_lock, true); 688 task_t *task = task_find_by_id(taskid); 689 task_t *task; 690 int i; 691 call_t *call; 692 link_t *tmp; 693 ipl_t ipl; 689 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); 690 701 if (!task) { 691 i rq_spinlock_unlock(&tasks_lock, true);702 interrupts_restore(ipl); 692 703 return; 693 704 } 694 695 /* Hand-over-hand locking */ 696 irq_spinlock_exchange(&tasks_lock, &task->lock); 697 705 698 706 /* Print opened phones & details */ 699 707 printf("PHONE:\n"); 700 701 size_t i;702 708 for (i = 0; i < IPC_MAX_PHONES; i++) { 703 709 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { … … 705 711 continue; 706 712 } 707 708 713 if (task->phones[i].state != IPC_PHONE_FREE) { 709 printf("%" PRIs ": ", i); 710 714 printf("%d: ", i); 711 715 switch (task->phones[i].state) { 712 716 case IPC_PHONE_CONNECTING: … … 714 718 break; 715 719 case IPC_PHONE_CONNECTED: 716 printf("connected to: %p ", 717 task->phones[i].callee);720 printf("connected to: %p ", 721 task->phones[i].callee); 718 722 break; 719 723 case IPC_PHONE_SLAMMED: 720 724 printf("slammed by: %p ", 721 task->phones[i].callee);725 task->phones[i].callee); 722 726 break; 723 727 case IPC_PHONE_HUNGUP: 724 728 printf("hung up - was: %p ", 725 task->phones[i].callee);729 task->phones[i].callee); 726 730 break; 727 731 default: 728 732 break; 729 733 } 730 731 printf("active: %" PRIun "\n", 734 printf("active: %ld\n", 732 735 atomic_get(&task->phones[i].active_calls)); 733 736 } 734 735 737 mutex_unlock(&task->phones[i].lock); 736 738 } 737 738 irq_spinlock_lock(&task->answerbox.lock, false); 739 740 link_t *cur; 741 739 740 742 741 /* Print answerbox - calls */ 742 spinlock_lock(&task->answerbox.lock); 743 743 printf("ABOX - CALLS:\n"); 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);744 for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; 745 tmp = tmp->next) { 746 call = list_get_instance(tmp, 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 757 /* Print answerbox - dispatched calls */ 756 /* Print answerbox - calls */ 758 757 printf("ABOX - DISPATCHED CALLS:\n"); 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);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); 763 762 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 764 763 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun … … 770 769 call->flags); 771 770 } 772 773 /* Print answerbox - answers */ 771 /* Print answerbox - calls */ 774 772 printf("ABOX - ANSWERS:\n"); 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);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); 779 777 printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun 780 778 " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", … … 784 782 call->flags); 785 783 } 786 787 irq_spinlock_unlock(&task->answerbox.lock, false); 788 irq_spinlock_unlock(&task->lock, true); 784 785 spinlock_unlock(&task->answerbox.lock); 786 spinlock_unlock(&task->lock); 787 interrupts_restore(ipl); 789 788 } 790 789
Note:
See TracChangeset
for help on using the changeset viewer.