Changes in / [983cabe8:3ffd4c3] in mainline
- Files:
-
- 13 deleted
- 13 edited
-
abi/include/ipc/ipc.h (modified) (1 diff)
-
kernel/Makefile (modified) (1 diff)
-
kernel/generic/include/config.h (modified) (1 diff)
-
kernel/generic/include/ipc/ipc.h (modified) (5 diffs)
-
kernel/generic/include/ipc/ipcrsc.h (modified) (1 diff)
-
kernel/generic/include/ipc/sysipc_ops.h (deleted)
-
kernel/generic/include/ipc/sysipc_priv.h (deleted)
-
kernel/generic/include/proc/task.h (modified) (1 diff)
-
kernel/generic/src/ipc/event.c (modified) (1 diff)
-
kernel/generic/src/ipc/ipc.c (modified) (20 diffs)
-
kernel/generic/src/ipc/ipcrsc.c (modified) (5 diffs)
-
kernel/generic/src/ipc/irq.c (modified) (1 diff)
-
kernel/generic/src/ipc/kbox.c (modified) (3 diffs)
-
kernel/generic/src/ipc/ops/clnestab.c (deleted)
-
kernel/generic/src/ipc/ops/conctmeto.c (deleted)
-
kernel/generic/src/ipc/ops/concttome.c (deleted)
-
kernel/generic/src/ipc/ops/connclone.c (deleted)
-
kernel/generic/src/ipc/ops/dataread.c (deleted)
-
kernel/generic/src/ipc/ops/datawrite.c (deleted)
-
kernel/generic/src/ipc/ops/debug.c (deleted)
-
kernel/generic/src/ipc/ops/sharein.c (deleted)
-
kernel/generic/src/ipc/ops/shareout.c (deleted)
-
kernel/generic/src/ipc/ops/stchngath.c (deleted)
-
kernel/generic/src/ipc/sysipc.c (modified) (8 diffs)
-
kernel/generic/src/ipc/sysipc_ops.c (deleted)
-
kernel/generic/src/proc/task.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
abi/include/ipc/ipc.h
r983cabe8 r3ffd4c3 57 57 #define IPC_CALL_FORWARDED (1 << 2) 58 58 59 /** Identify connect_me_to answer */ 60 #define IPC_CALL_CONN_ME_TO (1 << 3) 61 59 62 /** Interrupt notification */ 60 #define IPC_CALL_NOTIF (1 << 3)63 #define IPC_CALL_NOTIF (1 << 4) 61 64 62 65 -
kernel/Makefile
r983cabe8 r3ffd4c3 257 257 generic/src/ipc/ipc.c \ 258 258 generic/src/ipc/sysipc.c \ 259 generic/src/ipc/sysipc_ops.c \260 generic/src/ipc/ops/clnestab.c \261 generic/src/ipc/ops/conctmeto.c \262 generic/src/ipc/ops/concttome.c \263 generic/src/ipc/ops/connclone.c \264 generic/src/ipc/ops/dataread.c \265 generic/src/ipc/ops/datawrite.c \266 generic/src/ipc/ops/debug.c \267 generic/src/ipc/ops/sharein.c \268 generic/src/ipc/ops/shareout.c \269 generic/src/ipc/ops/stchngath.c \270 259 generic/src/ipc/ipcrsc.c \ 271 260 generic/src/ipc/irq.c \ -
kernel/generic/include/config.h
r983cabe8 r3ffd4c3 47 47 #define CONFIG_INIT_TASKS 32 48 48 #define CONFIG_TASK_NAME_BUFLEN 32 49 50 /**51 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ52 * requests.53 */54 #define DATA_XFER_LIMIT (64 * 1024)55 49 56 50 #ifndef __ASM__ -
kernel/generic/include/ipc/ipc.h
r983cabe8 r3ffd4c3 72 72 typedef struct answerbox { 73 73 IRQ_SPINLOCK_DECLARE(lock); 74 75 /** Answerbox is active until it enters cleanup. */76 bool active;77 74 78 75 struct task *task; … … 109 106 110 107 typedef struct { 111 /** 112 * Task link. 113 * Valid only when the call is not forgotten. 114 * Protected by the task's active_calls_lock. 115 */ 116 link_t ta_link; 117 118 /** Answerbox link. */ 119 link_t ab_link; 108 link_t link; 120 109 121 110 unsigned int flags; 122 123 /** Protects the forget member. */124 SPINLOCK_DECLARE(forget_lock);125 126 /**127 * True if the caller 'forgot' this call and donated it to the callee.128 * Forgotten calls are discarded upon answering (the answer is not129 * delivered) and answered calls cannot be forgotten. Forgotten calls130 * also do not figure on the task's active call list.131 *132 * We keep this separate from the flags so that it is not necessary133 * to take a lock when accessing them.134 */135 bool forget;136 137 /** True if the call is in the active list. */138 bool active;139 111 140 /** 141 * Identification of the caller. 142 * Valid only when the call is not forgotten. 143 */ 112 /** Identification of the caller. */ 144 113 struct task *sender; 145 146 /** Phone which was used to send the call. */147 phone_t *caller_phone;148 114 149 115 /** Private data to internal IPC. */ … … 152 118 /** Data passed from/to userspace. */ 153 119 ipc_data_t data; 154 155 /** Method as it was sent in the request. */ 156 sysarg_t request_method; 157 120 158 121 /** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */ 159 122 uint8_t *buffer; 123 124 /* 125 * The forward operation can masquerade the caller phone. For those 126 * cases, we must keep it aside so that the answer is processed 127 * correctly. 128 */ 129 phone_t *caller_phone; 160 130 } call_t; 161 131 … … 171 141 extern int ipc_forward(call_t *, phone_t *, answerbox_t *, unsigned int); 172 142 extern void ipc_answer(answerbox_t *, call_t *); 173 extern void _ipc_answer_free_call(call_t *, bool);174 143 175 144 extern void ipc_phone_init(phone_t *); 176 extern boolipc_phone_connect(phone_t *, answerbox_t *);145 extern void ipc_phone_connect(phone_t *, answerbox_t *); 177 146 extern int ipc_phone_hangup(phone_t *); 178 147 … … 182 151 extern void ipc_backsend_err(phone_t *, call_t *, sysarg_t); 183 152 extern void ipc_answerbox_slam_phones(answerbox_t *, bool); 184 extern void ipc_cleanup_call_list( answerbox_t *,list_t *);153 extern void ipc_cleanup_call_list(list_t *); 185 154 186 155 extern void ipc_print_task(task_id_t); -
kernel/generic/include/ipc/ipcrsc.h
r983cabe8 r3ffd4c3 40 40 41 41 extern call_t *get_call(sysarg_t); 42 extern int phone_get(sysarg_t, phone_t **);43 42 extern int phone_alloc(task_t *); 44 extern boolphone_connect(int, answerbox_t *);43 extern void phone_connect(int, answerbox_t *); 45 44 extern void phone_dealloc(int); 46 45 -
kernel/generic/include/proc/task.h
r983cabe8 r3ffd4c3 91 91 92 92 /* IPC stuff */ 93 94 /** Receiving communication endpoint */ 95 answerbox_t answerbox; 96 97 /** Sending communication endpoints */ 93 answerbox_t answerbox; /**< Communication endpoint */ 98 94 phone_t phones[IPC_MAX_PHONES]; 99 100 /** Spinlock protecting the active_calls list. */ 101 SPINLOCK_DECLARE(active_calls_lock); 102 103 /** 104 * List of all calls sent by this task that have not yet been 105 * answered. 106 */ 107 list_t active_calls; 108 95 stats_ipc_t ipc_info; /**< IPC statistics */ 109 96 event_t events[EVENT_TASK_END - EVENT_END]; 110 111 /** IPC statistics */112 stats_ipc_t ipc_info;113 97 114 98 #ifdef CONFIG_UDEBUG -
kernel/generic/src/ipc/event.c
r983cabe8 r3ffd4c3 163 163 call->data.task_id = TASK ? TASK->taskid : 0; 164 164 165 irq_spinlock_lock(&event->answerbox->irq_lock, 166 true); 167 list_append(&call->ab_link, 168 &event->answerbox->irq_notifs); 169 irq_spinlock_unlock(&event->answerbox->irq_lock, 170 true); 171 172 waitq_wakeup(&event->answerbox->wq, 173 WAKEUP_FIRST); 165 irq_spinlock_lock(&event->answerbox->irq_lock, true); 166 list_append(&call->link, &event->answerbox->irq_notifs); 167 irq_spinlock_unlock(&event->answerbox->irq_lock, true); 168 169 waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST); 174 170 175 171 if (mask) -
kernel/generic/src/ipc/ipc.c
r983cabe8 r3ffd4c3 45 45 #include <ipc/kbox.h> 46 46 #include <ipc/event.h> 47 #include <ipc/sysipc_ops.h>48 #include <ipc/sysipc_priv.h>49 47 #include <errno.h> 50 48 #include <mm/slab.h> … … 73 71 { 74 72 memsetb(call, sizeof(*call), 0); 75 spinlock_initialize(&call->forget_lock, "forget_lock");76 call->active = false;77 call->forget = false;78 73 call->sender = TASK; 79 74 call->buffer = NULL; … … 137 132 * @param phone Initialized phone structure. 138 133 * @param box Initialized answerbox structure. 139 * @return True if the phone was connected, false otherwise. 140 */ 141 bool ipc_phone_connect(phone_t *phone, answerbox_t *box) 142 { 143 bool active; 144 134 * 135 */ 136 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 137 { 145 138 mutex_lock(&phone->lock); 139 140 phone->state = IPC_PHONE_CONNECTED; 141 phone->callee = box; 142 146 143 irq_spinlock_lock(&box->lock, true); 147 148 active = box->active; 149 if (active) { 150 phone->state = IPC_PHONE_CONNECTED; 151 phone->callee = box; 152 list_append(&phone->link, &box->connected_phones); 153 } 154 144 list_append(&phone->link, &box->connected_phones); 155 145 irq_spinlock_unlock(&box->lock, true); 146 156 147 mutex_unlock(&phone->lock); 157 158 return active;159 148 } 160 149 … … 178 167 * 179 168 */ 180 void _ipc_answer_free_call(call_t *call, bool selflocked) 181 { 169 static void _ipc_answer_free_call(call_t *call, bool selflocked) 170 { 171 answerbox_t *callerbox = &call->sender->answerbox; 172 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 173 182 174 /* Count sent answer */ 183 175 irq_spinlock_lock(&TASK->lock, true); 184 176 TASK->ipc_info.answer_sent++; 185 177 irq_spinlock_unlock(&TASK->lock, true); 186 187 spinlock_lock(&call->forget_lock); 188 if (call->forget) { 189 /* This is a forgotten call and call->sender is not valid. */ 190 spinlock_unlock(&call->forget_lock); 191 ipc_call_free(call); 192 return; 193 } else { 194 /* 195 * If the call is still active, i.e. it was answered 196 * in a non-standard way, remove the call from the 197 * sender's active call list. 198 */ 199 if (call->active) { 200 spinlock_lock(&call->sender->active_calls_lock); 201 list_remove(&call->ta_link); 202 spinlock_unlock(&call->sender->active_calls_lock); 178 179 call->flags |= IPC_CALL_ANSWERED; 180 181 if (call->flags & IPC_CALL_FORWARDED) { 182 if (call->caller_phone) { 183 /* Demasquerade the caller phone. */ 184 call->data.phone = call->caller_phone; 203 185 } 204 186 } 205 spinlock_unlock(&call->forget_lock); 206 207 answerbox_t *callerbox = &call->sender->answerbox; 208 bool do_lock = ((!selflocked) || (callerbox != &TASK->answerbox)); 209 210 call->flags |= IPC_CALL_ANSWERED; 211 187 212 188 call->data.task_id = TASK->taskid; 213 189 … … 215 191 irq_spinlock_lock(&callerbox->lock, true); 216 192 217 list_append(&call-> ab_link, &callerbox->answers);193 list_append(&call->link, &callerbox->answers); 218 194 219 195 if (do_lock) … … 233 209 /* Remove from active box */ 234 210 irq_spinlock_lock(&box->lock, true); 235 list_remove(&call-> ab_link);211 list_remove(&call->link); 236 212 irq_spinlock_unlock(&box->lock, true); 237 213 … … 252 228 void ipc_backsend_err(phone_t *phone, call_t *call, sysarg_t err) 253 229 { 254 call->caller_phone = phone;255 230 call->data.phone = phone; 256 231 atomic_inc(&phone->active_calls); 257 258 spinlock_lock(&TASK->active_calls_lock);259 list_append(&call->ta_link, &TASK->active_calls);260 spinlock_unlock(&TASK->active_calls_lock);261 262 232 IPC_SET_RETVAL(call->data, err); 263 233 _ipc_answer_free_call(call, false); … … 280 250 if (!(call->flags & IPC_CALL_FORWARDED)) { 281 251 atomic_inc(&phone->active_calls); 282 283 call->caller_phone = phone;284 call->active = true;285 286 spinlock_lock(&TASK->active_calls_lock);287 list_append(&call->ta_link, &TASK->active_calls);288 spinlock_unlock(&TASK->active_calls_lock);289 290 252 call->data.phone = phone; 291 253 call->data.task_id = TASK->taskid; … … 293 255 294 256 irq_spinlock_lock(&box->lock, true); 295 list_append(&call-> ab_link, &box->calls);257 list_append(&call->link, &box->calls); 296 258 irq_spinlock_unlock(&box->lock, true); 297 259 … … 313 275 if (phone->state != IPC_PHONE_CONNECTED) { 314 276 mutex_unlock(&phone->lock); 315 if (!(call->flags & IPC_CALL_FORWARDED)) { 277 if (call->flags & IPC_CALL_FORWARDED) { 278 IPC_SET_RETVAL(call->data, EFORWARD); 279 _ipc_answer_free_call(call, false); 280 } else { 316 281 if (phone->state == IPC_PHONE_HUNGUP) 317 282 ipc_backsend_err(phone, call, EHANGUP); … … 391 356 TASK->ipc_info.forwarded++; 392 357 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 393 list_remove(&call-> ab_link);358 list_remove(&call->link); 394 359 irq_spinlock_unlock(&oldbox->lock, true); 395 360 396 361 if (mode & IPC_FF_ROUTE_FROM_ME) { 362 if (!call->caller_phone) 363 call->caller_phone = call->data.phone; 397 364 call->data.phone = newphone; 398 365 call->data.task_id = TASK->taskid; … … 439 406 440 407 request = list_get_instance(list_first(&box->irq_notifs), 441 call_t, ab_link);442 list_remove(&request-> ab_link);408 call_t, link); 409 list_remove(&request->link); 443 410 444 411 irq_spinlock_unlock(&box->irq_lock, false); … … 449 416 /* Handle asynchronous answers */ 450 417 request = list_get_instance(list_first(&box->answers), 451 call_t, ab_link);452 list_remove(&request-> ab_link);453 atomic_dec(&request-> caller_phone->active_calls);418 call_t, link); 419 list_remove(&request->link); 420 atomic_dec(&request->data.phone->active_calls); 454 421 } else if (!list_empty(&box->calls)) { 455 422 /* Count received call */ … … 458 425 /* Handle requests */ 459 426 request = list_get_instance(list_first(&box->calls), 460 call_t, ab_link);461 list_remove(&request-> ab_link);427 call_t, link); 428 list_remove(&request->link); 462 429 463 430 /* Append request to dispatch queue */ 464 list_append(&request-> ab_link, &box->dispatched_calls);431 list_append(&request->link, &box->dispatched_calls); 465 432 } else { 466 433 /* This can happen regularly after ipc_cleanup */ … … 482 449 /** Answer all calls from list with EHANGUP answer. 483 450 * 484 * @param box Answerbox with the list.485 451 * @param lst Head of the list to be cleaned up. 486 * /487 void ipc_cleanup_call_list(answerbox_t *box, list_t *lst) 488 { 489 irq_spinlock_lock(&box->lock, true); 452 * 453 */ 454 void ipc_cleanup_call_list(list_t *lst) 455 { 490 456 while (!list_empty(lst)) { 491 call_t *call = list_get_instance(list_first(lst), call_t, 492 ab_link); 493 494 list_remove(&call->ab_link); 495 496 irq_spinlock_unlock(&box->lock, true); 497 498 ipc_data_t old = call->data; 457 call_t *call = list_get_instance(list_first(lst), call_t, link); 458 if (call->buffer) 459 free(call->buffer); 460 461 list_remove(&call->link); 462 499 463 IPC_SET_RETVAL(call->data, EHANGUP); 500 answer_preprocess(call, &old);501 464 _ipc_answer_free_call(call, true); 502 503 irq_spinlock_lock(&box->lock, true); 504 } 505 irq_spinlock_unlock(&box->lock, true); 465 } 506 466 } 507 467 … … 569 529 } 570 530 571 static void ipc_forget_all_active_calls(void)572 {573 call_t *call;574 575 restart:576 spinlock_lock(&TASK->active_calls_lock);577 if (list_empty(&TASK->active_calls)) {578 /*579 * We are done, there are no more active calls.580 * Nota bene: there may still be answers waiting for pick up.581 */582 spinlock_unlock(&TASK->active_calls_lock);583 return;584 }585 586 call = list_get_instance(list_first(&TASK->active_calls), call_t,587 ta_link);588 589 if (!spinlock_trylock(&call->forget_lock)) {590 /*591 * Avoid deadlock and let async_answer() or592 * _ipc_answer_free_call() win the race to dequeue the first593 * call on the list.594 */595 spinlock_unlock(&TASK->active_calls_lock);596 goto restart;597 }598 599 /*600 * Forget the call and donate it to the task which holds up the answer.601 */602 603 call->forget = true;604 call->sender = NULL;605 list_remove(&call->ta_link);606 607 spinlock_unlock(&call->forget_lock);608 spinlock_unlock(&TASK->active_calls_lock);609 610 atomic_dec(&call->caller_phone->active_calls);611 612 sysipc_ops_t *ops = sysipc_ops_get(call->request_method);613 if (ops->request_forget)614 ops->request_forget(call);615 616 goto restart;617 }618 619 /** Wait for all answers to asynchronous calls to arrive. */620 static void ipc_wait_for_all_answered_calls(void)621 {622 call_t *call;623 size_t i;624 625 restart:626 /*627 * Go through all phones, until they are all free.628 * Locking is needed as there may be connection handshakes in progress.629 */630 for (i = 0; i < IPC_MAX_PHONES; i++) {631 phone_t *phone = &TASK->phones[i];632 633 mutex_lock(&phone->lock);634 if ((phone->state == IPC_PHONE_HUNGUP) &&635 (atomic_get(&phone->active_calls) == 0)) {636 phone->state = IPC_PHONE_FREE;637 phone->callee = NULL;638 }639 640 /*641 * We might have had some IPC_PHONE_CONNECTING phones at the642 * beginning of ipc_cleanup(). Depending on whether these were643 * forgotten or answered, they will eventually enter the644 * IPC_PHONE_FREE or IPC_PHONE_CONNECTED states, respectively.645 * In the latter case, the other side may slam the open phones646 * at any time, in which case we will get an IPC_PHONE_SLAMMED647 * phone.648 */649 if ((phone->state == IPC_PHONE_CONNECTED) ||650 (phone->state == IPC_PHONE_SLAMMED)) {651 mutex_unlock(&phone->lock);652 ipc_phone_hangup(phone);653 /*654 * Now there may be one extra active call, which needs655 * to be forgotten.656 */657 ipc_forget_all_active_calls();658 goto restart;659 }660 661 /*662 * If the hangup succeeded, it has sent a HANGUP message, the663 * IPC is now in HUNGUP state, we wait for the reply to come664 */665 if (phone->state != IPC_PHONE_FREE) {666 mutex_unlock(&phone->lock);667 break;668 }669 670 mutex_unlock(&phone->lock);671 }672 673 /* Got into cleanup */674 if (i == IPC_MAX_PHONES)675 return;676 677 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,678 SYNCH_FLAGS_NONE);679 ASSERT(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF));680 ipc_call_free(call);681 goto restart;682 }683 684 531 /** Clean up all IPC communication of the current task. 685 532 * … … 690 537 void ipc_cleanup(void) 691 538 { 692 /*693 * Mark the answerbox as inactive.694 *695 * The main purpose for doing this is to prevent any pending callback696 * connections from getting established beyond this point.697 */698 irq_spinlock_lock(&TASK->answerbox.lock, true);699 TASK->answerbox.active = false;700 irq_spinlock_unlock(&TASK->answerbox.lock, true);701 702 539 /* Disconnect all our phones ('ipc_phone_hangup') */ 703 for (size_t i = 0; i < IPC_MAX_PHONES; i++) 540 size_t i; 541 for (i = 0; i < IPC_MAX_PHONES; i++) 704 542 ipc_phone_hangup(&TASK->phones[i]); 705 543 … … 719 557 720 558 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 721 ipc_cleanup_call_list(&TASK->answerbox, 722 &TASK->answerbox.dispatched_calls); 723 ipc_cleanup_call_list(&TASK->answerbox, &TASK->answerbox.calls); 724 725 ipc_forget_all_active_calls(); 726 ipc_wait_for_all_answered_calls(); 559 irq_spinlock_lock(&TASK->answerbox.lock, true); 560 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 561 ipc_cleanup_call_list(&TASK->answerbox.calls); 562 irq_spinlock_unlock(&TASK->answerbox.lock, true); 563 564 /* Wait for all answers to asynchronous calls to arrive */ 565 while (true) { 566 /* 567 * Go through all phones, until they are all FREE 568 * Locking is not needed, no one else should modify 569 * it when we are in cleanup 570 */ 571 for (i = 0; i < IPC_MAX_PHONES; i++) { 572 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 573 atomic_get(&TASK->phones[i].active_calls) == 0) { 574 TASK->phones[i].state = IPC_PHONE_FREE; 575 TASK->phones[i].callee = NULL; 576 } 577 578 /* 579 * Just for sure, we might have had some 580 * IPC_PHONE_CONNECTING phones 581 */ 582 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 583 ipc_phone_hangup(&TASK->phones[i]); 584 585 /* 586 * If the hangup succeeded, it has sent a HANGUP 587 * message, the IPC is now in HUNGUP state, we 588 * wait for the reply to come 589 */ 590 591 if (TASK->phones[i].state != IPC_PHONE_FREE) 592 break; 593 } 594 595 /* Got into cleanup */ 596 if (i == IPC_MAX_PHONES) 597 break; 598 599 call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 600 SYNCH_FLAGS_NONE); 601 ASSERT((call->flags & IPC_CALL_ANSWERED) || 602 (call->flags & IPC_CALL_NOTIF)); 603 604 ipc_call_free(call); 605 } 727 606 } 728 607 … … 736 615 ipc_answerbox_slab = slab_cache_create("answerbox_t", 737 616 sizeof(answerbox_t), 0, NULL, NULL, 0); 738 }739 740 741 static void ipc_print_call_list(list_t *list)742 {743 list_foreach(*list, cur) {744 call_t *call = list_get_instance(cur, call_t, ab_link);745 746 #ifdef __32_BITS__747 printf("%10p ", call);748 #endif749 750 #ifdef __64_BITS__751 printf("%18p ", call);752 #endif753 754 spinlock_lock(&call->forget_lock);755 756 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun757 " %-6" PRIun " %-6" PRIun " %-7x",758 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),759 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),760 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),761 call->flags);762 763 if (call->forget) {764 printf(" ? (call forgotten)\n");765 } else {766 printf(" %" PRIu64 " (%s)\n",767 call->sender->taskid, call->sender->name);768 }769 770 spinlock_unlock(&call->forget_lock);771 }772 617 } 773 618 … … 843 688 844 689 printf(" --- incomming calls ---\n"); 845 ipc_print_call_list(&task->answerbox.calls); 690 list_foreach(task->answerbox.calls, cur) { 691 call_t *call = list_get_instance(cur, call_t, link); 692 693 #ifdef __32_BITS__ 694 printf("%10p ", call); 695 #endif 696 697 #ifdef __64_BITS__ 698 printf("%18p ", call); 699 #endif 700 701 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 702 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 703 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 704 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 705 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 706 call->flags, call->sender->taskid, call->sender->name); 707 } 708 846 709 printf(" --- dispatched calls ---\n"); 847 ipc_print_call_list(&task->answerbox.dispatched_calls); 710 list_foreach(task->answerbox.dispatched_calls, cur) { 711 call_t *call = list_get_instance(cur, call_t, link); 712 713 #ifdef __32_BITS__ 714 printf("%10p ", call); 715 #endif 716 717 #ifdef __64_BITS__ 718 printf("%18p ", call); 719 #endif 720 721 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 722 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 723 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 724 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 725 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 726 call->flags, call->sender->taskid, call->sender->name); 727 } 728 848 729 printf(" --- incoming answers ---\n"); 849 ipc_print_call_list(&task->answerbox.answers); 730 list_foreach(task->answerbox.answers, cur) { 731 call_t *call = list_get_instance(cur, call_t, link); 732 733 #ifdef __32_BITS__ 734 printf("%10p ", call); 735 #endif 736 737 #ifdef __64_BITS__ 738 printf("%18p ", call); 739 #endif 740 741 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 742 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 743 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 744 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 745 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 746 call->flags, call->sender->taskid, call->sender->name); 747 } 850 748 851 749 irq_spinlock_unlock(&task->answerbox.lock, false); -
kernel/generic/src/ipc/ipcrsc.c
r983cabe8 r3ffd4c3 132 132 #include <ipc/ipcrsc.h> 133 133 #include <debug.h> 134 #include <abi/errno.h>135 134 136 135 /** Find call_t * in call table according to callid. … … 152 151 153 152 list_foreach(TASK->answerbox.dispatched_calls, lst) { 154 call_t *call = list_get_instance(lst, call_t, ab_link);153 call_t *call = list_get_instance(lst, call_t, link); 155 154 if ((sysarg_t) call == callid) { 156 155 result = call; … … 161 160 irq_spinlock_unlock(&TASK->answerbox.lock, true); 162 161 return result; 163 }164 165 /** Get phone from the current task by ID.166 *167 * @param phoneid Phone ID.168 * @param phone Place to store pointer to phone.169 *170 * @return EOK on success, EINVAL if ID is invalid.171 *172 */173 int phone_get(sysarg_t phoneid, phone_t **phone)174 {175 if (phoneid >= IPC_MAX_PHONES)176 return EINVAL;177 178 *phone = &TASK->phones[phoneid];179 return EOK;180 162 } 181 163 … … 241 223 * @param phoneid Phone handle to be connected. 242 224 * @param box Answerbox to which to connect the phone handle. 243 * @return True if the phone was connected, false otherwise.244 225 * 245 226 * The procedure _enforces_ that the user first marks the phone … … 248 229 * 249 230 */ 250 boolphone_connect(int phoneid, answerbox_t *box)231 void phone_connect(int phoneid, answerbox_t *box) 251 232 { 252 233 phone_t *phone = &TASK->phones[phoneid]; 253 234 254 235 ASSERT(phone->state == IPC_PHONE_CONNECTING); 255 returnipc_phone_connect(phone, box);236 ipc_phone_connect(phone, box); 256 237 } 257 238 -
kernel/generic/src/ipc/irq.c
r983cabe8 r3ffd4c3 510 510 { 511 511 irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false); 512 list_append(&call-> ab_link, &irq->notif_cfg.answerbox->irq_notifs);512 list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs); 513 513 irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false); 514 514 -
kernel/generic/src/ipc/kbox.c
r983cabe8 r3ffd4c3 48 48 { 49 49 /* 50 * Not really needed, just to be consistent with the meaning of51 * answerbox_t.active.52 */53 irq_spinlock_lock(&TASK->kb.box.lock, true);54 TASK->kb.box.active = false;55 irq_spinlock_unlock(&TASK->kb.box.lock, true);56 57 /*58 50 * Only hold kb.cleanup_lock while setting kb.finished - 59 51 * this is enough. … … 96 88 97 89 /* Answer all messages in 'calls' and 'dispatched_calls' queues. */ 98 ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.dispatched_calls); 99 ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.calls); 90 irq_spinlock_lock(&TASK->kb.box.lock, true); 91 ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls); 92 ipc_cleanup_call_list(&TASK->kb.box.calls); 93 irq_spinlock_unlock(&TASK->kb.box.lock, true); 100 94 } 101 95 … … 242 236 243 237 /* Connect the newly allocated phone to the kbox */ 244 (void)ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);238 ipc_phone_connect(&TASK->phones[newphid], &task->kb.box); 245 239 246 240 if (task->kb.thread != NULL) { -
kernel/generic/src/ipc/sysipc.c
r983cabe8 r3ffd4c3 34 34 35 35 #include <arch.h> 36 #include <proc/task.h> 37 #include <proc/thread.h> 36 38 #include <errno.h> 37 39 #include <memstr.h> 40 #include <debug.h> 38 41 #include <ipc/ipc.h> 39 42 #include <abi/ipc/methods.h> 40 43 #include <ipc/sysipc.h> 41 #include <ipc/sysipc_ops.h>42 #include <ipc/sysipc_priv.h>43 44 #include <ipc/irq.h> 44 45 #include <ipc/ipcrsc.h> … … 46 47 #include <ipc/kbox.h> 47 48 #include <synch/waitq.h> 49 #include <udebug/udebug_ipc.h> 48 50 #include <arch/interrupt.h> 49 51 #include <syscall/copy.h> 50 52 #include <security/cap.h> 51 53 #include <console/console.h> 54 #include <mm/as.h> 52 55 #include <print.h> 53 56 #include <macros.h> 54 57 58 /** 59 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ 60 * requests. 61 */ 62 #define DATA_XFER_LIMIT (64 * 1024) 63 55 64 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src))) 65 66 /** Get phone from the current task by ID. 67 * 68 * @param phoneid Phone ID. 69 * @param phone Place to store pointer to phone. 70 * 71 * @return EOK on success, EINVAL if ID is invalid. 72 * 73 */ 74 static int phone_get(sysarg_t phoneid, phone_t **phone) 75 { 76 if (phoneid >= IPC_MAX_PHONES) 77 return EINVAL; 78 79 *phone = &TASK->phones[phoneid]; 80 return EOK; 81 } 56 82 57 83 /** Decide if the interface and method is a system method. … … 155 181 * @param olddata Saved data of the request. 156 182 * 157 * @return Return EOK on success or a negative error code. 158 * 159 */ 160 int answer_preprocess(call_t *answer, ipc_data_t *olddata) 161 { 162 int rc = EOK; 163 sysipc_ops_t *ops; 164 165 spinlock_lock(&answer->forget_lock); 166 if (answer->forget) { 167 /* 168 * This is a forgotten call and answer->sender is not valid. 183 * @return Return 0 on success or an error code. 184 * 185 */ 186 static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) 187 { 188 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 189 /* In case of forward, hangup the forwared phone, 190 * not the originator 169 191 */ 170 spinlock_unlock(&answer->forget_lock); 171 172 ops = sysipc_ops_get(answer->request_method); 173 if (ops->answer_cleanup) 174 ops->answer_cleanup(answer, olddata); 175 176 return rc; 177 } else { 178 ASSERT(answer->active); 179 180 /* 181 * Mark the call as inactive to prevent _ipc_answer_free_call() 182 * from attempting to remove the call from the active list 183 * itself. 184 */ 185 answer->active = false; 186 187 /* 188 * Remove the call from the sender's active call list. 189 * We enforce this locking order so that any potential 190 * concurrently executing forget operation is forced to 191 * release its active_calls_lock and lose the race to 192 * forget this soon to be answered call. 193 */ 194 spinlock_lock(&answer->sender->active_calls_lock); 195 list_remove(&answer->ta_link); 196 spinlock_unlock(&answer->sender->active_calls_lock); 197 } 198 spinlock_unlock(&answer->forget_lock); 199 200 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 201 phone_t *phone = answer->caller_phone; 202 mutex_lock(&phone->lock); 203 if (phone->state == IPC_PHONE_CONNECTED) { 204 irq_spinlock_lock(&phone->callee->lock, true); 205 list_remove(&phone->link); 206 phone->state = IPC_PHONE_SLAMMED; 207 irq_spinlock_unlock(&phone->callee->lock, true); 208 } 209 mutex_unlock(&phone->lock); 192 mutex_lock(&answer->data.phone->lock); 193 irq_spinlock_lock(&TASK->answerbox.lock, true); 194 if (answer->data.phone->state == IPC_PHONE_CONNECTED) { 195 list_remove(&answer->data.phone->link); 196 answer->data.phone->state = IPC_PHONE_SLAMMED; 197 } 198 irq_spinlock_unlock(&TASK->answerbox.lock, true); 199 mutex_unlock(&answer->data.phone->lock); 210 200 } 211 201 212 202 if (!olddata) 213 return rc; 214 215 ops = sysipc_ops_get(answer->request_method); 216 if (ops->answer_preprocess) 217 rc = ops->answer_preprocess(answer, olddata); 218 219 return rc; 203 return 0; 204 205 if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECTION_CLONE) { 206 int phoneid = IPC_GET_ARG1(*olddata); 207 phone_t *phone = &TASK->phones[phoneid]; 208 209 if (IPC_GET_RETVAL(answer->data) != EOK) { 210 /* 211 * The recipient of the cloned phone rejected the offer. 212 * In this case, the connection was established at the 213 * request time and therefore we need to slam the phone. 214 * We don't merely hangup as that would result in 215 * sending IPC_M_HUNGUP to the third party on the 216 * other side of the cloned phone. 217 */ 218 mutex_lock(&phone->lock); 219 if (phone->state == IPC_PHONE_CONNECTED) { 220 irq_spinlock_lock(&phone->callee->lock, true); 221 list_remove(&phone->link); 222 phone->state = IPC_PHONE_SLAMMED; 223 irq_spinlock_unlock(&phone->callee->lock, true); 224 } 225 mutex_unlock(&phone->lock); 226 } 227 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CLONE_ESTABLISH) { 228 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 229 230 if (IPC_GET_RETVAL(answer->data) != EOK) { 231 /* 232 * The other party on the cloned phoned rejected our 233 * request for connection on the protocol level. 234 * We need to break the connection without sending 235 * IPC_M_HUNGUP back. 236 */ 237 mutex_lock(&phone->lock); 238 if (phone->state == IPC_PHONE_CONNECTED) { 239 irq_spinlock_lock(&phone->callee->lock, true); 240 list_remove(&phone->link); 241 phone->state = IPC_PHONE_SLAMMED; 242 irq_spinlock_unlock(&phone->callee->lock, true); 243 } 244 mutex_unlock(&phone->lock); 245 } 246 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) { 247 int phoneid = IPC_GET_ARG5(*olddata); 248 249 if (IPC_GET_RETVAL(answer->data) != EOK) { 250 /* The connection was not accepted */ 251 phone_dealloc(phoneid); 252 } else { 253 /* The connection was accepted */ 254 phone_connect(phoneid, &answer->sender->answerbox); 255 /* Set 'phone hash' as arg5 of response */ 256 IPC_SET_ARG5(answer->data, 257 (sysarg_t) &TASK->phones[phoneid]); 258 } 259 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) { 260 /* If the users accepted call, connect */ 261 if (IPC_GET_RETVAL(answer->data) == EOK) { 262 ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), 263 &TASK->answerbox); 264 } 265 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) { 266 if (!IPC_GET_RETVAL(answer->data)) { 267 /* Accepted, handle as_area receipt */ 268 269 irq_spinlock_lock(&answer->sender->lock, true); 270 as_t *as = answer->sender->as; 271 irq_spinlock_unlock(&answer->sender->lock, true); 272 273 uintptr_t dst_base = (uintptr_t) -1; 274 int rc = as_area_share(as, IPC_GET_ARG1(*olddata), 275 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 276 &dst_base, IPC_GET_ARG1(answer->data)); 277 278 if (rc == EOK) 279 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 280 &dst_base, sizeof(dst_base)); 281 282 IPC_SET_RETVAL(answer->data, rc); 283 return rc; 284 } 285 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) { 286 if (!IPC_GET_RETVAL(answer->data)) { 287 irq_spinlock_lock(&answer->sender->lock, true); 288 as_t *as = answer->sender->as; 289 irq_spinlock_unlock(&answer->sender->lock, true); 290 291 uintptr_t dst_base = (uintptr_t) -1; 292 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 293 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data), 294 &dst_base, IPC_GET_ARG3(answer->data)); 295 IPC_SET_ARG4(answer->data, dst_base); 296 IPC_SET_RETVAL(answer->data, rc); 297 } 298 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) { 299 ASSERT(!answer->buffer); 300 if (!IPC_GET_RETVAL(answer->data)) { 301 /* The recipient agreed to send data. */ 302 uintptr_t src = IPC_GET_ARG1(answer->data); 303 uintptr_t dst = IPC_GET_ARG1(*olddata); 304 size_t max_size = IPC_GET_ARG2(*olddata); 305 size_t size = IPC_GET_ARG2(answer->data); 306 if (size && size <= max_size) { 307 /* 308 * Copy the destination VA so that this piece of 309 * information is not lost. 310 */ 311 IPC_SET_ARG1(answer->data, dst); 312 313 answer->buffer = malloc(size, 0); 314 int rc = copy_from_uspace(answer->buffer, 315 (void *) src, size); 316 if (rc) { 317 IPC_SET_RETVAL(answer->data, rc); 318 free(answer->buffer); 319 answer->buffer = NULL; 320 } 321 } else if (!size) { 322 IPC_SET_RETVAL(answer->data, EOK); 323 } else { 324 IPC_SET_RETVAL(answer->data, ELIMIT); 325 } 326 } 327 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) { 328 ASSERT(answer->buffer); 329 if (!IPC_GET_RETVAL(answer->data)) { 330 /* The recipient agreed to receive data. */ 331 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 332 size_t size = (size_t)IPC_GET_ARG2(answer->data); 333 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 334 335 if (size <= max_size) { 336 int rc = copy_to_uspace((void *) dst, 337 answer->buffer, size); 338 if (rc) 339 IPC_SET_RETVAL(answer->data, rc); 340 } else { 341 IPC_SET_RETVAL(answer->data, ELIMIT); 342 } 343 } 344 free(answer->buffer); 345 answer->buffer = NULL; 346 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) { 347 if (!IPC_GET_RETVAL(answer->data)) { 348 /* The recipient authorized the change of state. */ 349 phone_t *recipient_phone; 350 task_t *other_task_s; 351 task_t *other_task_r; 352 int rc; 353 354 rc = phone_get(IPC_GET_ARG1(answer->data), 355 &recipient_phone); 356 if (rc != EOK) { 357 IPC_SET_RETVAL(answer->data, ENOENT); 358 return ENOENT; 359 } 360 361 mutex_lock(&recipient_phone->lock); 362 if (recipient_phone->state != IPC_PHONE_CONNECTED) { 363 mutex_unlock(&recipient_phone->lock); 364 IPC_SET_RETVAL(answer->data, EINVAL); 365 return EINVAL; 366 } 367 368 other_task_r = recipient_phone->callee->task; 369 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 370 371 /* 372 * See if both the sender and the recipient meant the 373 * same third party task. 374 */ 375 if (other_task_r != other_task_s) { 376 IPC_SET_RETVAL(answer->data, EINVAL); 377 rc = EINVAL; 378 } else { 379 rc = event_task_notify_5(other_task_r, 380 EVENT_TASK_STATE_CHANGE, false, 381 IPC_GET_ARG1(*olddata), 382 IPC_GET_ARG2(*olddata), 383 IPC_GET_ARG3(*olddata), 384 LOWER32(olddata->task_id), 385 UPPER32(olddata->task_id)); 386 IPC_SET_RETVAL(answer->data, rc); 387 } 388 389 mutex_unlock(&recipient_phone->lock); 390 return rc; 391 } 392 } 393 394 return 0; 395 } 396 397 static void phones_lock(phone_t *p1, phone_t *p2) 398 { 399 if (p1 < p2) { 400 mutex_lock(&p1->lock); 401 mutex_lock(&p2->lock); 402 } else if (p1 > p2) { 403 mutex_lock(&p2->lock); 404 mutex_lock(&p1->lock); 405 } else 406 mutex_lock(&p1->lock); 407 } 408 409 static void phones_unlock(phone_t *p1, phone_t *p2) 410 { 411 mutex_unlock(&p1->lock); 412 if (p1 != p2) 413 mutex_unlock(&p2->lock); 220 414 } 221 415 … … 230 424 static int request_preprocess(call_t *call, phone_t *phone) 231 425 { 232 int rc = EOK; 233 234 call->request_method = IPC_GET_IMETHOD(call->data); 235 236 sysipc_ops_t *ops = sysipc_ops_get(call->request_method); 237 if (ops->request_preprocess) 238 rc = ops->request_preprocess(call, phone); 239 240 return rc; 426 switch (IPC_GET_IMETHOD(call->data)) { 427 case IPC_M_CONNECTION_CLONE: { 428 phone_t *cloned_phone; 429 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 430 return ENOENT; 431 432 phones_lock(cloned_phone, phone); 433 434 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 435 phone->state != IPC_PHONE_CONNECTED) { 436 phones_unlock(cloned_phone, phone); 437 return EINVAL; 438 } 439 440 /* 441 * We can be pretty sure now that both tasks exist and we are 442 * connected to them. As we continue to hold the phone locks, 443 * we are effectively preventing them from finishing their 444 * potential cleanup. 445 * 446 */ 447 int newphid = phone_alloc(phone->callee->task); 448 if (newphid < 0) { 449 phones_unlock(cloned_phone, phone); 450 return ELIMIT; 451 } 452 453 ipc_phone_connect(&phone->callee->task->phones[newphid], 454 cloned_phone->callee); 455 phones_unlock(cloned_phone, phone); 456 457 /* Set the new phone for the callee. */ 458 IPC_SET_ARG1(call->data, newphid); 459 break; 460 } 461 case IPC_M_CLONE_ESTABLISH: 462 IPC_SET_ARG5(call->data, (sysarg_t) phone); 463 break; 464 case IPC_M_CONNECT_ME_TO: { 465 int newphid = phone_alloc(TASK); 466 if (newphid < 0) 467 return ELIMIT; 468 469 /* Set arg5 for server */ 470 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]); 471 call->flags |= IPC_CALL_CONN_ME_TO; 472 call->priv = newphid; 473 break; 474 } 475 case IPC_M_SHARE_OUT: { 476 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 477 if (!size) 478 return EPERM; 479 480 IPC_SET_ARG2(call->data, size); 481 break; 482 } 483 case IPC_M_DATA_READ: { 484 size_t size = IPC_GET_ARG2(call->data); 485 if (size > DATA_XFER_LIMIT) { 486 int flags = IPC_GET_ARG3(call->data); 487 if (flags & IPC_XF_RESTRICT) 488 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT); 489 else 490 return ELIMIT; 491 } 492 break; 493 } 494 case IPC_M_DATA_WRITE: { 495 uintptr_t src = IPC_GET_ARG1(call->data); 496 size_t size = IPC_GET_ARG2(call->data); 497 498 if (size > DATA_XFER_LIMIT) { 499 int flags = IPC_GET_ARG3(call->data); 500 if (flags & IPC_XF_RESTRICT) { 501 size = DATA_XFER_LIMIT; 502 IPC_SET_ARG2(call->data, size); 503 } else 504 return ELIMIT; 505 } 506 507 call->buffer = (uint8_t *) malloc(size, 0); 508 int rc = copy_from_uspace(call->buffer, (void *) src, size); 509 if (rc != 0) { 510 free(call->buffer); 511 return rc; 512 } 513 514 break; 515 } 516 case IPC_M_STATE_CHANGE_AUTHORIZE: { 517 phone_t *sender_phone; 518 task_t *other_task_s; 519 520 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK) 521 return ENOENT; 522 523 mutex_lock(&sender_phone->lock); 524 if (sender_phone->state != IPC_PHONE_CONNECTED) { 525 mutex_unlock(&sender_phone->lock); 526 return EINVAL; 527 } 528 529 other_task_s = sender_phone->callee->task; 530 531 mutex_unlock(&sender_phone->lock); 532 533 /* Remember the third party task hash. */ 534 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 535 break; 536 } 537 #ifdef CONFIG_UDEBUG 538 case IPC_M_DEBUG: 539 return udebug_request_preprocess(call, phone); 540 #endif 541 default: 542 break; 543 } 544 545 return 0; 241 546 } 242 547 … … 256 561 IPC_SET_RETVAL(call->data, EFORWARD); 257 562 258 sysipc_ops_t *ops = sysipc_ops_get(call->request_method); 259 if (ops->answer_process) 260 (void) ops->answer_process(call); 261 } 262 563 if (call->flags & IPC_CALL_CONN_ME_TO) { 564 if (IPC_GET_RETVAL(call->data)) 565 phone_dealloc(call->priv); 566 else 567 IPC_SET_ARG5(call->data, call->priv); 568 } 569 570 if (call->buffer) { 571 /* 572 * This must be an affirmative answer to IPC_M_DATA_READ 573 * or IPC_M_DEBUG/UDEBUG_M_MEM_READ... 574 * 575 */ 576 uintptr_t dst = IPC_GET_ARG1(call->data); 577 size_t size = IPC_GET_ARG2(call->data); 578 int rc = copy_to_uspace((void *) dst, call->buffer, size); 579 if (rc) 580 IPC_SET_RETVAL(call->data, rc); 581 free(call->buffer); 582 call->buffer = NULL; 583 } 584 } 263 585 264 586 /** Do basic kernel processing of received call request. … … 273 595 static int process_request(answerbox_t *box, call_t *call) 274 596 { 275 int rc = EOK; 276 277 sysipc_ops_t *ops = sysipc_ops_get(call->request_method); 278 if (ops->request_process) 279 rc = ops->request_process(call, box); 280 281 return rc; 597 if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) { 598 int phoneid = phone_alloc(TASK); 599 if (phoneid < 0) { /* Failed to allocate phone */ 600 IPC_SET_RETVAL(call->data, ELIMIT); 601 ipc_answer(box, call); 602 return -1; 603 } 604 605 IPC_SET_ARG5(call->data, phoneid); 606 } 607 608 switch (IPC_GET_IMETHOD(call->data)) { 609 case IPC_M_DEBUG: 610 return -1; 611 default: 612 break; 613 } 614 615 return 0; 282 616 } 283 617 … … 411 745 { 412 746 call_t *call = get_call(callid); 413 phone_t *phone;414 bool need_old = answer_need_old(call);415 bool after_forward = false;416 ipc_data_t old;417 int rc;418 419 747 if (!call) 420 748 return ENOENT; 421 422 if (need_old)423 old = call->data;424 749 750 call->flags |= IPC_CALL_FORWARDED; 751 752 phone_t *phone; 425 753 if (phone_get(phoneid, &phone) != EOK) { 426 rc = ENOENT; 427 goto error; 754 IPC_SET_RETVAL(call->data, EFORWARD); 755 ipc_answer(&TASK->answerbox, call); 756 return ENOENT; 428 757 } 429 758 430 759 if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) { 431 rc = EPERM; 432 goto error; 433 } 434 435 call->flags |= IPC_CALL_FORWARDED; 760 IPC_SET_RETVAL(call->data, EFORWARD); 761 ipc_answer(&TASK->answerbox, call); 762 return EPERM; 763 } 436 764 437 765 /* … … 469 797 } 470 798 471 rc = ipc_forward(call, phone, &TASK->answerbox, mode); 472 if (rc != EOK) { 473 after_forward = true; 474 goto error; 475 } 476 477 return EOK; 478 479 error: 480 IPC_SET_RETVAL(call->data, EFORWARD); 481 (void) answer_preprocess(call, need_old ? &old : NULL); 482 if (after_forward) 483 _ipc_answer_free_call(call, false); 484 else 485 ipc_answer(&TASK->answerbox, call); 486 487 return rc; 799 return ipc_forward(call, phone, &TASK->answerbox, mode); 488 800 } 489 801 -
kernel/generic/src/proc/task.c
r983cabe8 r3ffd4c3 162 162 for (i = 0; i < IPC_MAX_PHONES; i++) 163 163 ipc_phone_init(&task->phones[i]); 164 165 spinlock_initialize(&task->active_calls_lock, "active_calls_lock");166 list_initialize(&task->active_calls);167 164 168 165 #ifdef CONFIG_UDEBUG … … 206 203 event_task_init(task); 207 204 208 task->answerbox.active = true;209 210 205 #ifdef CONFIG_UDEBUG 211 206 /* Init debugging stuff */ … … 213 208 214 209 /* Init kbox stuff */ 215 task->kb.box.active = true;216 210 task->kb.finished = false; 217 211 #endif … … 219 213 if ((ipc_phone_0) && 220 214 (container_check(ipc_phone_0->task->container, task->container))) 221 (void)ipc_phone_connect(&task->phones[0], ipc_phone_0);215 ipc_phone_connect(&task->phones[0], ipc_phone_0); 222 216 223 217 btree_create(&task->futexes);
Note:
See TracChangeset
for help on using the changeset viewer.
