Changes in kernel/generic/src/ipc/ipc.c [6aef742:287e83f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/ipc.c
r6aef742 r287e83f 62 62 63 63 static slab_cache_t *ipc_call_slab; 64 static slab_cache_t *ipc_answerbox_slab;65 64 66 65 /** Initialize a call structure. 67 66 * 68 * @param call Call structure to be initialized. 69 * 67 * @param call Call structure to be initialized. 70 68 */ 71 69 static void _ipc_call_init(call_t *call) … … 78 76 79 77 /** Allocate and initialize a call structure. 80 * 78 * 81 79 * The call is initialized, so that the reply will be directed to 82 80 * TASK->answerbox. 83 81 * 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); 82 * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC). 83 * 84 * @return If flags permit it, return NULL, or initialized kernel 85 * call structure. 86 */ 87 call_t *ipc_call_alloc(int flags) 88 { 89 call_t *call; 90 91 call = slab_alloc(ipc_call_slab, flags); 93 92 if (call) 94 93 _ipc_call_init(call); 95 94 96 95 return call; 97 96 } 98 97 98 /** Initialize a statically allocated call structure. 99 * 100 * @param call Statically allocated kernel call structure to be 101 * initialized. 102 */ 103 void ipc_call_static_init(call_t *call) 104 { 105 _ipc_call_init(call); 106 call->flags |= IPC_CALL_STATIC_ALLOC; 107 } 108 99 109 /** Deallocate a call structure. 100 110 * 101 * @param call Call structure to be freed. 102 * 111 * @param call Call structure to be freed. 103 112 */ 104 113 void ipc_call_free(call_t *call) 105 114 { 115 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 106 116 /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */ 107 117 if (call->buffer) … … 112 122 /** Initialize an answerbox structure. 113 123 * 114 * @param box Answerbox structure to be initialized. 115 * @param task Task to which the answerbox belongs. 116 * 124 * @param box Answerbox structure to be initialized. 125 * @param task Task to which the answerbox belongs. 117 126 */ 118 127 void ipc_answerbox_init(answerbox_t *box, task_t *task) 119 128 { 120 irq_spinlock_initialize(&box->lock, "ipc.box.lock");121 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock");129 spinlock_initialize(&box->lock, "ipc_box_lock"); 130 spinlock_initialize(&box->irq_lock, "ipc_box_irqlock"); 122 131 waitq_initialize(&box->wq); 123 link_initialize(&box->sync_box_link);124 132 list_initialize(&box->connected_phones); 125 133 list_initialize(&box->calls); … … 133 141 /** Connect a phone to an answerbox. 134 142 * 135 * @param phone Initialized phone structure. 136 * @param box Initialized answerbox structure. 137 * 143 * @param phone Initialized phone structure. 144 * @param box Initialized answerbox structure. 138 145 */ 139 146 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 140 147 { 141 148 mutex_lock(&phone->lock); 142 149 143 150 phone->state = IPC_PHONE_CONNECTED; 144 151 phone->callee = box; 145 146 irq_spinlock_lock(&box->lock, true);152 153 spinlock_lock(&box->lock); 147 154 list_append(&phone->link, &box->connected_phones); 148 irq_spinlock_unlock(&box->lock, true);149 155 spinlock_unlock(&box->lock); 156 150 157 mutex_unlock(&phone->lock); 151 158 } … … 153 160 /** Initialize a phone structure. 154 161 * 155 * @param phone Phone structure to be initialized. 156 * 162 * @param phone Phone structure to be initialized. 157 163 */ 158 164 void ipc_phone_init(phone_t *phone) … … 166 172 /** Helper function to facilitate synchronous calls. 167 173 * 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 * 174 * @param phone Destination kernel phone structure. 175 * @param request Call structure with request. 176 * 177 * @return EOK on success or EINTR if the sleep was interrupted. 173 178 */ 174 179 int ipc_call_sync(phone_t *phone, call_t *request) 175 180 { 176 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0); 177 ipc_answerbox_init(sync_box, TASK); 178 179 /* 180 * Put the answerbox on the TASK's list of synchronous answerboxes so 181 * that it can be cleaned up if the call is interrupted. 182 */ 183 irq_spinlock_lock(&TASK->lock, true); 184 list_append(&sync_box->sync_box_link, &TASK->sync_box_head); 185 irq_spinlock_unlock(&TASK->lock, true); 186 181 answerbox_t sync_box; 182 183 ipc_answerbox_init(&sync_box, TASK); 184 187 185 /* We will receive data in a special box. */ 188 request->callerbox = sync_box;189 186 request->callerbox = &sync_box; 187 190 188 ipc_call(phone, request); 191 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT, 192 SYNCH_FLAGS_INTERRUPTIBLE)) { 193 /* The answerbox and the call will be freed by ipc_cleanup(). */ 189 if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, 190 SYNCH_FLAGS_INTERRUPTIBLE)) 194 191 return EINTR; 195 }196 197 /*198 * The answer arrived without interruption so we can remove the199 * answerbox from the TASK's list of synchronous answerboxes.200 */201 irq_spinlock_lock(&TASK->lock, true);202 list_remove(&sync_box->sync_box_link);203 irq_spinlock_unlock(&TASK->lock, true);204 205 slab_free(ipc_answerbox_slab, sync_box);206 192 return EOK; 207 193 } … … 209 195 /** Answer a message which was not dispatched and is not listed in any queue. 210 196 * 211 * @param call Call structure to be answered. 212 * @param selflocked If true, then TASK->answebox is locked. 213 * 214 */ 215 static void _ipc_answer_free_call(call_t *call, bool selflocked) 197 * @param call Call structure to be answered. 198 */ 199 static void _ipc_answer_free_call(call_t *call) 216 200 { 217 201 answerbox_t *callerbox = call->callerbox; 218 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 219 220 /* Count sent answer */ 221 irq_spinlock_lock(&TASK->lock, true); 222 TASK->ipc_info.answer_sent++; 223 irq_spinlock_unlock(&TASK->lock, true); 224 202 225 203 call->flags |= IPC_CALL_ANSWERED; 226 204 227 205 if (call->flags & IPC_CALL_FORWARDED) { 228 206 if (call->caller_phone) { … … 231 209 } 232 210 } 233 234 if (do_lock) 235 irq_spinlock_lock(&callerbox->lock, true); 236 211 212 spinlock_lock(&callerbox->lock); 237 213 list_append(&call->link, &callerbox->answers); 238 239 if (do_lock) 240 irq_spinlock_unlock(&callerbox->lock, true); 241 214 spinlock_unlock(&callerbox->lock); 242 215 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 243 216 } … … 245 218 /** Answer a message which is in a callee queue. 246 219 * 247 * @param box Answerbox that is answering the message. 248 * @param call Modified request that is being sent back. 249 * 220 * @param box Answerbox that is answering the message. 221 * @param call Modified request that is being sent back. 250 222 */ 251 223 void ipc_answer(answerbox_t *box, call_t *call) 252 224 { 253 225 /* Remove from active box */ 254 irq_spinlock_lock(&box->lock, true);226 spinlock_lock(&box->lock); 255 227 list_remove(&call->link); 256 irq_spinlock_unlock(&box->lock, true); 257 228 spinlock_unlock(&box->lock); 258 229 /* Send back answer */ 259 _ipc_answer_free_call(call , false);230 _ipc_answer_free_call(call); 260 231 } 261 232 … … 265 236 * message and sending it as a normal answer. 266 237 * 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 * 271 */ 272 void ipc_backsend_err(phone_t *phone, call_t *call, sysarg_t err) 238 * @param phone Phone structure the call should appear to come from. 239 * @param call Call structure to be answered. 240 * @param err Return value to be used for the answer. 241 */ 242 void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err) 273 243 { 274 244 call->data.phone = phone; 275 245 atomic_inc(&phone->active_calls); 276 246 IPC_SET_RETVAL(call->data, err); 277 _ipc_answer_free_call(call , false);247 _ipc_answer_free_call(call); 278 248 } 279 249 280 250 /** Unsafe unchecking version of ipc_call. 281 251 * 282 * @param phone Phone structure the call comes from. 283 * @param box Destination answerbox structure. 284 * @param call Call structure with request. 285 * 252 * @param phone Phone structure the call comes from. 253 * @param box Destination answerbox structure. 254 * @param call Call structure with request. 286 255 */ 287 256 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 288 257 { 289 /* Count sent ipc call */290 irq_spinlock_lock(&TASK->lock, true);291 TASK->ipc_info.call_sent++;292 irq_spinlock_unlock(&TASK->lock, true);293 294 258 if (!(call->flags & IPC_CALL_FORWARDED)) { 295 259 atomic_inc(&phone->active_calls); 296 260 call->data.phone = phone; 297 call->data.task = TASK; 298 } 299 300 irq_spinlock_lock(&box->lock, true); 261 } 262 263 spinlock_lock(&box->lock); 301 264 list_append(&call->link, &box->calls); 302 irq_spinlock_unlock(&box->lock, true); 303 265 spinlock_unlock(&box->lock); 304 266 waitq_wakeup(&box->wq, WAKEUP_FIRST); 305 267 } … … 307 269 /** Send an asynchronous request using a phone to an answerbox. 308 270 * 309 * @param phone Phone structure the call comes from and which is 310 * connected to the destination answerbox. 311 * @param call Call structure with request. 312 * 313 * @return Return 0 on success, ENOENT on error. 314 * 271 * @param phone Phone structure the call comes from and which is 272 * connected to the destination answerbox. 273 * @param call Call structure with request. 274 * 275 * @return Return 0 on success, ENOENT on error. 315 276 */ 316 277 int ipc_call(phone_t *phone, call_t *call) 317 278 { 279 answerbox_t *box; 280 318 281 mutex_lock(&phone->lock); 319 282 if (phone->state != IPC_PHONE_CONNECTED) { … … 321 284 if (call->flags & IPC_CALL_FORWARDED) { 322 285 IPC_SET_RETVAL(call->data, EFORWARD); 323 _ipc_answer_free_call(call , false);286 _ipc_answer_free_call(call); 324 287 } else { 325 288 if (phone->state == IPC_PHONE_HUNGUP) … … 328 291 ipc_backsend_err(phone, call, ENOENT); 329 292 } 330 331 293 return ENOENT; 332 294 } 333 334 answerbox_t *box = phone->callee; 295 box = phone->callee; 335 296 _ipc_call(phone, box, call); 336 297 … … 344 305 * lazily later. 345 306 * 346 * @param phone Phone structure to be hung up. 347 * 348 * @return 0 if the phone is disconnected. 349 * @return -1 if the phone was already disconnected. 350 * 307 * @param phone Phone structure to be hung up. 308 * 309 * @return Return 0 if the phone is disconnected. 310 * Return -1 if the phone was already disconnected. 351 311 */ 352 312 int ipc_phone_hangup(phone_t *phone) 353 313 { 314 answerbox_t *box; 315 call_t *call; 316 354 317 mutex_lock(&phone->lock); 355 318 if (phone->state == IPC_PHONE_FREE || … … 359 322 return -1; 360 323 } 361 362 answerbox_t *box = phone->callee; 324 box = phone->callee; 363 325 if (phone->state != IPC_PHONE_SLAMMED) { 364 326 /* Remove myself from answerbox */ 365 irq_spinlock_lock(&box->lock, true);327 spinlock_lock(&box->lock); 366 328 list_remove(&phone->link); 367 irq_spinlock_unlock(&box->lock, true);368 369 call _t *call= ipc_call_alloc(0);370 IPC_SET_ IMETHOD(call->data, IPC_M_PHONE_HUNGUP);329 spinlock_unlock(&box->lock); 330 331 call = ipc_call_alloc(0); 332 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 371 333 call->flags |= IPC_CALL_DISCARD_ANSWER; 372 334 _ipc_call(phone, box, call); 373 335 } 374 336 375 337 phone->state = IPC_PHONE_HUNGUP; 376 338 mutex_unlock(&phone->lock); 377 339 378 340 return 0; 379 341 } … … 381 343 /** Forwards call from one answerbox to another one. 382 344 * 383 * @param call 384 * @param newphone 385 * @param oldbox 386 * @param mode 387 * 388 * @return 0 if forwarding succeeded or an error code if389 * there was anerror.390 * 345 * @param call Call structure to be redirected. 346 * @param newphone Phone structure to target answerbox. 347 * @param oldbox Old answerbox structure. 348 * @param mode Flags that specify mode of the forward operation. 349 * 350 * @return Return 0 if forwarding succeeded or an error code if 351 * there was error. 352 * 391 353 * The return value serves only as an information for the forwarder, 392 354 * the original caller is notified automatically with EFORWARD. 393 * 394 */ 395 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, 396 unsigned int mode) 397 { 398 /* Count forwarded calls */ 399 irq_spinlock_lock(&TASK->lock, true); 400 TASK->ipc_info.forwarded++; 401 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 355 */ 356 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox, int mode) 357 { 358 spinlock_lock(&oldbox->lock); 402 359 list_remove(&call->link); 403 irq_spinlock_unlock(&oldbox->lock, true);404 360 spinlock_unlock(&oldbox->lock); 361 405 362 if (mode & IPC_FF_ROUTE_FROM_ME) { 406 363 if (!call->caller_phone) 407 364 call->caller_phone = call->data.phone; 408 365 call->data.phone = newphone; 409 call->data.task = TASK; 410 } 411 366 } 367 412 368 return ipc_call(newphone, call); 413 369 } … … 416 372 /** Wait for a phone call. 417 373 * 418 * @param box Answerbox expecting the call. 419 * @param usec Timeout in microseconds. See documentation for 420 * waitq_sleep_timeout() for decription of its special 421 * meaning. 422 * @param flags Select mode of sleep operation. See documentation for 423 * waitq_sleep_timeout() for description of its special 424 * meaning. 425 * 426 * @return Recived call structure or NULL. 427 * 374 * @param box Answerbox expecting the call. 375 * @param usec Timeout in microseconds. See documentation for 376 * waitq_sleep_timeout() for decription of its special 377 * meaning. 378 * @param flags Select mode of sleep operation. See documentation for 379 * waitq_sleep_timeout() for description of its special 380 * meaning. 381 * @return Recived call structure or NULL. 382 * 428 383 * To distinguish between a call and an answer, have a look at call->flags. 429 * 430 */ 431 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, unsigned int flags) 384 */ 385 call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags) 432 386 { 433 387 call_t *request; 434 uint64_t irq_cnt = 0; 435 uint64_t answer_cnt = 0; 436 uint64_t call_cnt = 0; 388 ipl_t ipl; 437 389 int rc; 438 390 439 391 restart: 440 392 rc = waitq_sleep_timeout(&box->wq, usec, flags); … … 442 394 return NULL; 443 395 444 irq_spinlock_lock(&box->lock, true);396 spinlock_lock(&box->lock); 445 397 if (!list_empty(&box->irq_notifs)) { 446 /* Count received IRQ notification */ 447 irq_cnt++; 448 449 irq_spinlock_lock(&box->irq_lock, false); 450 398 ipl = interrupts_disable(); 399 spinlock_lock(&box->irq_lock); 400 451 401 request = list_get_instance(box->irq_notifs.next, call_t, link); 452 402 list_remove(&request->link); 453 454 irq_spinlock_unlock(&box->irq_lock, false); 403 404 spinlock_unlock(&box->irq_lock); 405 interrupts_restore(ipl); 455 406 } else if (!list_empty(&box->answers)) { 456 /* Count received answer */457 answer_cnt++;458 459 407 /* Handle asynchronous answers */ 460 408 request = list_get_instance(box->answers.next, call_t, link); … … 462 410 atomic_dec(&request->data.phone->active_calls); 463 411 } else if (!list_empty(&box->calls)) { 464 /* Count received call */465 call_cnt++;466 467 412 /* Handle requests */ 468 413 request = list_get_instance(box->calls.next, call_t, link); 469 414 list_remove(&request->link); 470 471 415 /* Append request to dispatch queue */ 472 416 list_append(&request->link, &box->dispatched_calls); 473 417 } else { 474 418 /* This can happen regularly after ipc_cleanup */ 475 irq_spinlock_unlock(&box->lock, true);419 spinlock_unlock(&box->lock); 476 420 goto restart; 477 421 } 478 479 irq_spinlock_pass(&box->lock, &TASK->lock); 480 481 TASK->ipc_info.irq_notif_received += irq_cnt; 482 TASK->ipc_info.answer_received += answer_cnt; 483 TASK->ipc_info.call_received += call_cnt; 484 485 irq_spinlock_unlock(&TASK->lock, true); 486 422 spinlock_unlock(&box->lock); 487 423 return request; 488 424 } … … 490 426 /** Answer all calls from list with EHANGUP answer. 491 427 * 492 * @param lst Head of the list to be cleaned up. 493 * 428 * @param lst Head of the list to be cleaned up. 494 429 */ 495 430 void ipc_cleanup_call_list(link_t *lst) 496 431 { 432 call_t *call; 433 497 434 while (!list_empty(lst)) { 498 call _t *call= list_get_instance(lst->next, call_t, link);435 call = list_get_instance(lst->next, call_t, link); 499 436 if (call->buffer) 500 437 free(call->buffer); 501 502 438 list_remove(&call->link); 503 439 504 440 IPC_SET_RETVAL(call->data, EHANGUP); 505 _ipc_answer_free_call(call , true);441 _ipc_answer_free_call(call); 506 442 } 507 443 } … … 509 445 /** Disconnects all phones connected to an answerbox. 510 446 * 511 * @param box Answerbox to disconnect phones from. 512 * @param notify_box If true, the answerbox will get a hangup message for 513 * each disconnected phone. 514 * 447 * @param box Answerbox to disconnect phones from. 448 * @param notify_box If true, the answerbox will get a hangup message for 449 * each disconnected phone. 515 450 */ 516 451 void ipc_answerbox_slam_phones(answerbox_t *box, bool notify_box) … … 518 453 phone_t *phone; 519 454 DEADLOCK_PROBE_INIT(p_phonelck); 520 521 call_t *call = notify_box ? ipc_call_alloc(0) : NULL; 522 455 ipl_t ipl; 456 call_t *call; 457 458 call = notify_box ? ipc_call_alloc(0) : NULL; 459 523 460 /* Disconnect all phones connected to our answerbox */ 524 461 restart_phones: 525 irq_spinlock_lock(&box->lock, true); 462 ipl = interrupts_disable(); 463 spinlock_lock(&box->lock); 526 464 while (!list_empty(&box->connected_phones)) { 527 465 phone = list_get_instance(box->connected_phones.next, 528 466 phone_t, link); 529 467 if (SYNCH_FAILED(mutex_trylock(&phone->lock))) { 530 irq_spinlock_unlock(&box->lock, true); 468 spinlock_unlock(&box->lock); 469 interrupts_restore(ipl); 531 470 DEADLOCK_PROBE(p_phonelck, DEADLOCK_THRESHOLD); 532 471 goto restart_phones; … … 535 474 /* Disconnect phone */ 536 475 ASSERT(phone->state == IPC_PHONE_CONNECTED); 537 476 538 477 list_remove(&phone->link); 539 478 phone->state = IPC_PHONE_SLAMMED; 540 479 541 480 if (notify_box) { 542 481 mutex_unlock(&phone->lock); 543 irq_spinlock_unlock(&box->lock, true); 544 482 spinlock_unlock(&box->lock); 483 interrupts_restore(ipl); 484 545 485 /* 546 486 * Send one message to the answerbox for each … … 549 489 * disconnected. 550 490 */ 551 IPC_SET_ IMETHOD(call->data, IPC_M_PHONE_HUNGUP);491 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 552 492 call->flags |= IPC_CALL_DISCARD_ANSWER; 553 493 _ipc_call(phone, box, call); 554 494 555 495 /* Allocate another call in advance */ 556 496 call = ipc_call_alloc(0); 557 497 558 498 /* Must start again */ 559 499 goto restart_phones; 560 500 } 561 501 562 502 mutex_unlock(&phone->lock); 563 503 } 564 565 irq_spinlock_unlock(&box->lock, true); 566 504 505 spinlock_unlock(&box->lock); 506 interrupts_restore(ipl); 507 567 508 /* Free unused call */ 568 509 if (call) … … 570 511 } 571 512 572 /** Clean up all IPC communication of the current task.513 /** Cleans up all IPC communication of the current task. 573 514 * 574 515 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you 575 516 * have to change it as well if you want to cleanup other tasks than TASK. 576 *577 517 */ 578 518 void ipc_cleanup(void) 579 519 { 520 int i; 521 call_t *call; 522 580 523 /* Disconnect all our phones ('ipc_phone_hangup') */ 581 size_t i;582 524 for (i = 0; i < IPC_MAX_PHONES; i++) 583 525 ipc_phone_hangup(&TASK->phones[i]); 584 526 585 527 /* Unsubscribe from any event notifications. */ 586 528 event_cleanup_answerbox(&TASK->answerbox); 587 529 588 530 /* Disconnect all connected irqs */ 589 531 ipc_irq_cleanup(&TASK->answerbox); 590 532 591 533 /* Disconnect all phones connected to our regular answerbox */ 592 534 ipc_answerbox_slam_phones(&TASK->answerbox, false); 593 535 594 536 #ifdef CONFIG_UDEBUG 595 537 /* Clean up kbox thread and communications */ 596 538 ipc_kbox_cleanup(); 597 539 #endif 598 540 599 541 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 600 irq_spinlock_lock(&TASK->answerbox.lock, true);542 spinlock_lock(&TASK->answerbox.lock); 601 543 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 602 544 ipc_cleanup_call_list(&TASK->answerbox.calls); 603 irq_spinlock_unlock(&TASK->answerbox.lock, true);545 spinlock_unlock(&TASK->answerbox.lock); 604 546 605 /* Wait for all answers to interrupted synchronous calls to arrive */ 606 ipl_t ipl = interrupts_disable(); 607 while (!list_empty(&TASK->sync_box_head)) { 608 answerbox_t *box = list_get_instance(TASK->sync_box_head.next, 609 answerbox_t, sync_box_link); 610 611 list_remove(&box->sync_box_link); 612 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT, 613 SYNCH_FLAGS_NONE); 614 ipc_call_free(call); 615 slab_free(ipc_answerbox_slab, box); 616 } 617 interrupts_restore(ipl); 618 619 /* Wait for all answers to asynchronous calls to arrive */ 620 while (true) { 621 /* 622 * Go through all phones, until they are all FREE 623 * Locking is not needed, no one else should modify 624 * it when we are in cleanup 625 */ 547 /* Wait for all async answers to arrive */ 548 while (1) { 549 /* Go through all phones, until all are FREE... */ 550 /* Locking not needed, no one else should modify 551 * it, when we are in cleanup */ 626 552 for (i = 0; i < IPC_MAX_PHONES; i++) { 627 553 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 628 atomic_get(&TASK->phones[i].active_calls) == 0) {554 atomic_get(&TASK->phones[i].active_calls) == 0) 629 555 TASK->phones[i].state = IPC_PHONE_FREE; 630 TASK->phones[i].callee = NULL;631 }632 556 633 /* 634 * Just for sure, we might have had some 635 * IPC_PHONE_CONNECTING phones 636 */ 557 /* Just for sure, we might have had some 558 * IPC_PHONE_CONNECTING phones */ 637 559 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 638 560 ipc_phone_hangup(&TASK->phones[i]); 639 640 /* 641 * If the hangup succeeded, it has sent a HANGUP 561 /* If the hangup succeeded, it has sent a HANGUP 642 562 * message, the IPC is now in HUNGUP state, we 643 * wait for the reply to come 644 */ 563 * wait for the reply to come */ 645 564 646 565 if (TASK->phones[i].state != IPC_PHONE_FREE) 647 566 break; 648 567 } 649 650 /* Got into cleanup */ 568 /* Voila, got into cleanup */ 651 569 if (i == IPC_MAX_PHONES) 652 570 break; 653 571 654 call _t *call= ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,572 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 655 573 SYNCH_FLAGS_NONE); 656 574 ASSERT((call->flags & IPC_CALL_ANSWERED) || 657 575 (call->flags & IPC_CALL_NOTIF)); 576 ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); 658 577 578 /* 579 * Record the receipt of this call in the current task's counter 580 * of active calls. IPC_M_PHONE_HUNGUP calls do not contribute 581 * to this counter so do not record answers to them either. 582 */ 583 if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) 584 atomic_dec(&TASK->active_calls); 659 585 ipc_call_free(call); 660 586 } 661 587 } 662 588 663 /** Initilize IPC subsystem 664 * 665 */ 589 590 /** Initilize IPC subsystem */ 666 591 void ipc_init(void) 667 592 { 668 593 ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, 669 594 NULL, 0); 670 ipc_answerbox_slab = slab_cache_create("ipc_answerbox", 671 sizeof(answerbox_t), 0, NULL, NULL, 0); 672 } 595 } 596 673 597 674 598 /** List answerbox contents. 675 599 * 676 * @param taskid Task ID. 677 * 600 * @param taskid Task ID. 678 601 */ 679 602 void ipc_print_task(task_id_t taskid) 680 603 { 681 irq_spinlock_lock(&tasks_lock, true); 682 task_t *task = task_find_by_id(taskid); 604 task_t *task; 605 int i; 606 call_t *call; 607 link_t *tmp; 683 608 684 if (!task) { 685 irq_spinlock_unlock(&tasks_lock, true); 609 spinlock_lock(&tasks_lock); 610 task = task_find_by_id(taskid); 611 if (task) 612 spinlock_lock(&task->lock); 613 spinlock_unlock(&tasks_lock); 614 if (!task) 686 615 return; 687 } 688 689 /* Hand-over-hand locking */ 690 irq_spinlock_exchange(&tasks_lock, &task->lock); 691 692 printf("[phone id] [calls] [state\n"); 693 694 size_t i; 616 617 /* Print opened phones & details */ 618 printf("PHONE:\n"); 695 619 for (i = 0; i < IPC_MAX_PHONES; i++) { 696 620 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) { 697 printf("% -10zu (mutex busy)\n", i);621 printf("%d: mutex busy\n", i); 698 622 continue; 699 623 } 700 701 624 if (task->phones[i].state != IPC_PHONE_FREE) { 702 printf("%-10zu %7" PRIun " ", i, 703 atomic_get(&task->phones[i].active_calls)); 704 625 printf("%d: ", i); 705 626 switch (task->phones[i].state) { 706 627 case IPC_PHONE_CONNECTING: 707 printf("connecting ");628 printf("connecting "); 708 629 break; 709 630 case IPC_PHONE_CONNECTED: 710 printf("connected to %" PRIu64 " (%s)", 711 task->phones[i].callee->task->taskid, 712 task->phones[i].callee->task->name); 631 printf("connected to: %p ", 632 task->phones[i].callee); 713 633 break; 714 634 case IPC_PHONE_SLAMMED: 715 printf("slammed by %p",716 task->phones[i].callee);635 printf("slammed by: %p ", 636 task->phones[i].callee); 717 637 break; 718 638 case IPC_PHONE_HUNGUP: 719 printf("hung up by %p",720 task->phones[i].callee);639 printf("hung up - was: %p ", 640 task->phones[i].callee); 721 641 break; 722 642 default: 723 643 break; 724 644 } 725 726 printf("\n");645 printf("active: %ld\n", 646 atomic_get(&task->phones[i].active_calls)); 727 647 } 728 729 648 mutex_unlock(&task->phones[i].lock); 730 649 } 731 732 irq_spinlock_lock(&task->answerbox.lock, false); 733 734 #ifdef __32_BITS__ 735 printf("[call id ] [method] [arg1] [arg2] [arg3] [arg4] [arg5]" 736 " [flags] [sender\n"); 737 #endif 738 739 #ifdef __64_BITS__ 740 printf("[call id ] [method] [arg1] [arg2] [arg3] [arg4]" 741 " [arg5] [flags] [sender\n"); 742 #endif 743 744 link_t *cur; 745 746 printf(" --- incomming calls ---\n"); 747 for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls; 748 cur = cur->next) { 749 call_t *call = list_get_instance(cur, call_t, link); 750 751 #ifdef __32_BITS__ 752 printf("%10p ", call); 753 #endif 754 755 #ifdef __64_BITS__ 756 printf("%18p ", call); 757 #endif 758 759 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 760 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 761 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 650 651 652 /* Print answerbox - calls */ 653 spinlock_lock(&task->answerbox.lock); 654 printf("ABOX - CALLS:\n"); 655 for (tmp = task->answerbox.calls.next; tmp != &task->answerbox.calls; 656 tmp = tmp->next) { 657 call = list_get_instance(tmp, call_t, link); 658 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 659 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun 660 " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, 661 call->sender->taskid, 662 IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), 762 663 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 763 664 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 764 call->flags, call->sender->taskid, call->sender->name); 765 } 766 767 printf(" --- dispatched calls ---\n"); 768 for (cur = task->answerbox.dispatched_calls.next; 769 cur != &task->answerbox.dispatched_calls; 770 cur = cur->next) { 771 call_t *call = list_get_instance(cur, call_t, link); 772 773 #ifdef __32_BITS__ 774 printf("%10p ", call); 775 #endif 776 777 #ifdef __64_BITS__ 778 printf("%18p ", call); 779 #endif 780 781 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 782 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 783 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 665 call->flags); 666 } 667 /* Print answerbox - calls */ 668 printf("ABOX - DISPATCHED CALLS:\n"); 669 for (tmp = task->answerbox.dispatched_calls.next; 670 tmp != &task->answerbox.dispatched_calls; 671 tmp = tmp->next) { 672 call = list_get_instance(tmp, call_t, link); 673 printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun 674 " A1:%" PRIun " A2:%" PRIun " A3:%" PRIun 675 " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, 676 call->sender->taskid, 677 IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), 784 678 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 785 679 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 786 call->flags, call->sender->taskid, call->sender->name); 787 } 788 789 printf(" --- incoming answers ---\n"); 790 for (cur = task->answerbox.answers.next; 791 cur != &task->answerbox.answers; 792 cur = cur->next) { 793 call_t *call = list_get_instance(cur, call_t, link); 794 795 #ifdef __32_BITS__ 796 printf("%10p ", call); 797 #endif 798 799 #ifdef __64_BITS__ 800 printf("%18p ", call); 801 #endif 802 803 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 804 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 805 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 680 call->flags); 681 } 682 /* Print answerbox - calls */ 683 printf("ABOX - ANSWERS:\n"); 684 for (tmp = task->answerbox.answers.next; 685 tmp != &task->answerbox.answers; 686 tmp = tmp->next) { 687 call = list_get_instance(tmp, call_t, link); 688 printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun 689 " A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", 690 call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), 806 691 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 807 692 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 808 call->flags , call->sender->taskid, call->sender->name);809 } 810 811 irq_spinlock_unlock(&task->answerbox.lock, false);812 irq_spinlock_unlock(&task->lock, true);693 call->flags); 694 } 695 696 spinlock_unlock(&task->answerbox.lock); 697 spinlock_unlock(&task->lock); 813 698 } 814 699
Note:
See TracChangeset
for help on using the changeset viewer.