Rev 1596 | Rev 1614 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1596 | Rev 1610 | ||
|---|---|---|---|
| Line 132... | Line 132... | ||
| 132 | ipc_callid_t callid; |
132 | ipc_callid_t callid; |
| 133 | ipc_call_t call; |
133 | ipc_call_t call; |
| 134 | void (*cthread)(ipc_callid_t,ipc_call_t *); |
134 | void (*cthread)(ipc_callid_t,ipc_call_t *); |
| 135 | } connection_t; |
135 | } connection_t; |
| 136 | 136 | ||
| 137 | - | ||
| - | 137 | /** Identifier of incoming connection handled by current thread */ |
|
| 138 | __thread connection_t *PS_connection; |
138 | __thread connection_t *PS_connection; |
| - | 139 | /** If true, it is forbidden to use async_req functions and |
|
| - | 140 | * all preemption is disabled */ |
|
| - | 141 | __thread int in_interrupt_handler; |
|
| 139 | 142 | ||
| 140 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
143 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
| 141 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
144 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
| 142 | static async_client_conn_t client_connection = default_client_connection; |
145 | static async_client_conn_t client_connection = default_client_connection; |
| 143 | static async_client_conn_t interrupt_received = default_interrupt_received; |
146 | static async_client_conn_t interrupt_received = default_interrupt_received; |
| Line 223... | Line 226... | ||
| 223 | { |
226 | { |
| 224 | link_t *tmp; |
227 | link_t *tmp; |
| 225 | awaiter_t *cur; |
228 | awaiter_t *cur; |
| 226 | 229 | ||
| 227 | wd->timedout = 0; |
230 | wd->timedout = 0; |
| - | 231 | wd->inlist = 1; |
|
| 228 | 232 | ||
| 229 | tmp = timeout_list.next; |
233 | tmp = timeout_list.next; |
| 230 | while (tmp != &timeout_list) { |
234 | while (tmp != &timeout_list) { |
| 231 | cur = list_get_instance(tmp, awaiter_t, link); |
235 | cur = list_get_instance(tmp, awaiter_t, link); |
| 232 | if (tv_gteq(&cur->expires, &wd->expires)) |
236 | if (tv_gteq(&cur->expires, &wd->expires)) |
| Line 292... | Line 296... | ||
| 292 | * I would never expect to find so many errors in |
296 | * I would never expect to find so many errors in |
| 293 | * compiler *($&$(*&$ |
297 | * compiler *($&$(*&$ |
| 294 | */ |
298 | */ |
| 295 | conn = PS_connection; |
299 | conn = PS_connection; |
| 296 | 300 | ||
| 297 | if (usecs < 0) /* TODO: let it get through the ipc_call once */ |
- | |
| 298 | return 0; |
- | |
| 299 | - | ||
| 300 | futex_down(&async_futex); |
301 | futex_down(&async_futex); |
| 301 | 302 | ||
| 302 | if (usecs) { |
303 | if (usecs) { |
| 303 | gettimeofday(&conn->wdata.expires, NULL); |
304 | gettimeofday(&conn->wdata.expires, NULL); |
| 304 | tv_add(&conn->wdata.expires, usecs); |
305 | tv_add(&conn->wdata.expires, usecs); |
| 305 | } else { |
306 | } else { |
| 306 | conn->wdata.inlist = 0; |
307 | conn->wdata.inlist = 0; |
| 307 | } |
308 | } |
| 308 | /* If nothing in queue, wait until something appears */ |
309 | /* If nothing in queue, wait until something appears */ |
| 309 | while (list_empty(&conn->msg_queue)) { |
310 | while (list_empty(&conn->msg_queue)) { |
| 310 | if (usecs) { |
311 | if (usecs) |
| 311 | conn->wdata.inlist = 1; |
- | |
| 312 | insert_timeout(&conn->wdata); |
312 | insert_timeout(&conn->wdata); |
| 313 | } |
313 | |
| 314 | conn->wdata.active = 0; |
314 | conn->wdata.active = 0; |
| 315 | psthread_schedule_next_adv(PS_TO_MANAGER); |
315 | psthread_schedule_next_adv(PS_TO_MANAGER); |
| 316 | /* Futex is up after getting back from async_manager |
316 | /* Futex is up after getting back from async_manager |
| 317 | * get it again */ |
317 | * get it again */ |
| 318 | futex_down(&async_futex); |
318 | futex_down(&async_futex); |
| Line 360... | Line 360... | ||
| 360 | msg_t *msg; |
360 | msg_t *msg; |
| 361 | 361 | ||
| 362 | /* Setup thread local connection pointer */ |
362 | /* Setup thread local connection pointer */ |
| 363 | PS_connection = (connection_t *)arg; |
363 | PS_connection = (connection_t *)arg; |
| 364 | PS_connection->cthread(PS_connection->callid, &PS_connection->call); |
364 | PS_connection->cthread(PS_connection->callid, &PS_connection->call); |
| 365 | - | ||
| 366 | /* Remove myself from connection hash table */ |
365 | /* Remove myself from connection hash table */ |
| 367 | futex_down(&async_futex); |
366 | futex_down(&async_futex); |
| 368 | key = PS_connection->in_phone_hash; |
367 | key = PS_connection->in_phone_hash; |
| 369 | hash_table_remove(&conn_hash_table, &key, 1); |
368 | hash_table_remove(&conn_hash_table, &key, 1); |
| 370 | futex_up(&async_futex); |
369 | futex_up(&async_futex); |
| Line 433... | Line 432... | ||
| 433 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
432 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
| 434 | { |
433 | { |
| 435 | /* Unrouted call - do some default behaviour */ |
434 | /* Unrouted call - do some default behaviour */ |
| 436 | switch (IPC_GET_METHOD(*call)) { |
435 | switch (IPC_GET_METHOD(*call)) { |
| 437 | case IPC_M_INTERRUPT: |
436 | case IPC_M_INTERRUPT: |
| - | 437 | in_interrupt_handler = 1; |
|
| 438 | (*interrupt_received)(callid,call); |
438 | (*interrupt_received)(callid,call); |
| - | 439 | in_interrupt_handler = 0; |
|
| 439 | return; |
440 | return; |
| 440 | case IPC_M_CONNECT_ME_TO: |
441 | case IPC_M_CONNECT_ME_TO: |
| 441 | /* Open new connection with thread etc. */ |
442 | /* Open new connection with thread etc. */ |
| 442 | async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection); |
443 | async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection); |
| 443 | return; |
444 | return; |
| Line 483... | Line 484... | ||
| 483 | 484 | ||
| 484 | futex_up(&async_futex); |
485 | futex_up(&async_futex); |
| 485 | } |
486 | } |
| 486 | 487 | ||
| 487 | /** Endless loop dispatching incoming calls and answers */ |
488 | /** Endless loop dispatching incoming calls and answers */ |
| 488 | int async_manager(void) |
489 | static int async_manager_worker(void) |
| 489 | { |
490 | { |
| 490 | ipc_call_t call; |
491 | ipc_call_t call; |
| 491 | ipc_callid_t callid; |
492 | ipc_callid_t callid; |
| 492 | int timeout; |
493 | int timeout; |
| 493 | awaiter_t *waiter; |
494 | awaiter_t *waiter; |
| Line 519... | Line 520... | ||
| 519 | if (!callid) { |
520 | if (!callid) { |
| 520 | handle_expired_timeouts(); |
521 | handle_expired_timeouts(); |
| 521 | continue; |
522 | continue; |
| 522 | } |
523 | } |
| 523 | 524 | ||
| 524 | if (callid & IPC_CALLID_ANSWERED) |
525 | if (callid & IPC_CALLID_ANSWERED) { |
| 525 | continue; |
526 | continue; |
| - | 527 | } |
|
| 526 | 528 | ||
| 527 | handle_call(callid, &call); |
529 | handle_call(callid, &call); |
| 528 | } |
530 | } |
| 529 | } |
531 | } |
| 530 | 532 | ||
| Line 535... | Line 537... | ||
| 535 | * currently one async_manager is started automatically per kernel |
537 | * currently one async_manager is started automatically per kernel |
| 536 | * thread except main thread. |
538 | * thread except main thread. |
| 537 | */ |
539 | */ |
| 538 | static int async_manager_thread(void *arg) |
540 | static int async_manager_thread(void *arg) |
| 539 | { |
541 | { |
| - | 542 | in_interrupt_handler = 0; // TODO: Handle TLS better |
|
| 540 | futex_up(&async_futex); /* async_futex is always locked when entering |
543 | futex_up(&async_futex); /* async_futex is always locked when entering |
| 541 | * manager */ |
544 | * manager */ |
| 542 | async_manager(); |
545 | async_manager_worker(); |
| 543 | } |
546 | } |
| 544 | 547 | ||
| 545 | /** Add one manager to manager list */ |
548 | /** Add one manager to manager list */ |
| 546 | void async_create_manager(void) |
549 | void async_create_manager(void) |
| 547 | { |
550 | { |
| Line 605... | Line 608... | ||
| 605 | aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
608 | aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
| 606 | ipc_call_t *dataptr) |
609 | ipc_call_t *dataptr) |
| 607 | { |
610 | { |
| 608 | amsg_t *msg; |
611 | amsg_t *msg; |
| 609 | 612 | ||
| - | 613 | if (in_interrupt_handler) { |
|
| - | 614 | printf("Cannot send asynchronou request in interrupt handler.\n"); |
|
| - | 615 | _exit(1); |
|
| - | 616 | } |
|
| - | 617 | ||
| 610 | msg = malloc(sizeof(*msg)); |
618 | msg = malloc(sizeof(*msg)); |
| 611 | msg->done = 0; |
619 | msg->done = 0; |
| 612 | msg->dataptr = dataptr; |
620 | msg->dataptr = dataptr; |
| 613 | 621 | ||
| 614 | msg->wdata.active = 1; /* We may sleep in next method, but it |
622 | msg->wdata.active = 1; /* We may sleep in next method, but it |
| Line 626... | Line 634... | ||
| 626 | aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
634 | aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
| 627 | ipcarg_t arg3, ipc_call_t *dataptr) |
635 | ipcarg_t arg3, ipc_call_t *dataptr) |
| 628 | { |
636 | { |
| 629 | amsg_t *msg; |
637 | amsg_t *msg; |
| 630 | 638 | ||
| - | 639 | if (in_interrupt_handler) { |
|
| - | 640 | printf("Cannot send asynchronou request in interrupt handler.\n"); |
|
| - | 641 | _exit(1); |
|
| - | 642 | } |
|
| - | 643 | ||
| 631 | msg = malloc(sizeof(*msg)); |
644 | msg = malloc(sizeof(*msg)); |
| 632 | msg->done = 0; |
645 | msg->done = 0; |
| 633 | msg->dataptr = dataptr; |
646 | msg->dataptr = dataptr; |
| 634 | 647 | ||
| 635 | msg->wdata.active = 1; /* We may sleep in next method, but it |
648 | msg->wdata.active = 1; /* We may sleep in next method, but it |
| Line 696... | Line 709... | ||
| 696 | gettimeofday(&msg->wdata.expires, NULL); |
709 | gettimeofday(&msg->wdata.expires, NULL); |
| 697 | tv_add(&msg->wdata.expires, timeout); |
710 | tv_add(&msg->wdata.expires, timeout); |
| 698 | 711 | ||
| 699 | msg->wdata.ptid = psthread_get_id(); |
712 | msg->wdata.ptid = psthread_get_id(); |
| 700 | msg->wdata.active = 0; |
713 | msg->wdata.active = 0; |
| 701 | msg->wdata.inlist = 1; |
- | |
| 702 | - | ||
| 703 | insert_timeout(&msg->wdata); |
714 | insert_timeout(&msg->wdata); |
| 704 | 715 | ||
| 705 | /* Leave locked async_futex when entering this function */ |
716 | /* Leave locked async_futex when entering this function */ |
| 706 | psthread_schedule_next_adv(PS_TO_MANAGER); |
717 | psthread_schedule_next_adv(PS_TO_MANAGER); |
| 707 | /* futex is up automatically after psthread_schedule_next...*/ |
718 | /* futex is up automatically after psthread_schedule_next...*/ |
| Line 723... | Line 734... | ||
| 723 | */ |
734 | */ |
| 724 | void async_usleep(suseconds_t timeout) |
735 | void async_usleep(suseconds_t timeout) |
| 725 | { |
736 | { |
| 726 | amsg_t *msg; |
737 | amsg_t *msg; |
| 727 | 738 | ||
| - | 739 | if (in_interrupt_handler) { |
|
| - | 740 | printf("Cannot call async_usleep in interrupt handler.\n"); |
|
| - | 741 | _exit(1); |
|
| - | 742 | } |
|
| - | 743 | ||
| 728 | msg = malloc(sizeof(*msg)); |
744 | msg = malloc(sizeof(*msg)); |
| 729 | if (!msg) |
745 | if (!msg) |
| 730 | return; |
746 | return; |
| 731 | 747 | ||
| 732 | msg->wdata.ptid = psthread_get_id(); |
748 | msg->wdata.ptid = psthread_get_id(); |
| 733 | msg->wdata.inlist = 1; |
- | |
| 734 | msg->wdata.active = 0; |
749 | msg->wdata.active = 0; |
| 735 | 750 | ||
| 736 | gettimeofday(&msg->wdata.expires, NULL); |
751 | gettimeofday(&msg->wdata.expires, NULL); |
| 737 | tv_add(&msg->wdata.expires, timeout); |
752 | tv_add(&msg->wdata.expires, timeout); |
| 738 | 753 | ||
| Line 754... | Line 769... | ||
| 754 | } |
769 | } |
| 755 | void async_set_interrupt_received(async_client_conn_t conn) |
770 | void async_set_interrupt_received(async_client_conn_t conn) |
| 756 | { |
771 | { |
| 757 | interrupt_received = conn; |
772 | interrupt_received = conn; |
| 758 | } |
773 | } |
| - | 774 | ||
| - | 775 | /* Primitive functions for simple communication */ |
|
| - | 776 | void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, |
|
| - | 777 | ipcarg_t arg2, ipcarg_t arg3) |
|
| - | 778 | { |
|
| - | 779 | ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler); |
|
| - | 780 | } |
|
| - | 781 | ||
| - | 782 | void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2) |
|
| - | 783 | { |
|
| - | 784 | ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler); |
|
| - | 785 | } |
|