Changeset 8820544 in mainline for uspace/lib/c/generic/async.c
- Timestamp:
- 2014-08-16T00:02:04Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 35b8bfe, 8cd680c
- Parents:
- 83f29e0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r83f29e0 r8820544 101 101 #undef LIBC_ASYNC_C_ 102 102 103 #include <ipc/irq.h> 104 #include <ipc/event.h> 103 105 #include <futex.h> 104 106 #include <fibril.h> … … 116 118 #include "private/libc.h" 117 119 118 119 120 /** Session data */ 120 121 struct async_sess { … … 242 243 async_client_conn_t cfibril; 243 244 } connection_t; 245 246 /* Notification data */ 247 typedef struct { 248 ht_link_t link; 249 250 /** Notification method */ 251 sysarg_t imethod; 252 253 /** Notification handler */ 254 async_notification_handler_t handler; 255 256 /** Notification data */ 257 void *data; 258 } notification_t; 244 259 245 260 /** Identifier of the incoming connection handled by the current fibril. */ … … 335 350 } 336 351 337 /** Default fibril function that gets called to handle interrupt notifications.338 *339 * This function is defined as a weak symbol - to be redefined in user code.340 *341 * @param callid Hash of the incoming call.342 * @param call Data of the incoming call.343 * @param arg Local argument.344 *345 */346 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)347 {348 }349 350 352 static async_client_conn_t client_connection = default_client_connection; 351 static async_interrupt_handler_t interrupt_received = default_interrupt_received; 352 static size_t interrupt_handler_stksz = FIBRIL_DFLT_STK_SIZE; 353 static size_t notification_handler_stksz = FIBRIL_DFLT_STK_SIZE; 353 354 354 355 /** Setter for client_connection function pointer. … … 363 364 } 364 365 365 /** Setter for interrupt_received function pointer. 366 * 367 * @param intr Function that will implement a new interrupt 368 * notification fibril. 369 */ 370 void async_set_interrupt_received(async_interrupt_handler_t intr) 371 { 372 interrupt_received = intr; 373 } 374 375 /** Set the stack size for the interrupt handler notification fibrils. 366 /** Set the stack size for the notification handler notification fibrils. 376 367 * 377 368 * @param size Stack size in bytes. 378 369 */ 379 void async_set_ interrupt_handler_stack_size(size_t size)380 { 381 interrupt_handler_stksz = size;370 void async_set_notification_handler_stack_size(size_t size) 371 { 372 notification_handler_stksz = size; 382 373 } 383 374 … … 399 390 static hash_table_t client_hash_table; 400 391 static hash_table_t conn_hash_table; 392 static hash_table_t notification_hash_table; 401 393 static LIST_INITIALIZE(timeout_list); 402 394 403 static size_t client_key_hash(void *k) 404 { 405 task_id_t key = *(task_id_t*)k; 406 return key; 395 static sysarg_t notification_avail = 0; 396 397 static size_t client_key_hash(void *key) 398 { 399 task_id_t in_task_id = *(task_id_t *) key; 400 return in_task_id; 407 401 } 408 402 … … 413 407 } 414 408 415 static bool client_key_equal(void *k , const ht_link_t *item)416 { 417 task_id_t key = *(task_id_t*)k;409 static bool client_key_equal(void *key, const ht_link_t *item) 410 { 411 task_id_t in_task_id = *(task_id_t *) key; 418 412 client_t *client = hash_table_get_inst(item, client_t, link); 419 return key == client->in_task_id; 420 } 421 413 return in_task_id == client->in_task_id; 414 } 422 415 423 416 /** Operations for the client hash table. */ … … 439 432 static size_t conn_key_hash(void *key) 440 433 { 441 sysarg_t in_phone_hash = *(sysarg_t*)key;442 return in_phone_hash 434 sysarg_t in_phone_hash = *(sysarg_t *) key; 435 return in_phone_hash; 443 436 } 444 437 … … 451 444 static bool conn_key_equal(void *key, const ht_link_t *item) 452 445 { 453 sysarg_t in_phone_hash = *(sysarg_t *)key;446 sysarg_t in_phone_hash = *(sysarg_t *) key; 454 447 connection_t *conn = hash_table_get_inst(item, connection_t, link); 455 448 return (in_phone_hash == conn->in_phone_hash); 456 449 } 457 458 450 459 451 /** Operations for the connection hash table. */ … … 462 454 .key_hash = conn_key_hash, 463 455 .key_equal = conn_key_equal, 456 .equal = NULL, 457 .remove_callback = NULL 458 }; 459 460 static size_t notification_key_hash(void *key) 461 { 462 sysarg_t id = *(sysarg_t *) key; 463 return id; 464 } 465 466 static size_t notification_hash(const ht_link_t *item) 467 { 468 notification_t *notification = 469 hash_table_get_inst(item, notification_t, link); 470 return notification_key_hash(¬ification->imethod); 471 } 472 473 static bool notification_key_equal(void *key, const ht_link_t *item) 474 { 475 sysarg_t id = *(sysarg_t *) key; 476 notification_t *notification = 477 hash_table_get_inst(item, notification_t, link); 478 return id == notification->imethod; 479 } 480 481 /** Operations for the notification hash table. */ 482 static hash_table_ops_t notification_hash_table_ops = { 483 .hash = notification_hash, 484 .key_hash = notification_key_hash, 485 .key_equal = notification_key_equal, 464 486 .equal = NULL, 465 487 .remove_callback = NULL … … 511 533 futex_down(&async_futex); 512 534 513 ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash); 514 515 if (!hlp) { 535 ht_link_t *link = hash_table_find(&conn_hash_table, &call->in_phone_hash); 536 if (!link) { 516 537 futex_up(&async_futex); 517 538 return false; 518 539 } 519 540 520 connection_t *conn = hash_table_get_inst( hlp, connection_t, link);541 connection_t *conn = hash_table_get_inst(link, connection_t, link); 521 542 522 543 msg_t *msg = malloc(sizeof(*msg)); … … 553 574 * 554 575 * When a notification arrives, a fibril with this implementing function is 555 * created. It calls interrupt_received() and does the final cleanup. 576 * created. It calls the corresponding notification handler and does the final 577 * cleanup. 556 578 * 557 579 * @param arg Message structure pointer. … … 565 587 566 588 msg_t *msg = (msg_t *) arg; 567 interrupt_received(msg->callid, &msg->call); 589 async_notification_handler_t handler = NULL; 590 void *data = NULL; 591 592 futex_down(&async_futex); 593 594 ht_link_t *link = hash_table_find(¬ification_hash_table, 595 &IPC_GET_IMETHOD(msg->call)); 596 if (link) { 597 notification_t *notification = 598 hash_table_get_inst(link, notification_t, link); 599 handler = notification->handler; 600 data = notification->data; 601 } 602 603 futex_up(&async_futex); 604 605 if (handler) 606 handler(msg->callid, &msg->call, data); 568 607 569 608 free(msg); … … 571 610 } 572 611 573 /** Process interruptnotification.612 /** Process notification. 574 613 * 575 614 * A new fibril is created which would process the notification. … … 598 637 599 638 fid_t fid = fibril_create_generic(notification_fibril, msg, 600 interrupt_handler_stksz);639 notification_handler_stksz); 601 640 if (fid == 0) { 602 641 free(msg); … … 609 648 futex_up(&async_futex); 610 649 return true; 650 } 651 652 /** Subscribe to IRQ notification. 653 * 654 * @param inr IRQ number. 655 * @param devno Device number of the device generating inr. 656 * @param handler Notification handler. 657 * @param data Notification handler client data. 658 * @param ucode Top-half pseudocode handler. 659 * 660 * @return Zero on success or a negative error code. 661 * 662 */ 663 int async_irq_subscribe(int inr, int devno, 664 async_notification_handler_t handler, void *data, const irq_code_t *ucode) 665 { 666 notification_t *notification = 667 (notification_t *) malloc(sizeof(notification_t)); 668 if (!notification) 669 return ENOMEM; 670 671 futex_down(&async_futex); 672 673 sysarg_t imethod = notification_avail; 674 notification_avail++; 675 676 notification->imethod = imethod; 677 notification->handler = handler; 678 notification->data = data; 679 680 hash_table_insert(¬ification_hash_table, ¬ification->link); 681 682 futex_up(&async_futex); 683 684 return ipc_irq_subscribe(inr, devno, imethod, ucode); 685 } 686 687 /** Unsubscribe from IRQ notification. 688 * 689 * @param inr IRQ number. 690 * @param devno Device number of the device generating inr. 691 * 692 * @return Zero on success or a negative error code. 693 * 694 */ 695 int async_irq_unsubscribe(int inr, int devno) 696 { 697 // TODO: Remove entry from hash table 698 // to avoid memory leak 699 700 return ipc_irq_unsubscribe(inr, devno); 701 } 702 703 /** Subscribe to event notifications. 704 * 705 * @param evno Event type to subscribe. 706 * @param handler Notification handler. 707 * @param data Notification handler client data. 708 * 709 * @return Zero on success or a negative error code. 710 * 711 */ 712 int async_event_subscribe(event_type_t evno, 713 async_notification_handler_t handler, void *data) 714 { 715 notification_t *notification = 716 (notification_t *) malloc(sizeof(notification_t)); 717 if (!notification) 718 return ENOMEM; 719 720 futex_down(&async_futex); 721 722 sysarg_t imethod = notification_avail; 723 notification_avail++; 724 725 notification->imethod = imethod; 726 notification->handler = handler; 727 notification->data = data; 728 729 hash_table_insert(¬ification_hash_table, ¬ification->link); 730 731 futex_up(&async_futex); 732 733 return ipc_event_subscribe(evno, imethod); 734 } 735 736 /** Subscribe to task event notifications. 737 * 738 * @param evno Event type to subscribe. 739 * @param handler Notification handler. 740 * @param data Notification handler client data. 741 * 742 * @return Zero on success or a negative error code. 743 * 744 */ 745 int async_event_task_subscribe(event_task_type_t evno, 746 async_notification_handler_t handler, void *data) 747 { 748 notification_t *notification = 749 (notification_t *) malloc(sizeof(notification_t)); 750 if (!notification) 751 return ENOMEM; 752 753 futex_down(&async_futex); 754 755 sysarg_t imethod = notification_avail; 756 notification_avail++; 757 758 notification->imethod = imethod; 759 notification->handler = handler; 760 notification->data = data; 761 762 hash_table_insert(¬ification_hash_table, ¬ification->link); 763 764 futex_up(&async_futex); 765 766 return ipc_event_task_subscribe(evno, imethod); 767 } 768 769 /** Unmask event notifications. 770 * 771 * @param evno Event type to unmask. 772 * 773 * @return Value returned by the kernel. 774 * 775 */ 776 int async_event_unmask(event_type_t evno) 777 { 778 return ipc_event_unmask(evno); 779 } 780 781 /** Unmask task event notifications. 782 * 783 * @param evno Event type to unmask. 784 * 785 * @return Value returned by the kernel. 786 * 787 */ 788 int async_event_task_unmask(event_task_type_t evno) 789 { 790 return ipc_event_task_unmask(evno); 611 791 } 612 792 … … 702 882 703 883 futex_down(&async_futex); 704 ht_link_t *l nk = hash_table_find(&client_hash_table, &client_id);705 if (l nk) {706 client = hash_table_get_inst(l nk, client_t, link);884 ht_link_t *link = hash_table_find(&client_hash_table, &client_id); 885 if (link) { 886 client = hash_table_get_inst(link, client_t, link); 707 887 atomic_inc(&client->refcnt); 708 888 } else if (create) { … … 1106 1286 1107 1287 if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops)) 1288 abort(); 1289 1290 if (!hash_table_create(¬ification_hash_table, 0, 0, 1291 ¬ification_hash_table_ops)) 1108 1292 abort(); 1109 1293
Note:
See TracChangeset
for help on using the changeset viewer.