Changeset 924c2530 in mainline for kernel/generic/src/ipc/sysipc.c
- Timestamp:
- 2012-08-15T12:49:22Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 691d8d8
- Parents:
- 9a82ac1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/sysipc.c
r9a82ac1 r924c2530 491 491 } 492 492 493 static int r_preprocess_m_connection_clone(call_t *call, phone_t *phone) 494 { 495 phone_t *cloned_phone; 496 497 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 498 return ENOENT; 499 500 phones_lock(cloned_phone, phone); 501 502 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 503 phone->state != IPC_PHONE_CONNECTED) { 504 phones_unlock(cloned_phone, phone); 505 return EINVAL; 506 } 507 508 /* 509 * We can be pretty sure now that both tasks exist and we are 510 * connected to them. As we continue to hold the phone locks, 511 * we are effectively preventing them from finishing their 512 * potential cleanup. 513 * 514 */ 515 int newphid = phone_alloc(phone->callee->task); 516 if (newphid < 0) { 517 phones_unlock(cloned_phone, phone); 518 return ELIMIT; 519 } 520 521 ipc_phone_connect(&phone->callee->task->phones[newphid], 522 cloned_phone->callee); 523 phones_unlock(cloned_phone, phone); 524 525 /* Set the new phone for the callee. */ 526 IPC_SET_ARG1(call->data, newphid); 527 528 return EOK; 529 } 530 531 static int r_preprocess_m_clone_establish(call_t *call, phone_t *phone) 532 { 533 IPC_SET_ARG5(call->data, (sysarg_t) phone); 534 535 return EOK; 536 } 537 538 static int r_preprocess_m_connect_me_to(call_t *call, phone_t *phone) 539 { 540 int newphid = phone_alloc(TASK); 541 542 if (newphid < 0) 543 return ELIMIT; 544 545 /* Set arg5 for server */ 546 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]); 547 call->flags |= IPC_CALL_CONN_ME_TO; 548 call->priv = newphid; 549 550 return EOK; 551 } 552 553 static int r_preprocess_m_share_out(call_t *call, phone_t *phone) 554 { 555 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 556 557 if (!size) 558 return EPERM; 559 IPC_SET_ARG2(call->data, size); 560 561 return EOK; 562 } 563 564 static int r_preprocess_m_data_read(call_t *call, phone_t *phone) 565 { 566 size_t size = IPC_GET_ARG2(call->data); 567 568 if (size > DATA_XFER_LIMIT) { 569 int flags = IPC_GET_ARG3(call->data); 570 571 if (flags & IPC_XF_RESTRICT) 572 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT); 573 else 574 return ELIMIT; 575 } 576 577 return EOK; 578 } 579 580 static int r_preprocess_m_data_write(call_t *call, phone_t *phone) 581 { 582 uintptr_t src = IPC_GET_ARG1(call->data); 583 size_t size = IPC_GET_ARG2(call->data); 584 585 if (size > DATA_XFER_LIMIT) { 586 int flags = IPC_GET_ARG3(call->data); 587 588 if (flags & IPC_XF_RESTRICT) { 589 size = DATA_XFER_LIMIT; 590 IPC_SET_ARG2(call->data, size); 591 } else 592 return ELIMIT; 593 } 594 595 call->buffer = (uint8_t *) malloc(size, 0); 596 int rc = copy_from_uspace(call->buffer, (void *) src, size); 597 if (rc != 0) { 598 free(call->buffer); 599 return rc; 600 } 601 602 return EOK; 603 } 604 605 static int r_preprocess_m_state_change_authorize(call_t *call, phone_t *phone) 606 { 607 phone_t *sender_phone; 608 task_t *other_task_s; 609 610 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK) 611 return ENOENT; 612 613 mutex_lock(&sender_phone->lock); 614 if (sender_phone->state != IPC_PHONE_CONNECTED) { 615 mutex_unlock(&sender_phone->lock); 616 return EINVAL; 617 } 618 619 other_task_s = sender_phone->callee->task; 620 621 mutex_unlock(&sender_phone->lock); 622 623 /* Remember the third party task hash. */ 624 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 625 626 return EOK; 627 } 628 493 629 /** Called before the request is sent. 494 630 * … … 501 637 static int request_preprocess(call_t *call, phone_t *phone) 502 638 { 639 int rc = EOK; 640 503 641 switch (IPC_GET_IMETHOD(call->data)) { 504 case IPC_M_CONNECTION_CLONE: { 505 phone_t *cloned_phone; 506 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 507 return ENOENT; 508 509 phones_lock(cloned_phone, phone); 510 511 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 512 phone->state != IPC_PHONE_CONNECTED) { 513 phones_unlock(cloned_phone, phone); 514 return EINVAL; 515 } 516 517 /* 518 * We can be pretty sure now that both tasks exist and we are 519 * connected to them. As we continue to hold the phone locks, 520 * we are effectively preventing them from finishing their 521 * potential cleanup. 522 * 523 */ 524 int newphid = phone_alloc(phone->callee->task); 525 if (newphid < 0) { 526 phones_unlock(cloned_phone, phone); 527 return ELIMIT; 528 } 529 530 ipc_phone_connect(&phone->callee->task->phones[newphid], 531 cloned_phone->callee); 532 phones_unlock(cloned_phone, phone); 533 534 /* Set the new phone for the callee. */ 535 IPC_SET_ARG1(call->data, newphid); 536 break; 537 } 642 case IPC_M_CONNECTION_CLONE: 643 rc = r_preprocess_m_connection_clone(call, phone); 644 break; 538 645 case IPC_M_CLONE_ESTABLISH: 539 IPC_SET_ARG5(call->data, (sysarg_t) phone); 540 break; 541 case IPC_M_CONNECT_ME_TO: { 542 int newphid = phone_alloc(TASK); 543 if (newphid < 0) 544 return ELIMIT; 545 546 /* Set arg5 for server */ 547 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]); 548 call->flags |= IPC_CALL_CONN_ME_TO; 549 call->priv = newphid; 550 break; 551 } 552 case IPC_M_SHARE_OUT: { 553 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 554 if (!size) 555 return EPERM; 556 557 IPC_SET_ARG2(call->data, size); 558 break; 559 } 560 case IPC_M_DATA_READ: { 561 size_t size = IPC_GET_ARG2(call->data); 562 if (size > DATA_XFER_LIMIT) { 563 int flags = IPC_GET_ARG3(call->data); 564 if (flags & IPC_XF_RESTRICT) 565 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT); 566 else 567 return ELIMIT; 568 } 569 break; 570 } 571 case IPC_M_DATA_WRITE: { 572 uintptr_t src = IPC_GET_ARG1(call->data); 573 size_t size = IPC_GET_ARG2(call->data); 574 575 if (size > DATA_XFER_LIMIT) { 576 int flags = IPC_GET_ARG3(call->data); 577 if (flags & IPC_XF_RESTRICT) { 578 size = DATA_XFER_LIMIT; 579 IPC_SET_ARG2(call->data, size); 580 } else 581 return ELIMIT; 582 } 583 584 call->buffer = (uint8_t *) malloc(size, 0); 585 int rc = copy_from_uspace(call->buffer, (void *) src, size); 586 if (rc != 0) { 587 free(call->buffer); 588 return rc; 589 } 590 591 break; 592 } 593 case IPC_M_STATE_CHANGE_AUTHORIZE: { 594 phone_t *sender_phone; 595 task_t *other_task_s; 596 597 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK) 598 return ENOENT; 599 600 mutex_lock(&sender_phone->lock); 601 if (sender_phone->state != IPC_PHONE_CONNECTED) { 602 mutex_unlock(&sender_phone->lock); 603 return EINVAL; 604 } 605 606 other_task_s = sender_phone->callee->task; 607 608 mutex_unlock(&sender_phone->lock); 609 610 /* Remember the third party task hash. */ 611 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 612 break; 613 } 646 rc = r_preprocess_m_clone_establish(call, phone); 647 break; 648 case IPC_M_CONNECT_ME_TO: 649 rc = r_preprocess_m_connect_me_to(call, phone); 650 break; 651 case IPC_M_SHARE_OUT: 652 rc = r_preprocess_m_share_out(call, phone); 653 break; 654 case IPC_M_DATA_READ: 655 rc = r_preprocess_m_data_read(call, phone); 656 break; 657 case IPC_M_DATA_WRITE: 658 rc = r_preprocess_m_data_write(call, phone); 659 break; 660 case IPC_M_STATE_CHANGE_AUTHORIZE: 661 rc = r_preprocess_m_state_change_authorize(call, phone); 662 break; 614 663 #ifdef CONFIG_UDEBUG 615 664 case IPC_M_DEBUG: 616 return udebug_request_preprocess(call, phone); 665 rc = udebug_request_preprocess(call, phone); 666 break; 617 667 #endif 618 668 default: … … 620 670 } 621 671 622 return 0;672 return rc; 623 673 } 624 674
Note:
See TracChangeset
for help on using the changeset viewer.