Rev 2484 | Rev 2486 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2484 | Rev 2485 | ||
---|---|---|---|
Line 254... | Line 254... | ||
254 | tmp = tmp->next; |
254 | tmp = tmp->next; |
255 | } |
255 | } |
256 | list_append(&wd->link, tmp); |
256 | list_append(&wd->link, tmp); |
257 | } |
257 | } |
258 | 258 | ||
259 | /*************************************************/ |
- | |
260 | - | ||
261 | /** Try to route a call to an appropriate connection thread |
259 | /** Try to route a call to an appropriate connection fibril |
262 | * |
260 | * |
263 | */ |
261 | */ |
264 | static int route_call(ipc_callid_t callid, ipc_call_t *call) |
262 | static int route_call(ipc_callid_t callid, ipc_call_t *call) |
265 | { |
263 | { |
266 | connection_t *conn; |
264 | connection_t *conn; |
Line 300... | Line 298... | ||
300 | futex_up(&async_futex); |
298 | futex_up(&async_futex); |
301 | 299 | ||
302 | return 1; |
300 | return 1; |
303 | } |
301 | } |
304 | 302 | ||
305 | /** Return new incoming message for current(thread-local) connection */ |
303 | /** Return new incoming message for the current (fibril-local) connection */ |
306 | ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
304 | ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
307 | { |
305 | { |
308 | msg_t *msg; |
306 | msg_t *msg; |
309 | ipc_callid_t callid; |
307 | ipc_callid_t callid; |
310 | connection_t *conn; |
308 | connection_t *conn; |
Line 351... | Line 349... | ||
351 | 349 | ||
352 | futex_up(&async_futex); |
350 | futex_up(&async_futex); |
353 | return callid; |
351 | return callid; |
354 | } |
352 | } |
355 | 353 | ||
356 | /** Thread function that gets created on new connection |
354 | /** Fibril function that gets created on new connection |
357 | * |
355 | * |
358 | * This function is defined as a weak symbol - to be redefined in |
356 | * This function is defined as a weak symbol - to be redefined in |
359 | * user code. |
357 | * user code. |
360 | */ |
358 | */ |
361 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
359 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
Line 364... | Line 362... | ||
364 | } |
362 | } |
365 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
363 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) |
366 | { |
364 | { |
367 | } |
365 | } |
368 | 366 | ||
369 | /** Wrapper for client connection thread |
367 | /** Wrapper for client connection fibril. |
- | 368 | * |
|
- | 369 | * When new connection arrives, a fibril with this implementing function is |
|
- | 370 | * created. It calls client_connection() and does the final cleanup. |
|
370 | * |
371 | * |
371 | * When new connection arrives, thread with this function is created. |
- | |
372 | * It calls client_connection and does final cleanup. |
372 | * @param arg Connection structure pointer |
373 | * |
373 | * |
374 | * @param arg Connection structure pointer |
374 | * @return Always zero. |
375 | */ |
375 | */ |
376 | static int connection_fibril(void *arg) |
376 | static int connection_fibril(void *arg) |
377 | { |
377 | { |
378 | unsigned long key; |
378 | unsigned long key; |
379 | msg_t *msg; |
379 | msg_t *msg; |
380 | int close_answered = 0; |
380 | int close_answered = 0; |
381 | 381 | ||
382 | /* Setup thread local connection pointer */ |
382 | /* Setup fibril-local connection pointer */ |
383 | FIBRIL_connection = (connection_t *) arg; |
383 | FIBRIL_connection = (connection_t *) arg; |
384 | FIBRIL_connection->cfibril(FIBRIL_connection->callid, |
384 | FIBRIL_connection->cfibril(FIBRIL_connection->callid, |
385 | &FIBRIL_connection->call); |
385 | &FIBRIL_connection->call); |
386 | 386 | ||
387 | /* Remove myself from connection hash table */ |
387 | /* Remove myself from connection hash table */ |
Line 404... | Line 404... | ||
404 | ipc_answer_fast(FIBRIL_connection->close_callid, 0, 0, 0); |
404 | ipc_answer_fast(FIBRIL_connection->close_callid, 0, 0, 0); |
405 | 405 | ||
406 | return 0; |
406 | return 0; |
407 | } |
407 | } |
408 | 408 | ||
409 | /** Create new thread for a new connection |
409 | /** Create a new fibril for a new connection. |
410 | * |
410 | * |
411 | * Creates new thread for connection, fills in connection |
411 | * Creates new fibril for connection, fills in connection structures and inserts |
412 | * structures and inserts it into the hash table, so that |
- | |
413 | * later we can easily do routing of messages to particular |
412 | * it into the hash table, so that later we can easily do routing of messages to |
414 | * threads. |
413 | * particular fibrils. |
415 | * |
414 | * |
416 | * @param in_phone_hash Identification of the incoming connection |
415 | * @param in_phone_hash Identification of the incoming connection |
417 | * @param callid Callid of the IPC_M_CONNECT_ME_TO packet |
416 | * @param callid Callid of the IPC_M_CONNECT_ME_TO packet |
418 | * @param call Call data of the opening packet |
417 | * @param call Call data of the opening packet |
419 | * @param cfibril Fibril function that should be called upon |
418 | * @param cfibril Fibril function that should be called upon |
420 | * opening the connection |
419 | * opening the connection |
421 | * @return New fibril id. |
420 | * @return New fibril id. |
422 | */ |
421 | */ |
423 | fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
422 | fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, |
424 | ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) |
423 | ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) |
425 | { |
424 | { |
426 | connection_t *conn; |
425 | connection_t *conn; |
Line 455... | Line 454... | ||
455 | fibril_add_ready(conn->wdata.fid); |
454 | fibril_add_ready(conn->wdata.fid); |
456 | 455 | ||
457 | return conn->wdata.fid; |
456 | return conn->wdata.fid; |
458 | } |
457 | } |
459 | 458 | ||
460 | /** Handle call that was received */ |
459 | /** Handle a call that was received. */ |
461 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
460 | static void handle_call(ipc_callid_t callid, ipc_call_t *call) |
462 | { |
461 | { |
463 | /* Unrouted call - do some default behaviour */ |
462 | /* Unrouted call - do some default behaviour */ |
464 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
463 | if ((callid & IPC_CALLID_NOTIFICATION)) { |
465 | in_interrupt_handler = 1; |
464 | in_interrupt_handler = 1; |
Line 468... | Line 467... | ||
468 | return; |
467 | return; |
469 | } |
468 | } |
470 | 469 | ||
471 | switch (IPC_GET_METHOD(*call)) { |
470 | switch (IPC_GET_METHOD(*call)) { |
472 | case IPC_M_CONNECT_ME_TO: |
471 | case IPC_M_CONNECT_ME_TO: |
473 | /* Open new connection with thread etc. */ |
472 | /* Open new connection with fibril etc. */ |
474 | async_new_connection(IPC_GET_ARG3(*call), callid, call, |
473 | async_new_connection(IPC_GET_ARG3(*call), callid, call, |
475 | client_connection); |
474 | client_connection); |
476 | return; |
475 | return; |
477 | } |
476 | } |
478 | 477 | ||
Line 482... | Line 481... | ||
482 | 481 | ||
483 | /* Unknown call from unknown phone - hang it up */ |
482 | /* Unknown call from unknown phone - hang it up */ |
484 | ipc_answer_fast(callid, EHANGUP, 0, 0); |
483 | ipc_answer_fast(callid, EHANGUP, 0, 0); |
485 | } |
484 | } |
486 | 485 | ||
487 | /** Fire all timeouts that expired |
486 | /** Fire all timeouts that expired. */ |
488 | * |
- | |
489 | */ |
- | |
490 | static void handle_expired_timeouts(void) |
487 | static void handle_expired_timeouts(void) |
491 | { |
488 | { |
492 | struct timeval tv; |
489 | struct timeval tv; |
493 | awaiter_t *waiter; |
490 | awaiter_t *waiter; |
494 | link_t *cur; |
491 | link_t *cur; |
Line 503... | Line 500... | ||
503 | break; |
500 | break; |
504 | cur = cur->next; |
501 | cur = cur->next; |
505 | list_remove(&waiter->link); |
502 | list_remove(&waiter->link); |
506 | waiter->inlist = 0; |
503 | waiter->inlist = 0; |
507 | waiter->timedout = 1; |
504 | waiter->timedout = 1; |
508 | /* Redundant condition? The thread should not |
505 | /* Redundant condition? The fibril should not |
509 | * be active when it gets here. |
506 | * be active when it gets here. |
510 | */ |
507 | */ |
511 | if (!waiter->active) { |
508 | if (!waiter->active) { |
512 | waiter->active = 1; |
509 | waiter->active = 1; |
513 | fibril_add_ready(waiter->fid); |
510 | fibril_add_ready(waiter->fid); |
Line 528... | Line 525... | ||
528 | 525 | ||
529 | while (1) { |
526 | while (1) { |
530 | if (fibril_schedule_next_adv(FIBRIL_FROM_MANAGER)) { |
527 | if (fibril_schedule_next_adv(FIBRIL_FROM_MANAGER)) { |
531 | futex_up(&async_futex); |
528 | futex_up(&async_futex); |
532 | /* async_futex is always held |
529 | /* async_futex is always held |
533 | * when entering manager thread |
530 | * when entering manager fibril |
534 | */ |
531 | */ |
535 | continue; |
532 | continue; |
536 | } |
533 | } |
537 | futex_down(&async_futex); |
534 | futex_down(&async_futex); |
538 | if (!list_empty(&timeout_list)) { |
535 | if (!list_empty(&timeout_list)) { |
Line 564... | Line 561... | ||
564 | } |
561 | } |
565 | 562 | ||
566 | return 0; |
563 | return 0; |
567 | } |
564 | } |
568 | 565 | ||
569 | /** Function to start async_manager as a standalone thread |
566 | /** Function to start async_manager as a standalone fibril. |
570 | * |
567 | * |
571 | * When more kernel threads are used, one async manager should |
568 | * When more kernel threads are used, one async manager should |
572 | * exist per thread. The particular implementation may change, |
- | |
573 | * currently one async_manager is started automatically per kernel |
- | |
574 | * thread except the main thread. |
569 | * exist per thread. |
575 | */ |
570 | */ |
576 | static int async_manager_fibril(void *arg) |
571 | static int async_manager_fibril(void *arg) |
577 | { |
572 | { |
578 | futex_up(&async_futex); |
573 | futex_up(&async_futex); |
579 | /* async_futex is always locked when entering |
574 | /* async_futex is always locked when entering |
Line 612... | Line 607... | ||
612 | 607 | ||
613 | /** IPC handler for messages in async framework |
608 | /** IPC handler for messages in async framework |
614 | * |
609 | * |
615 | * Notify the fibril which is waiting for this message, that it arrived |
610 | * Notify the fibril which is waiting for this message, that it arrived |
616 | */ |
611 | */ |
617 | static void reply_received(void *private, int retval, |
612 | static void reply_received(void *private, int retval, ipc_call_t *data) |
618 | ipc_call_t *data) |
- | |
619 | { |
613 | { |
620 | amsg_t *msg = (amsg_t *) private; |
614 | amsg_t *msg = (amsg_t *) private; |
621 | 615 | ||
622 | msg->retval = retval; |
616 | msg->retval = retval; |
623 | 617 | ||
Line 644... | Line 638... | ||
644 | * |
638 | * |
645 | * The return value can be used as input for async_wait() to wait |
639 | * The return value can be used as input for async_wait() to wait |
646 | * for completion. |
640 | * for completion. |
647 | */ |
641 | */ |
648 | aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
642 | aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
649 | ipc_call_t *dataptr) |
643 | ipc_call_t *dataptr) |
650 | { |
644 | { |
651 | amsg_t *msg; |
645 | amsg_t *msg; |
652 | 646 | ||
653 | if (in_interrupt_handler) { |
647 | if (in_interrupt_handler) { |
654 | printf("Cannot send asynchronous request in interrupt " |
648 | printf("Cannot send asynchronous request in interrupt " |
Line 671... | Line 665... | ||
671 | * |
665 | * |
672 | * The return value can be used as input for async_wait() to wait |
666 | * The return value can be used as input for async_wait() to wait |
673 | * for completion. |
667 | * for completion. |
674 | */ |
668 | */ |
675 | aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
669 | aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, |
676 | ipcarg_t arg3, ipc_call_t *dataptr) |
670 | ipcarg_t arg3, ipc_call_t *dataptr) |
677 | { |
671 | { |
678 | amsg_t *msg; |
672 | amsg_t *msg; |
679 | 673 | ||
680 | if (in_interrupt_handler) { |
674 | if (in_interrupt_handler) { |
681 | printf("Cannot send asynchronous request in interrupt handler.\n"); |
675 | printf("Cannot send asynchronous request in interrupt handler.\n"); |
Line 694... | Line 688... | ||
694 | return (aid_t) msg; |
688 | return (aid_t) msg; |
695 | } |
689 | } |
696 | 690 | ||
697 | /** Wait for a message sent by async framework |
691 | /** Wait for a message sent by async framework |
698 | * |
692 | * |
699 | * @param amsgid Message ID to wait for |
693 | * @param amsgid Message ID to wait for |
700 | * @param retval Pointer to variable where will be stored retval |
694 | * @param retval Pointer to variable where will be stored retval of the |
701 | * of the answered message. If NULL, it is ignored. |
695 | * answered message. If NULL, it is ignored. |
702 | * |
- | |
703 | */ |
696 | */ |
704 | void async_wait_for(aid_t amsgid, ipcarg_t *retval) |
697 | void async_wait_for(aid_t amsgid, ipcarg_t *retval) |
705 | { |
698 | { |
706 | amsg_t *msg = (amsg_t *) amsgid; |
699 | amsg_t *msg = (amsg_t *) amsgid; |
707 | 700 | ||
Line 791... | Line 784... | ||
791 | gettimeofday(&msg->wdata.expires, NULL); |
784 | gettimeofday(&msg->wdata.expires, NULL); |
792 | tv_add(&msg->wdata.expires, timeout); |
785 | tv_add(&msg->wdata.expires, timeout); |
793 | 786 | ||
794 | futex_down(&async_futex); |
787 | futex_down(&async_futex); |
795 | insert_timeout(&msg->wdata); |
788 | insert_timeout(&msg->wdata); |
796 | /* Leave locked async_futex when entering this function */ |
789 | /* Leave locked the async_futex when entering this function */ |
797 | fibril_schedule_next_adv(FIBRIL_TO_MANAGER); |
790 | fibril_schedule_next_adv(FIBRIL_TO_MANAGER); |
798 | /* futex is up automatically after fibril_schedule_next...*/ |
791 | /* futex is up automatically after fibril_schedule_next_adv()...*/ |
799 | free(msg); |
792 | free(msg); |
800 | } |
793 | } |
801 | 794 | ||
802 | /** Set function that is called, IPC_M_CONNECT_ME_TO is received |
795 | /** Set function that is called when IPC_M_CONNECT_ME_TO is received. |
803 | * |
796 | * |
804 | * @param conn Function that will form new psthread. |
797 | * @param conn Function that will form a new fibril. |
805 | */ |
798 | */ |
806 | void async_set_client_connection(async_client_conn_t conn) |
799 | void async_set_client_connection(async_client_conn_t conn) |
807 | { |
800 | { |
808 | client_connection = conn; |
801 | client_connection = conn; |
809 | } |
802 | } |