Changeset a35b458 in mainline for kernel/generic/src/ipc
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- Location:
- kernel/generic/src/ipc
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/event.c
r3061bc1 ra35b458 61 61 { 62 62 assert(evno < EVENT_TASK_END); 63 63 64 64 event_t *event; 65 65 66 66 if (evno < EVENT_END) 67 67 event = &events[(event_type_t) evno]; 68 68 else 69 69 event = &task->events[(event_task_type_t) evno - EVENT_END]; 70 70 71 71 return event; 72 72 } … … 96 96 for (unsigned int i = 0; i < EVENT_END; i++) { 97 97 spinlock_lock(&events[i].lock); 98 98 99 99 if (events[i].answerbox == answerbox) { 100 100 events[i].answerbox = NULL; … … 103 103 events[i].masked = false; 104 104 } 105 105 106 106 spinlock_unlock(&events[i].lock); 107 107 } … … 125 125 { 126 126 assert(evno < EVENT_END); 127 127 128 128 _event_set_unmask_callback(evno2event(evno, NULL), callback); 129 129 } … … 134 134 assert(evno >= (int) EVENT_END); 135 135 assert(evno < EVENT_TASK_END); 136 136 137 137 _event_set_unmask_callback(evno2event(evno, task), callback); 138 138 } … … 144 144 145 145 spinlock_lock(&event->lock); 146 146 147 147 if (event->answerbox != NULL) { 148 148 if (!event->masked) { 149 149 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 150 150 151 151 if (call) { 152 152 call->flags |= IPC_CALL_NOTIF; 153 153 call->priv = ++event->counter; 154 154 155 155 IPC_SET_IMETHOD(call->data, event->imethod); 156 156 IPC_SET_ARG1(call->data, a1); … … 159 159 IPC_SET_ARG4(call->data, a4); 160 160 IPC_SET_ARG5(call->data, a5); 161 161 162 162 call->data.task_id = TASK ? TASK->taskid : 0; 163 163 164 164 irq_spinlock_lock(&event->answerbox->irq_lock, 165 165 true); … … 168 168 irq_spinlock_unlock(&event->answerbox->irq_lock, 169 169 true); 170 170 171 171 waitq_wakeup(&event->answerbox->wq, 172 172 WAKEUP_FIRST); 173 173 174 174 if (mask) 175 175 event->masked = true; 176 176 177 177 res = EOK; 178 178 } else … … 182 182 } else 183 183 res = ENOENT; 184 184 185 185 spinlock_unlock(&event->lock); 186 186 return res; … … 210 210 { 211 211 assert(evno < EVENT_END); 212 212 213 213 return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5); 214 214 } … … 239 239 assert(evno >= (int) EVENT_END); 240 240 assert(evno < EVENT_TASK_END); 241 241 242 242 return event_enqueue(evno2event(evno, task), mask, a1, a2, a3, a4, a5); 243 243 } … … 259 259 { 260 260 errno_t res; 261 262 spinlock_lock(&event->lock); 263 261 262 spinlock_lock(&event->lock); 263 264 264 if (event->answerbox == NULL) { 265 265 event->answerbox = answerbox; … … 270 270 } else 271 271 res = EEXIST; 272 273 spinlock_unlock(&event->lock); 274 272 273 spinlock_unlock(&event->lock); 274 275 275 return res; 276 276 } … … 289 289 { 290 290 errno_t res; 291 292 spinlock_lock(&event->lock); 293 291 292 spinlock_lock(&event->lock); 293 294 294 if (event->answerbox == answerbox) { 295 295 event->answerbox = NULL; … … 300 300 } else 301 301 res = ENOENT; 302 303 spinlock_unlock(&event->lock); 304 302 303 spinlock_unlock(&event->lock); 304 305 305 return res; 306 306 } … … 317 317 event_callback_t callback = event->unmask_callback; 318 318 spinlock_unlock(&event->lock); 319 319 320 320 /* 321 321 * Check if there is an unmask callback … … 342 342 if (evno >= EVENT_TASK_END) 343 343 return ELIMIT; 344 344 345 345 return (sys_errno_t) event_subscribe(evno2event(evno, TASK), 346 346 (sysarg_t) imethod, &TASK->answerbox); … … 361 361 if (evno >= EVENT_TASK_END) 362 362 return ELIMIT; 363 363 364 364 return (sys_errno_t) event_unsubscribe(evno2event(evno, TASK), 365 365 &TASK->answerbox); … … 383 383 if (evno >= EVENT_TASK_END) 384 384 return ELIMIT; 385 385 386 386 event_unmask(evno2event(evno, TASK)); 387 387 -
kernel/generic/src/ipc/ipc.c
r3061bc1 ra35b458 127 127 kobject_initialize(kobj, KOBJECT_TYPE_CALL, call, &call_kobject_ops); 128 128 call->kobject = kobj; 129 129 130 130 return call; 131 131 } … … 212 212 answerbox_t *mybox = slab_alloc(answerbox_cache, 0); 213 213 ipc_answerbox_init(mybox, TASK); 214 214 215 215 /* We will receive data in a special box. */ 216 216 request->callerbox = mybox; 217 217 218 218 errno_t rc = ipc_call(phone, request); 219 219 if (rc != EOK) { … … 247 247 ipc_forget_call(request); /* releases locks */ 248 248 rc = EINTR; 249 249 250 250 } else { 251 251 spinlock_unlock(&TASK->active_calls_lock); … … 264 264 } 265 265 assert(!answer || request == answer); 266 266 267 267 slab_free(answerbox_cache, mybox); 268 268 return rc; … … 305 305 &call->sender->answerbox; 306 306 bool do_lock = ((!selflocked) || (callerbox != &TASK->answerbox)); 307 307 308 308 call->flags |= IPC_CALL_ANSWERED; 309 309 310 310 call->data.task_id = TASK->taskid; 311 311 312 312 if (do_lock) 313 313 irq_spinlock_lock(&callerbox->lock, true); 314 314 315 315 list_append(&call->ab_link, &callerbox->answers); 316 316 317 317 if (do_lock) 318 318 irq_spinlock_unlock(&callerbox->lock, true); 319 319 320 320 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 321 321 } … … 333 333 list_remove(&call->ab_link); 334 334 irq_spinlock_unlock(&box->lock, true); 335 335 336 336 /* Send back answer */ 337 337 _ipc_answer_free_call(call, false); … … 395 395 caller->ipc_info.call_sent++; 396 396 irq_spinlock_unlock(&caller->lock, true); 397 397 398 398 if (!(call->flags & IPC_CALL_FORWARDED)) 399 399 _ipc_call_actions_internal(phone, call, preforget); 400 400 401 401 irq_spinlock_lock(&box->lock, true); 402 402 list_append(&call->ab_link, &box->calls); 403 403 irq_spinlock_unlock(&box->lock, true); 404 404 405 405 waitq_wakeup(&box->wq, WAKEUP_FIRST); 406 406 } … … 426 426 ipc_backsend_err(phone, call, ENOENT); 427 427 } 428 428 429 429 return ENOENT; 430 430 } 431 431 432 432 answerbox_t *box = phone->callee; 433 433 _ipc_call(phone, box, call, false); 434 434 435 435 mutex_unlock(&phone->lock); 436 436 return 0; … … 457 457 return EINVAL; 458 458 } 459 459 460 460 answerbox_t *box = phone->callee; 461 461 if (phone->state != IPC_PHONE_SLAMMED) { … … 467 467 /* Drop the answerbox reference */ 468 468 kobject_put(phone->kobject); 469 469 470 470 call_t *call = ipc_call_alloc(0); 471 471 IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP); … … 474 474 _ipc_call(phone, box, call, false); 475 475 } 476 476 477 477 phone->state = IPC_PHONE_HUNGUP; 478 478 mutex_unlock(&phone->lock); 479 479 480 480 return EOK; 481 481 } … … 504 504 list_remove(&call->ab_link); 505 505 irq_spinlock_unlock(&oldbox->lock, true); 506 506 507 507 if (mode & IPC_FF_ROUTE_FROM_ME) { 508 508 call->data.phone = newphone; 509 509 call->data.task_id = TASK->taskid; 510 510 } 511 511 512 512 return ipc_call(newphone, call); 513 513 } … … 536 536 uint64_t call_cnt = 0; 537 537 errno_t rc; 538 538 539 539 restart: 540 540 rc = waitq_sleep_timeout(&box->wq, usec, flags, NULL); 541 541 if (rc != EOK) 542 542 return NULL; 543 543 544 544 irq_spinlock_lock(&box->lock, true); 545 545 if (!list_empty(&box->irq_notifs)) { 546 546 /* Count received IRQ notification */ 547 547 irq_cnt++; 548 548 549 549 irq_spinlock_lock(&box->irq_lock, false); 550 550 551 551 request = list_get_instance(list_first(&box->irq_notifs), 552 552 call_t, ab_link); 553 553 list_remove(&request->ab_link); 554 554 555 555 irq_spinlock_unlock(&box->irq_lock, false); 556 556 } else if (!list_empty(&box->answers)) { 557 557 /* Count received answer */ 558 558 answer_cnt++; 559 559 560 560 /* Handle asynchronous answers */ 561 561 request = list_get_instance(list_first(&box->answers), … … 566 566 /* Count received call */ 567 567 call_cnt++; 568 568 569 569 /* Handle requests */ 570 570 request = list_get_instance(list_first(&box->calls), 571 571 call_t, ab_link); 572 572 list_remove(&request->ab_link); 573 573 574 574 /* Append request to dispatch queue */ 575 575 list_append(&request->ab_link, &box->dispatched_calls); … … 579 579 goto restart; 580 580 } 581 581 582 582 irq_spinlock_pass(&box->lock, &TASK->lock); 583 583 584 584 TASK->ipc_info.irq_notif_received += irq_cnt; 585 585 TASK->ipc_info.answer_received += answer_cnt; 586 586 TASK->ipc_info.call_received += call_cnt; 587 587 588 588 irq_spinlock_unlock(&TASK->lock, true); 589 589 590 590 return request; 591 591 } … … 602 602 call_t *call = list_get_instance(list_first(lst), call_t, 603 603 ab_link); 604 604 605 605 list_remove(&call->ab_link); 606 606 … … 631 631 phone_t *phone; 632 632 DEADLOCK_PROBE_INIT(p_phonelck); 633 633 634 634 /* Disconnect all phones connected to our answerbox */ 635 635 restart_phones: … … 643 643 goto restart_phones; 644 644 } 645 645 646 646 /* Disconnect phone */ 647 647 assert(phone->state == IPC_PHONE_CONNECTED); 648 648 649 649 list_remove(&phone->link); 650 650 phone->state = IPC_PHONE_SLAMMED; 651 651 652 652 if (notify_box) { 653 653 task_hold(phone->caller); … … 671 671 672 672 kobject_put(phone->kobject); 673 673 674 674 /* Must start again */ 675 675 goto restart_phones; 676 676 } 677 677 678 678 mutex_unlock(&phone->lock); 679 679 kobject_put(phone->kobject); 680 680 } 681 681 682 682 irq_spinlock_unlock(&box->lock, true); 683 683 } … … 727 727 return; 728 728 } 729 729 730 730 call = list_get_instance(list_first(&TASK->active_calls), call_t, 731 731 ta_link); … … 811 811 if (restart) 812 812 goto restart; 813 813 814 814 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 815 815 SYNCH_FLAGS_NONE); … … 872 872 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 873 873 phone_cap_cleanup_cb, NULL); 874 874 875 875 /* Unsubscribe from any event notifications. */ 876 876 event_cleanup_answerbox(&TASK->answerbox); 877 877 878 878 /* Disconnect all connected IRQs */ 879 879 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_IRQ, irq_cap_cleanup_cb, 880 880 NULL); 881 881 882 882 /* Disconnect all phones connected to our regular answerbox */ 883 883 ipc_answerbox_slam_phones(&TASK->answerbox, false); 884 884 885 885 #ifdef CONFIG_UDEBUG 886 886 /* Clean up kbox thread and communications */ … … 891 891 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_CALL, call_cap_cleanup_cb, 892 892 NULL); 893 893 894 894 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 895 895 ipc_cleanup_call_list(&TASK->answerbox, &TASK->answerbox.calls); 896 896 ipc_cleanup_call_list(&TASK->answerbox, 897 897 &TASK->answerbox.dispatched_calls); 898 898 899 899 ipc_forget_all_active_calls(); 900 900 ipc_wait_for_all_answered_calls(); … … 921 921 printf("%10p ", call); 922 922 #endif 923 923 924 924 #ifdef __64_BITS__ 925 925 printf("%18p ", call); 926 926 #endif 927 927 928 928 spinlock_lock(&call->forget_lock); 929 929 … … 954 954 printf("%-11d %7" PRIun " ", cap->handle, 955 955 atomic_get(&phone->active_calls)); 956 956 957 957 switch (phone->state) { 958 958 case IPC_PHONE_CONNECTING: … … 973 973 break; 974 974 } 975 975 976 976 printf("\n"); 977 977 } … … 996 996 task_hold(task); 997 997 irq_spinlock_unlock(&tasks_lock, true); 998 998 999 999 printf("[phone cap] [calls] [state\n"); 1000 1000 1001 1001 caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE, 1002 1002 print_task_phone_cb, NULL); 1003 1003 1004 1004 irq_spinlock_lock(&task->lock, true); 1005 1005 irq_spinlock_lock(&task->answerbox.lock, false); 1006 1006 1007 1007 #ifdef __32_BITS__ 1008 1008 printf("[call id ] [method] [arg1] [arg2] [arg3] [arg4] [arg5]" 1009 1009 " [flags] [sender\n"); 1010 1010 #endif 1011 1011 1012 1012 #ifdef __64_BITS__ 1013 1013 printf("[call id ] [method] [arg1] [arg2] [arg3] [arg4]" 1014 1014 " [arg5] [flags] [sender\n"); 1015 1015 #endif 1016 1016 1017 1017 printf(" --- incomming calls ---\n"); 1018 1018 ipc_print_call_list(&task->answerbox.calls); … … 1021 1021 printf(" --- incoming answers ---\n"); 1022 1022 ipc_print_call_list(&task->answerbox.answers); 1023 1023 1024 1024 irq_spinlock_unlock(&task->answerbox.lock, false); 1025 1025 irq_spinlock_unlock(&task->lock, true); -
kernel/generic/src/ipc/ipcrsc.c
r3061bc1 ra35b458 193 193 &phone_kobject_ops); 194 194 phone->kobject = kobject; 195 195 196 196 cap_publish(task, handle, kobject); 197 197 … … 213 213 if (!kobj) 214 214 return; 215 215 216 216 assert(kobj->phone); 217 217 assert(kobj->phone->state == IPC_PHONE_CONNECTING); 218 218 219 219 kobject_put(kobj); 220 220 cap_free(TASK, handle); … … 232 232 if (!phone_obj) 233 233 return false; 234 234 235 235 assert(phone_obj->phone->state == IPC_PHONE_CONNECTING); 236 236 237 237 /* Hand over phone_obj reference to the answerbox */ 238 238 return ipc_phone_connect(phone_obj->phone, box); -
kernel/generic/src/ipc/irq.c
r3061bc1 ra35b458 85 85 for (size_t i = 0; i < rangecount; i++) 86 86 pbase[i] = ranges[i].base; 87 87 88 88 /* Map the PIO ranges into the kernel virtual address space. */ 89 89 for (size_t i = 0; i < rangecount; i++) { … … 100 100 } 101 101 } 102 102 103 103 /* Rewrite the IRQ code addresses from physical to kernel virtual. */ 104 104 for (size_t i = 0; i < cmdcount; i++) { 105 105 uintptr_t addr; 106 106 size_t size; 107 107 108 108 /* Process only commands that use an address. */ 109 109 switch (cmds[i].cmd) { … … 127 127 continue; 128 128 } 129 129 130 130 addr = (uintptr_t) cmds[i].addr; 131 131 132 132 size_t j; 133 133 for (j = 0; j < rangecount; j++) { … … 135 135 if (!iswithin(pbase[j], ranges[j].size, addr, size)) 136 136 continue; 137 137 138 138 /* Switch the command to a kernel virtual address. */ 139 139 addr -= pbase[j]; 140 140 addr += ranges[j].base; 141 141 142 142 cmds[i].addr = (void *) addr; 143 143 break; 144 144 } 145 145 146 146 if (j == rangecount) { 147 147 /* … … 154 154 } 155 155 } 156 156 157 157 free(pbase); 158 158 return EOK; … … 172 172 if (cmds[i].cmd >= CMD_LAST) 173 173 return EINVAL; 174 174 175 175 if (cmds[i].srcarg >= IPC_CALL_LEN) 176 176 return EINVAL; 177 177 178 178 if (cmds[i].dstarg >= IPC_CALL_LEN) 179 179 return EINVAL; 180 180 181 181 switch (cmds[i].cmd) { 182 182 case CMD_PREDICATE: … … 188 188 if (i + cmds[i].value > cmdcount) 189 189 return EINVAL; 190 190 191 191 break; 192 192 default: … … 194 194 } 195 195 } 196 196 197 197 return EOK; 198 198 } … … 224 224 irq_pio_range_t *ranges = NULL; 225 225 irq_cmd_t *cmds = NULL; 226 226 227 227 irq_code_t *code = malloc(sizeof(*code), 0); 228 228 errno_t rc = copy_from_uspace(code, ucode, sizeof(*code)); 229 229 if (rc != EOK) 230 230 goto error; 231 231 232 232 if ((code->rangecount > IRQ_MAX_RANGE_COUNT) || 233 233 (code->cmdcount > IRQ_MAX_PROG_SIZE)) 234 234 goto error; 235 235 236 236 ranges = malloc(sizeof(code->ranges[0]) * code->rangecount, 0); 237 237 rc = copy_from_uspace(ranges, code->ranges, … … 239 239 if (rc != EOK) 240 240 goto error; 241 241 242 242 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 243 243 rc = copy_from_uspace(cmds, code->cmds, … … 245 245 if (rc != EOK) 246 246 goto error; 247 247 248 248 rc = code_check(cmds, code->cmdcount); 249 249 if (rc != EOK) 250 250 goto error; 251 251 252 252 rc = ranges_map_and_apply(ranges, code->rangecount, cmds, 253 253 code->cmdcount); 254 254 if (rc != EOK) 255 255 goto error; 256 256 257 257 code->ranges = ranges; 258 258 code->cmds = cmds; 259 259 260 260 return code; 261 261 262 262 error: 263 263 if (cmds) 264 264 free(cmds); 265 265 266 266 if (ranges) 267 267 free(ranges); 268 268 269 269 free(code); 270 270 return NULL; … … 275 275 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 276 276 irq_spinlock_lock(&irq->lock, false); 277 277 278 278 if (irq->notif_cfg.hashed_in) { 279 279 /* Remove the IRQ from the uspace IRQ hash table. */ … … 318 318 if ((inr < 0) || (inr > last_inr)) 319 319 return ELIMIT; 320 320 321 321 irq_code_t *code; 322 322 if (ucode) { … … 326 326 } else 327 327 code = NULL; 328 328 329 329 /* 330 330 * Allocate and populate the IRQ kernel object. … … 334 334 if (rc != EOK) 335 335 return rc; 336 336 337 337 rc = copy_to_uspace(uspace_handle, &handle, sizeof(cap_handle_t)); 338 338 if (rc != EOK) { … … 353 353 return ENOMEM; 354 354 } 355 355 356 356 irq_initialize(irq); 357 357 irq->inr = inr; … … 363 363 irq->notif_cfg.code = code; 364 364 irq->notif_cfg.counter = 0; 365 365 366 366 /* 367 367 * Insert the IRQ structure into the uspace IRQ hash table. … … 369 369 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 370 370 irq_spinlock_lock(&irq->lock, false); 371 371 372 372 irq->notif_cfg.hashed_in = true; 373 373 hash_table_insert(&irq_uspace_hash_table, &irq->link); 374 374 375 375 irq_spinlock_unlock(&irq->lock, false); 376 376 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); … … 378 378 kobject_initialize(kobject, KOBJECT_TYPE_IRQ, irq, &irq_kobject_ops); 379 379 cap_publish(TASK, handle, kobject); 380 380 381 381 return EOK; 382 382 } … … 395 395 if (!kobj) 396 396 return ENOENT; 397 397 398 398 assert(kobj->irq->notif_cfg.answerbox == box); 399 399 … … 402 402 kobject_put(kobj); 403 403 cap_free(TASK, handle); 404 404 405 405 return EOK; 406 406 } … … 419 419 list_append(&call->ab_link, &irq->notif_cfg.answerbox->irq_notifs); 420 420 irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false); 421 421 422 422 waitq_wakeup(&irq->notif_cfg.answerbox->wq, WAKEUP_FIRST); 423 423 } … … 435 435 irq_code_t *code = irq->notif_cfg.code; 436 436 uint32_t *scratch = irq->notif_cfg.scratch; 437 437 438 438 if (!irq->notif_cfg.notify) 439 439 return IRQ_DECLINE; 440 440 441 441 if (!code) 442 442 return IRQ_DECLINE; 443 443 444 444 for (size_t i = 0; i < code->cmdcount; i++) { 445 445 uintptr_t srcarg = code->cmds[i].srcarg; 446 446 uintptr_t dstarg = code->cmds[i].dstarg; 447 447 448 448 switch (code->cmds[i].cmd) { 449 449 case CMD_PIO_READ_8: … … 493 493 if (scratch[srcarg] == 0) 494 494 i += code->cmds[i].value; 495 495 496 496 break; 497 497 case CMD_ACCEPT: … … 502 502 } 503 503 } 504 504 505 505 return IRQ_DECLINE; 506 506 } … … 516 516 { 517 517 assert(irq); 518 518 519 519 assert(interrupts_disabled()); 520 520 assert(irq_spinlock_locked(&irq->lock)); 521 521 522 522 if (irq->notif_cfg.answerbox) { 523 523 call_t *call = ipc_call_alloc(FRAME_ATOMIC); 524 524 if (!call) 525 525 return; 526 526 527 527 call->flags |= IPC_CALL_NOTIF; 528 528 /* Put a counter to the message */ 529 529 call->priv = ++irq->notif_cfg.counter; 530 530 531 531 /* Set up args */ 532 532 IPC_SET_IMETHOD(call->data, irq->notif_cfg.imethod); … … 536 536 IPC_SET_ARG4(call->data, irq->notif_cfg.scratch[4]); 537 537 IPC_SET_ARG5(call->data, irq->notif_cfg.scratch[5]); 538 538 539 539 send_call(irq, call); 540 540 } … … 555 555 { 556 556 irq_spinlock_lock(&irq->lock, true); 557 557 558 558 if (irq->notif_cfg.answerbox) { 559 559 call_t *call = ipc_call_alloc(FRAME_ATOMIC); … … 562 562 return; 563 563 } 564 564 565 565 call->flags |= IPC_CALL_NOTIF; 566 566 /* Put a counter to the message */ 567 567 call->priv = ++irq->notif_cfg.counter; 568 568 569 569 IPC_SET_IMETHOD(call->data, irq->notif_cfg.imethod); 570 570 IPC_SET_ARG1(call->data, a1); … … 573 573 IPC_SET_ARG4(call->data, a4); 574 574 IPC_SET_ARG5(call->data, a5); 575 575 576 576 send_call(irq, call); 577 577 } 578 578 579 579 irq_spinlock_unlock(&irq->lock, true); 580 580 } -
kernel/generic/src/ipc/kbox.c
r3061bc1 ra35b458 63 63 TASK->kb.finished = true; 64 64 mutex_unlock(&TASK->kb.cleanup_lock); 65 65 66 66 bool have_kb_thread = (TASK->kb.thread != NULL); 67 67 68 68 /* 69 69 * From now on nobody will try to connect phones or attach 70 70 * kbox threads 71 71 */ 72 72 73 73 /* 74 74 * Disconnect all phones connected to our kbox. Passing true for … … 78 78 */ 79 79 ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread); 80 80 81 81 /* 82 82 * If the task was being debugged, clean up debugging session. … … 87 87 udebug_task_cleanup(TASK); 88 88 mutex_unlock(&TASK->udebug.lock); 89 89 90 90 if (have_kb_thread) { 91 91 LOG("Join kb.thread."); … … 95 95 TASK->kb.thread = NULL; 96 96 } 97 97 98 98 /* Answer all messages in 'calls' and 'dispatched_calls' queues. */ 99 99 ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.calls); … … 120 120 LOG("Was not debugger."); 121 121 } 122 122 123 123 LOG("Continue with hangup message."); 124 124 IPC_SET_RETVAL(call->data, 0); 125 125 ipc_answer(&TASK->kb.box, call); 126 126 127 127 mutex_lock(&TASK->kb.cleanup_lock); 128 128 129 129 irq_spinlock_lock(&TASK->lock, true); 130 130 irq_spinlock_lock(&TASK->kb.box.lock, false); … … 134 134 * gets freed and signal to the caller. 135 135 */ 136 136 137 137 /* Only detach kbox thread unless already terminating. */ 138 138 if (TASK->kb.finished == false) { … … 141 141 TASK->kb.thread = NULL; 142 142 } 143 143 144 144 LOG("Phone list is empty."); 145 145 *last = true; 146 146 } else 147 147 *last = false; 148 148 149 149 irq_spinlock_unlock(&TASK->kb.box.lock, false); 150 150 irq_spinlock_unlock(&TASK->lock, true); 151 151 152 152 mutex_unlock(&TASK->kb.cleanup_lock); 153 153 } … … 166 166 LOG("Starting."); 167 167 bool done = false; 168 168 169 169 while (!done) { 170 170 call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT, 171 171 SYNCH_FLAGS_NONE); 172 172 173 173 if (call == NULL) 174 174 continue; /* Try again. */ 175 175 176 176 switch (IPC_GET_IMETHOD(call->data)) { 177 177 178 178 case IPC_M_DEBUG: 179 179 /* Handle debug call. */ 180 180 udebug_call_receive(call); 181 181 break; 182 182 183 183 case IPC_M_PHONE_HUNGUP: 184 184 /* … … 189 189 kbox_proc_phone_hungup(call, &done); 190 190 break; 191 191 192 192 default: 193 193 /* Ignore */ … … 195 195 } 196 196 } 197 197 198 198 LOG("Exiting."); 199 199 } … … 213 213 { 214 214 irq_spinlock_lock(&tasks_lock, true); 215 215 216 216 task_t *task = task_find_by_id(taskid); 217 217 if (task == NULL) { … … 219 219 return ENOENT; 220 220 } 221 221 222 222 atomic_inc(&task->refcount); 223 223 224 224 irq_spinlock_unlock(&tasks_lock, true); 225 225 226 226 mutex_lock(&task->kb.cleanup_lock); 227 227 228 228 if (atomic_predec(&task->refcount) == 0) { 229 229 mutex_unlock(&task->kb.cleanup_lock); … … 231 231 return ENOENT; 232 232 } 233 233 234 234 if (task->kb.finished) { 235 235 mutex_unlock(&task->kb.cleanup_lock); 236 236 return EINVAL; 237 237 } 238 238 239 239 /* Create a kbox thread if necessary. */ 240 240 if (task->kb.thread == NULL) { 241 241 thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 242 242 THREAD_FLAG_NONE, "kbox"); 243 243 244 244 if (!kb_thread) { 245 245 mutex_unlock(&task->kb.cleanup_lock); 246 246 return ENOMEM; 247 247 } 248 248 249 249 task->kb.thread = kb_thread; 250 250 thread_ready(kb_thread); 251 251 } 252 252 253 253 /* Allocate a new phone. */ 254 254 cap_handle_t phone_handle; … … 258 258 return rc; 259 259 } 260 260 261 261 kobject_t *phone_obj = kobject_get(TASK, phone_handle, 262 262 KOBJECT_TYPE_PHONE); … … 264 264 /* Hand over phone_obj's reference to ipc_phone_connect() */ 265 265 (void) ipc_phone_connect(phone_obj->phone, &task->kb.box); 266 266 267 267 mutex_unlock(&task->kb.cleanup_lock); 268 268 *out_phone = phone_handle; -
kernel/generic/src/ipc/ops/conctmeto.c
r3061bc1 ra35b458 108 108 IPC_SET_ARG5(answer->data, phone_handle); 109 109 } 110 110 111 111 return EOK; 112 112 } -
kernel/generic/src/ipc/ops/dataread.c
r3061bc1 ra35b458 74 74 */ 75 75 IPC_SET_ARG1(answer->data, dst); 76 76 77 77 answer->buffer = malloc(size, 0); 78 78 errno_t rc = copy_from_uspace(answer->buffer, -
kernel/generic/src/ipc/ops/datawrite.c
r3061bc1 ra35b458 65 65 return rc; 66 66 } 67 67 68 68 return EOK; 69 69 } … … 78 78 size_t size = (size_t)IPC_GET_ARG2(answer->data); 79 79 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 80 80 81 81 if (size <= max_size) { 82 82 errno_t rc = copy_to_uspace((void *) dst, -
kernel/generic/src/ipc/ops/pagein.c
r3061bc1 ra35b458 92 92 page_table_unlock(AS, true); 93 93 } 94 94 95 95 return EOK; 96 96 } -
kernel/generic/src/ipc/ops/sharein.c
r3061bc1 ra35b458 47 47 as_t *as = answer->sender->as; 48 48 irq_spinlock_unlock(&answer->sender->lock, true); 49 49 50 50 uintptr_t dst_base = (uintptr_t) -1; 51 51 errno_t rc = as_area_share(AS, IPC_GET_ARG1(answer->data), … … 55 55 IPC_SET_RETVAL(answer->data, rc); 56 56 } 57 57 58 58 return EOK; 59 59 } -
kernel/generic/src/ipc/ops/shareout.c
r3061bc1 ra35b458 68 68 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 69 69 &dst_base, IPC_GET_ARG1(answer->data)); 70 70 71 71 if (rc == EOK) { 72 72 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 73 73 &dst_base, sizeof(dst_base)); 74 74 } 75 75 76 76 IPC_SET_RETVAL(answer->data, rc); 77 77 } -
kernel/generic/src/ipc/sysipc.c
r3061bc1 ra35b458 69 69 if (imethod <= IPC_M_LAST_SYSTEM) 70 70 return true; 71 71 72 72 return false; 73 73 } … … 207 207 mutex_unlock(&phone->lock); 208 208 } 209 209 210 210 if (!olddata) 211 211 return rc; … … 242 242 (call->flags & IPC_CALL_FORWARDED)) 243 243 IPC_SET_RETVAL(call->data, EFORWARD); 244 244 245 245 SYSIPC_OP(answer_process, call); 246 246 } … … 276 276 if (!kobj->phone) 277 277 return ENOENT; 278 278 279 279 call_t *call = ipc_call_alloc(0); 280 280 call->priv = priv; 281 281 memcpy(call->data.args, data->args, sizeof(data->args)); 282 282 283 283 errno_t rc = request_preprocess(call, kobj->phone); 284 284 if (!rc) { … … 322 322 } else 323 323 IPC_SET_RETVAL(call->data, rc); 324 324 325 325 memcpy(data->args, call->data.args, sizeof(data->args)); 326 326 kobject_put(call->kobject); 327 327 kobject_put(kobj); 328 328 329 329 return EOK; 330 330 } … … 342 342 if (atomic_get(&phone->active_calls) >= IPC_MAX_ASYNC_CALLS) 343 343 return -1; 344 344 345 345 return 0; 346 346 } … … 368 368 if (!kobj) 369 369 return ENOENT; 370 370 371 371 if (check_call_limit(kobj->phone)) { 372 372 kobject_put(kobj); 373 373 return ELIMIT; 374 374 } 375 375 376 376 call_t *call = ipc_call_alloc(0); 377 377 IPC_SET_IMETHOD(call->data, imethod); … … 379 379 IPC_SET_ARG2(call->data, arg2); 380 380 IPC_SET_ARG3(call->data, arg3); 381 381 382 382 /* 383 383 * To achieve deterministic behavior, zero out arguments that are beyond … … 388 388 /* Set the user-defined label */ 389 389 call->data.label = label; 390 390 391 391 errno_t res = request_preprocess(call, kobj->phone); 392 392 393 393 if (!res) 394 394 ipc_call(kobj->phone, call); 395 395 else 396 396 ipc_backsend_err(kobj->phone, call, res); 397 397 398 398 kobject_put(kobj); 399 399 return EOK; … … 432 432 /* Set the user-defined label */ 433 433 call->data.label = label; 434 434 435 435 errno_t res = request_preprocess(call, kobj->phone); 436 436 437 437 if (!res) 438 438 ipc_call(kobj->phone, call); 439 439 else 440 440 ipc_backsend_err(kobj->phone, call, res); 441 441 442 442 kobject_put(kobj); 443 443 return EOK; … … 473 473 if (!ckobj) 474 474 return ENOENT; 475 475 476 476 call_t *call = ckobj->call; 477 477 … … 480 480 if (need_old) 481 481 old = call->data; 482 482 483 483 bool after_forward = false; 484 484 errno_t rc; … … 489 489 goto error; 490 490 } 491 491 492 492 if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) { 493 493 rc = EPERM; 494 494 goto error; 495 495 } 496 496 497 497 call->flags |= IPC_CALL_FORWARDED; 498 498 499 499 /* 500 500 * User space is not allowed to change interface and method of system … … 507 507 if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) 508 508 phone_dealloc(IPC_GET_ARG5(call->data)); 509 509 510 510 IPC_SET_ARG1(call->data, imethod); 511 511 IPC_SET_ARG2(call->data, arg1); 512 512 IPC_SET_ARG3(call->data, arg2); 513 513 514 514 if (slow) 515 515 IPC_SET_ARG4(call->data, arg3); 516 516 517 517 /* 518 518 * For system methods we deliberately don't … … 530 530 } 531 531 } 532 532 533 533 rc = ipc_forward(call, pkobj->phone, &TASK->answerbox, mode); 534 534 if (rc != EOK) { … … 609 609 if (rc != EOK) 610 610 return (sys_errno_t) rc; 611 611 612 612 return sys_ipc_forward_common(chandle, phandle, 613 613 IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata), … … 637 637 if (!kobj) 638 638 return ENOENT; 639 639 640 640 call_t *call = kobj->call; 641 641 642 642 ipc_data_t saved_data; 643 643 bool saved; 644 644 645 645 if (answer_need_old(call)) { 646 646 memcpy(&saved_data, &call->data, sizeof(call->data)); … … 648 648 } else 649 649 saved = false; 650 650 651 651 IPC_SET_RETVAL(call->data, retval); 652 652 IPC_SET_ARG1(call->data, arg1); … … 654 654 IPC_SET_ARG3(call->data, arg3); 655 655 IPC_SET_ARG4(call->data, arg4); 656 656 657 657 /* 658 658 * To achieve deterministic behavior, zero out arguments that are beyond … … 661 661 IPC_SET_ARG5(call->data, 0); 662 662 errno_t rc = answer_preprocess(call, saved ? &saved_data : NULL); 663 663 664 664 ipc_answer(&TASK->answerbox, call); 665 665 … … 683 683 if (!kobj) 684 684 return ENOENT; 685 685 686 686 call_t *call = kobj->call; 687 687 688 688 ipc_data_t saved_data; 689 689 bool saved; 690 690 691 691 if (answer_need_old(call)) { 692 692 memcpy(&saved_data, &call->data, sizeof(call->data)); … … 694 694 } else 695 695 saved = false; 696 696 697 697 errno_t rc = copy_from_uspace(&call->data.args, &data->args, 698 698 sizeof(call->data.args)); … … 704 704 return rc; 705 705 } 706 706 707 707 rc = answer_preprocess(call, saved ? &saved_data : NULL); 708 708 709 709 ipc_answer(&TASK->answerbox, call); 710 710 … … 727 727 if (!kobj) 728 728 return ENOENT; 729 729 730 730 errno_t rc = ipc_phone_hangup(kobj->phone); 731 731 kobject_put(kobj); … … 746 746 { 747 747 call_t *call; 748 748 749 749 restart: 750 750 751 751 #ifdef CONFIG_UDEBUG 752 752 udebug_stoppable_begin(); 753 753 #endif 754 754 755 755 call = ipc_wait_for_call(&TASK->answerbox, usec, 756 756 flags | SYNCH_FLAGS_INTERRUPTIBLE); 757 757 758 758 #ifdef CONFIG_UDEBUG 759 759 udebug_stoppable_end(); … … 766 766 return EOK; 767 767 } 768 768 769 769 call->data.flags = call->flags; 770 770 if (call->flags & IPC_CALL_NOTIF) { 771 771 /* Set in_phone_hash to the interrupt counter */ 772 772 call->data.phone = (void *) call->priv; 773 773 774 774 call->data.cap_handle = CAP_NIL; 775 775 776 776 STRUCT_TO_USPACE(calldata, &call->data); 777 777 kobject_put(call->kobject); 778 778 779 779 return EOK; 780 780 } 781 781 782 782 if (call->flags & IPC_CALL_ANSWERED) { 783 783 process_answer(call); 784 784 785 785 if (call->flags & IPC_CALL_DISCARD_ANSWER) { 786 786 kobject_put(call->kobject); … … 789 789 790 790 call->data.cap_handle = CAP_NIL; 791 791 792 792 STRUCT_TO_USPACE(calldata, &call->data); 793 793 kobject_put(call->kobject); 794 794 795 795 return EOK; 796 796 } 797 797 798 798 if (process_request(&TASK->answerbox, call)) 799 799 goto restart; 800 800 801 801 cap_handle_t handle; 802 802 errno_t rc = cap_alloc(TASK, &handle); … … 804 804 goto error; 805 805 } 806 806 807 807 call->data.cap_handle = handle; 808 808 … … 871 871 if (!(perm_get(TASK) & PERM_IRQ_REG)) 872 872 return EPERM; 873 873 874 874 return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode, uspace_handle); 875 875 } … … 887 887 if (!(perm_get(TASK) & PERM_IRQ_REG)) 888 888 return EPERM; 889 889 890 890 ipc_irq_unsubscribe(&TASK->answerbox, cap); 891 891 892 892 return 0; 893 893 } … … 903 903 task_id_t taskid; 904 904 cap_handle_t phone; 905 905 906 906 errno_t rc = copy_from_uspace(&taskid, uspace_taskid, sizeof(task_id_t)); 907 907 if (rc == EOK) { 908 908 rc = ipc_connect_kbox((task_id_t) taskid, &phone); 909 909 } 910 910 911 911 if (rc == EOK) { 912 912 rc = copy_to_uspace(uspace_phone, &phone, sizeof(cap_handle_t)); … … 916 916 } 917 917 } 918 918 919 919 return (sys_errno_t) rc; 920 920 #else
Note:
See TracChangeset
for help on using the changeset viewer.