Changeset 8e7c9fe in mainline for uspace/lib/c/generic
- Timestamp:
- 2014-09-12T03:45:25Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c53b58e
- Parents:
- 3eb0c85 (diff), 105d8d6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/c/generic
- Files:
-
- 2 added
- 19 edited
- 3 moved
-
adt/hash_table.c (modified) (1 diff)
-
async.c (modified) (18 diffs)
-
bd.c (modified) (1 diff)
-
bd_srv.c (modified) (3 diffs)
-
ddi.c (modified) (7 diffs)
-
device/clock_dev.c (modified) (1 diff)
-
device/led_dev.c (moved) (moved from uspace/drv/char/ps2mouse/chardev.h ) (2 diffs)
-
event.c (modified) (3 diffs)
-
fibril.c (modified) (3 diffs)
-
fibril_synch.c (modified) (8 diffs)
-
inet.c (modified) (3 diffs)
-
io/asprintf.c (modified) (2 diffs)
-
io/chardev.c (moved) (moved from uspace/drv/char/ps2mouse/chardev.c ) (3 diffs)
-
io/chardev_srv.c (added)
-
io/console.c (modified) (1 diff)
-
io/input.c (modified) (2 diffs)
-
iplink.c (modified) (3 diffs)
-
iplink_srv.c (modified) (3 diffs)
-
irc.c (added)
-
irq.c (moved) (moved from kernel/arch/mips64/src/mm/as.c ) (3 diffs)
-
stacktrace.c (modified) (1 diff)
-
str.c (modified) (1 diff)
-
task.c (modified) (16 diffs)
-
time.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/adt/hash_table.c
r3eb0c85 r8e7c9fe 370 370 */ 371 371 if (!f(cur_link, arg)) 372 return;373 } 374 } 375 372 goto out; 373 } 374 } 375 out: 376 376 h->apply_ongoing = false; 377 377 -
uspace/lib/c/generic/async.c
r3eb0c85 r8e7c9fe 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 -
uspace/lib/c/generic/bd.c
r3eb0c85 r8e7c9fe 150 150 } 151 151 152 int bd_sync_cache(bd_t *bd, aoff64_t ba, size_t cnt) 153 { 154 async_exch_t *exch = async_exchange_begin(bd->sess); 155 156 int rc = async_req_3_0(exch, BD_SYNC_CACHE, LOWER32(ba), 157 UPPER32(ba), cnt); 158 async_exchange_end(exch); 159 160 return rc; 161 } 162 152 163 int bd_get_block_size(bd_t *bd, size_t *rbsize) 153 164 { -
uspace/lib/c/generic/bd_srv.c
r3eb0c85 r8e7c9fe 128 128 } 129 129 130 static void bd_sync_cache_srv(bd_srv_t *srv, ipc_callid_t callid, 131 ipc_call_t *call) 132 { 133 aoff64_t ba; 134 size_t cnt; 135 int rc; 136 137 ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); 138 cnt = IPC_GET_ARG3(*call); 139 140 if (srv->srvs->ops->sync_cache == NULL) { 141 async_answer_0(callid, ENOTSUP); 142 return; 143 } 144 145 rc = srv->srvs->ops->sync_cache(srv, ba, cnt); 146 async_answer_0(callid, rc); 147 } 148 130 149 static void bd_write_blocks_srv(bd_srv_t *srv, ipc_callid_t callid, 131 150 ipc_call_t *call) … … 190 209 bd_srv_t *srv; 191 210 192 srv = calloc(1, sizeof( srv));211 srv = calloc(1, sizeof(bd_srv_t)); 193 212 if (srv == NULL) 194 213 return NULL; … … 244 263 bd_read_toc_srv(srv, callid, &call); 245 264 break; 265 case BD_SYNC_CACHE: 266 bd_sync_cache_srv(srv, callid, &call); 267 break; 246 268 case BD_WRITE_BLOCKS: 247 269 bd_write_blocks_srv(srv, callid, &call); -
uspace/lib/c/generic/ddi.c
r3eb0c85 r8e7c9fe 71 71 * @param flags Flags for the new address space area. 72 72 * @param virt Virtual address of the starting page. 73 * 74 * @return EOK on success 75 * @return EPERM if the caller lacks the CAP_MEM_MANAGER capability 76 * @return ENOENT if there is no task with specified ID 73 * If set to AS_AREA_ANY ((void *) -1), a suitable value 74 * is found by the kernel, otherwise the kernel tries to 75 * obey the desired value. 76 * 77 * @return EOK on success. 78 * @return EPERM if the caller lacks the CAP_MEM_MANAGER capability. 77 79 * @return ENOMEM if there was some problem in creating 78 80 * the address space area. … … 85 87 } 86 88 89 /** Unmap a piece of physical memory to task. 90 * 91 * Caller of this function must have the CAP_MEM_MANAGER capability. 92 * 93 * @param virt Virtual address from the phys-mapped region. 94 * 95 * @return EOK on success. 96 * @return EPERM if the caller lacks the CAP_MEM_MANAGER capability. 97 * 98 */ 99 int physmem_unmap(void *virt) 100 { 101 return __SYSCALL1(SYS_PHYSMEM_UNMAP, (sysarg_t) virt); 102 } 103 104 /** Lock a piece physical memory for DMA transfers. 105 * 106 * The mapping of the specified virtual memory address 107 * to physical memory address is locked in order to 108 * make it safe for DMA transferts. 109 * 110 * Caller of this function must have the CAP_MEM_MANAGER capability. 111 * 112 * @param virt Virtual address of the memory to be locked. 113 * @param size Number of bytes to lock. 114 * @param map_flags Desired virtual memory area flags. 115 * @param flags Flags for the physical memory address. 116 * @param phys Locked physical memory address. 117 * 118 * @return EOK on success. 119 * @return EPERM if the caller lacks the CAP_MEM_MANAGER capability. 120 * @return ENOMEM if there was some problem in creating 121 * the address space area. 122 * 123 */ 87 124 int dmamem_map(void *virt, size_t size, unsigned int map_flags, 88 125 unsigned int flags, uintptr_t *phys) … … 93 130 } 94 131 132 /** Map a piece of physical memory suitable for DMA transfers. 133 * 134 * Caller of this function must have the CAP_MEM_MANAGER capability. 135 * 136 * @param size Number of bytes to map. 137 * @param constraint Bit mask defining the contraint on the physical 138 * address to be mapped. 139 * @param map_flags Desired virtual memory area flags. 140 * @param flags Flags for the physical memory address. 141 * @param virt Virtual address of the starting page. 142 * If set to AS_AREA_ANY ((void *) -1), a suitable value 143 * is found by the kernel, otherwise the kernel tries to 144 * obey the desired value. 145 * 146 * @return EOK on success. 147 * @return EPERM if the caller lacks the CAP_MEM_MANAGER capability. 148 * @return ENOMEM if there was some problem in creating 149 * the address space area. 150 * 151 */ 95 152 int dmamem_map_anonymous(size_t size, uintptr_t constraint, 96 153 unsigned int map_flags, unsigned int flags, uintptr_t *phys, void **virt) … … 137 194 138 195 return __SYSCALL1(SYS_IOSPACE_ENABLE, (sysarg_t) &arg); 196 } 197 198 /** Disable I/O space range to task. 199 * 200 * Caller of this function must have the IO_MEM_MANAGER capability. 201 * 202 * @param id Task ID. 203 * @param ioaddr Starting address of the I/O range. 204 * @param size Size of the range. 205 * 206 * @return EOK on success 207 * @return EPERM if the caller lacks the CAP_IO_MANAGER capability 208 * @return ENOENT if there is no task with specified ID 209 * 210 */ 211 static int iospace_disable(task_id_t id, void *ioaddr, size_t size) 212 { 213 const ddi_ioarg_t arg = { 214 .task_id = id, 215 .ioaddr = ioaddr, 216 .size = size 217 }; 218 219 return __SYSCALL1(SYS_IOSPACE_DISABLE, (sysarg_t) &arg); 139 220 } 140 221 … … 221 302 size_t pages = SIZE2PAGES(offset + size); 222 303 223 void *virt_page ;304 void *virt_page = AS_AREA_ANY; 224 305 int rc = physmem_map(phys_frame, pages, 225 306 AS_AREA_READ | AS_AREA_WRITE, &virt_page); … … 231 312 } 232 313 314 /** Disable PIO for specified I/O range. 315 * 316 * @param virt I/O start address. 317 * @param size Size of the I/O region. 318 * 319 * @return EOK on success. 320 * @return Negative error code on failure. 321 * 322 */ 323 int pio_disable(void *virt, size_t size) 324 { 325 #ifdef IO_SPACE_BOUNDARY 326 if (virt < IO_SPACE_BOUNDARY) 327 return iospace_disable(task_get_id(), virt, size); 328 #else 329 (void) iospace_disable; 330 #endif 331 return physmem_unmap(virt); 332 } 333 233 334 void pio_write_8(ioport8_t *reg, uint8_t val) 234 335 { … … 270 371 } 271 372 272 /** Register IRQ notification.273 *274 * @param inr IRQ number.275 * @param devno Device number of the device generating inr.276 * @param method Use this method for notifying me.277 * @param ucode Top-half pseudocode handler.278 *279 * @return Value returned by the kernel.280 *281 */282 int irq_register(int inr, int devno, int method, const irq_code_t *ucode)283 {284 return __SYSCALL4(SYS_IRQ_REGISTER, inr, devno, method,285 (sysarg_t) ucode);286 }287 288 /** Unregister IRQ notification.289 *290 * @param inr IRQ number.291 * @param devno Device number of the device generating inr.292 *293 * @return Value returned by the kernel.294 *295 */296 int irq_unregister(int inr, int devno)297 {298 return __SYSCALL2(SYS_IRQ_UNREGISTER, inr, devno);299 }300 301 373 /** @} 302 374 */ -
uspace/lib/c/generic/device/clock_dev.c
r3eb0c85 r8e7c9fe 27 27 */ 28 28 29 /** @addtogroup libc29 /** @addtogroup libc 30 30 * @{ 31 31 */ -
uspace/lib/c/generic/device/led_dev.c
r3eb0c85 r8e7c9fe 1 1 /* 2 * Copyright (c) 201 1 Jan Vesely2 * Copyright (c) 2014 Martin Decky 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvmouse 28 29 /** @addtogroup libc 29 30 * @{ 30 31 */ 31 32 /** @file 32 * @brief ps/2 mouse driver.33 33 */ 34 34 35 #ifndef _CHARDEV_H_ 36 #define _CHARDEV_H_ 35 #include <errno.h> 36 #include <async.h> 37 #include <io/pixel.h> 38 #include <ipc/dev_iface.h> 39 #include <device/led_dev.h> 37 40 38 #include <libarch/types.h> 39 #include <async.h> 41 int led_dev_color_set(async_sess_t *sess, pixel_t pixel) 42 { 43 async_exch_t *exch = async_exchange_begin(sess); 44 45 aid_t req = async_send_2(exch, DEV_IFACE_ID(LED_DEV_IFACE), 46 LED_DEV_COLOR_SET, (sysarg_t) pixel, NULL); 47 48 async_exchange_end(exch); 49 50 sysarg_t rc; 51 async_wait_for(req, &rc); 52 53 return (int) rc; 54 } 40 55 41 ssize_t chardev_read(async_exch_t *, void *, size_t); 42 ssize_t chardev_write(async_exch_t *, const void *, size_t); 43 44 #endif 45 /** 46 * @} 56 /** @} 47 57 */ -
uspace/lib/c/generic/event.c
r3eb0c85 r8e7c9fe 38 38 39 39 #include <libc.h> 40 #include < event.h>40 #include <ipc/event.h> 41 41 42 /** Subscribe event notifications.42 /** Subscribe to event notifications. 43 43 * 44 44 * @param evno Event type to subscribe. … … 48 48 * 49 49 */ 50 int event_subscribe(event_type_t evno, sysarg_t imethod)50 int ipc_event_subscribe(event_type_t evno, sysarg_t imethod) 51 51 { 52 return __SYSCALL2(SYS_ EVENT_SUBSCRIBE, (sysarg_t) evno,52 return __SYSCALL2(SYS_IPC_EVENT_SUBSCRIBE, (sysarg_t) evno, 53 53 (sysarg_t) imethod); 54 54 } 55 55 56 int event_task_subscribe(event_task_type_t evno, sysarg_t imethod) 56 /** Subscribe to task event notifications. 57 * 58 * @param evno Event type to subscribe. 59 * @param imethod Use this interface and method for notifying me. 60 * 61 * @return Value returned by the kernel. 62 * 63 */ 64 int ipc_event_task_subscribe(event_task_type_t evno, sysarg_t imethod) 57 65 { 58 return __SYSCALL2(SYS_ EVENT_SUBSCRIBE, (sysarg_t) evno,66 return __SYSCALL2(SYS_IPC_EVENT_SUBSCRIBE, (sysarg_t) evno, 59 67 (sysarg_t) imethod); 68 } 69 70 /** Unsubscribe from event notifications. 71 * 72 * @param evno Event type to unsubscribe. 73 * 74 * @return Value returned by the kernel. 75 * 76 */ 77 int ipc_event_unsubscribe(event_type_t evno) 78 { 79 return __SYSCALL1(SYS_IPC_EVENT_UNSUBSCRIBE, (sysarg_t) evno); 80 } 81 82 /** Unsubscribe from task event notifications. 83 * 84 * @param evno Event type to unsubscribe. 85 * 86 * @return Value returned by the kernel. 87 * 88 */ 89 int ipc_event_task_unsubscribe(event_task_type_t evno) 90 { 91 return __SYSCALL1(SYS_IPC_EVENT_UNSUBSCRIBE, (sysarg_t) evno); 60 92 } 61 93 … … 67 99 * 68 100 */ 69 int event_unmask(event_type_t evno)101 int ipc_event_unmask(event_type_t evno) 70 102 { 71 return __SYSCALL1(SYS_ EVENT_UNMASK, (sysarg_t) evno);103 return __SYSCALL1(SYS_IPC_EVENT_UNMASK, (sysarg_t) evno); 72 104 } 73 105 74 int event_task_unmask(event_task_type_t evno) 106 /** Unmask task event notifications. 107 * 108 * @param evno Event type to unmask. 109 * 110 * @return Value returned by the kernel. 111 * 112 */ 113 int ipc_event_task_unmask(event_task_type_t evno) 75 114 { 76 return __SYSCALL1(SYS_ EVENT_UNMASK, (sysarg_t) evno);115 return __SYSCALL1(SYS_IPC_EVENT_UNMASK, (sysarg_t) evno); 77 116 } 78 117 -
uspace/lib/c/generic/fibril.c
r3eb0c85 r8e7c9fe 59 59 static LIST_INITIALIZE(serialized_list); 60 60 static LIST_INITIALIZE(manager_list); 61 static LIST_INITIALIZE(fibril_list); 61 62 62 63 /** Number of threads that are executing a manager fibril. */ … … 116 117 117 118 fibril->waits_for = NULL; 119 list_append(&fibril->all_link, &fibril_list); 118 120 119 121 return fibril; … … 122 124 void fibril_teardown(fibril_t *fibril) 123 125 { 126 list_remove(&fibril->all_link); 124 127 tls_free(fibril->tcb); 125 128 free(fibril); -
uspace/lib/c/generic/fibril_synch.c
r3eb0c85 r8e7c9fe 448 448 int rc; 449 449 450 fibril_mutex_lock(&timer->lock); 451 452 while (true) { 453 while (timer->state != fts_active && 454 timer->state != fts_cleanup) { 455 456 if (timer->state == fts_cleanup) 457 break; 458 459 fibril_condvar_wait(&timer->cv, &timer->lock); 450 fibril_mutex_lock(timer->lockp); 451 452 while (timer->state != fts_cleanup) { 453 switch (timer->state) { 454 case fts_not_set: 455 case fts_fired: 456 fibril_condvar_wait(&timer->cv, timer->lockp); 457 break; 458 case fts_active: 459 rc = fibril_condvar_wait_timeout(&timer->cv, 460 timer->lockp, timer->delay); 461 if (rc == ETIMEOUT && timer->state == fts_active) { 462 timer->state = fts_fired; 463 timer->handler_running = true; 464 fibril_mutex_unlock(timer->lockp); 465 timer->fun(timer->arg); 466 fibril_mutex_lock(timer->lockp); 467 timer->handler_running = false; 468 } 469 break; 470 case fts_cleanup: 471 case fts_clean: 472 assert(false); 473 break; 460 474 } 461 462 if (timer->state == fts_cleanup) 463 break; 464 465 rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock, 466 timer->delay); 467 if (rc == ETIMEOUT) { 468 timer->state = fts_fired; 469 fibril_mutex_unlock(&timer->lock); 470 timer->fun(timer->arg); 471 fibril_mutex_lock(&timer->lock); 472 } 473 } 474 475 fibril_mutex_unlock(&timer->lock); 475 } 476 477 /* Acknowledge timer fibril has finished cleanup. */ 478 timer->state = fts_clean; 479 fibril_mutex_unlock(timer->lockp); 480 free(timer); 481 476 482 return 0; 477 483 } … … 481 487 * @return New timer on success, @c NULL if out of memory. 482 488 */ 483 fibril_timer_t *fibril_timer_create( void)489 fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock) 484 490 { 485 491 fid_t fid; … … 501 507 timer->fibril = fid; 502 508 timer->state = fts_not_set; 509 timer->lockp = (lock != NULL) ? lock : &timer->lock; 503 510 504 511 fibril_add_ready(fid); 505 506 512 return timer; 507 513 } … … 513 519 void fibril_timer_destroy(fibril_timer_t *timer) 514 520 { 515 fibril_mutex_lock(&timer->lock); 516 assert(timer->state != fts_active); 521 fibril_mutex_lock(timer->lockp); 522 assert(timer->state == fts_not_set || timer->state == fts_fired); 523 524 /* Request timer fibril to terminate. */ 517 525 timer->state = fts_cleanup; 518 526 fibril_condvar_broadcast(&timer->cv); 519 fibril_mutex_unlock( &timer->lock);527 fibril_mutex_unlock(timer->lockp); 520 528 } 521 529 … … 533 541 fibril_timer_fun_t fun, void *arg) 534 542 { 535 fibril_mutex_lock(&timer->lock); 543 fibril_mutex_lock(timer->lockp); 544 fibril_timer_set_locked(timer, delay, fun, arg); 545 fibril_mutex_unlock(timer->lockp); 546 } 547 548 /** Set locked timer. 549 * 550 * Set timer to execute a callback function after the specified 551 * interval. Must be called when the timer is locked. 552 * 553 * @param timer Timer 554 * @param delay Delay in microseconds 555 * @param fun Callback function 556 * @param arg Argument for @a fun 557 */ 558 void fibril_timer_set_locked(fibril_timer_t *timer, suseconds_t delay, 559 fibril_timer_fun_t fun, void *arg) 560 { 561 assert(fibril_mutex_is_locked(timer->lockp)); 562 assert(timer->state == fts_not_set || timer->state == fts_fired); 536 563 timer->state = fts_active; 537 564 timer->delay = delay; … … 539 566 timer->arg = arg; 540 567 fibril_condvar_broadcast(&timer->cv); 541 fibril_mutex_unlock(&timer->lock);542 568 } 543 569 … … 557 583 fibril_timer_state_t old_state; 558 584 559 fibril_mutex_lock(&timer->lock); 585 fibril_mutex_lock(timer->lockp); 586 old_state = fibril_timer_clear_locked(timer); 587 fibril_mutex_unlock(timer->lockp); 588 589 return old_state; 590 } 591 592 /** Clear locked timer. 593 * 594 * Clears (cancels) timer and returns last state of the timer. 595 * This can be one of: 596 * - fts_not_set If the timer has not been set or has been cleared 597 * - fts_active Timer was set but did not fire 598 * - fts_fired Timer fired 599 * Must be called when the timer is locked. 600 * 601 * @param timer Timer 602 * @return Last timer state 603 */ 604 fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *timer) 605 { 606 fibril_timer_state_t old_state; 607 608 assert(fibril_mutex_is_locked(timer->lockp)); 609 610 while (timer->handler_running) 611 fibril_condvar_wait(&timer->cv, timer->lockp); 612 560 613 old_state = timer->state; 561 614 timer->state = fts_not_set; … … 565 618 timer->arg = NULL; 566 619 fibril_condvar_broadcast(&timer->cv); 567 fibril_mutex_unlock(&timer->lock);568 620 569 621 return old_state; -
uspace/lib/c/generic/inet.c
r3eb0c85 r8e7c9fe 1 1 /* 2 * Copyright (c) 201 2Jiri Svoboda2 * Copyright (c) 2013 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 34 34 #include <ipc/services.h> 35 35 #include <loc.h> 36 #include <stdlib.h> 36 37 37 38 static void inet_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg); … … 224 225 225 226 rc = inet_ev_ops->recv(&dgram); 227 free(dgram.data); 226 228 async_answer_0(iid, rc); 227 229 } -
uspace/lib/c/generic/io/asprintf.c
r3eb0c85 r8e7c9fe 76 76 * the newly allocated string. 77 77 * @fmt Format string. 78 * @args Variable argument list 79 * 80 * @return Number of characters printed or a negative error code. 81 * 82 */ 83 int vasprintf(char **strp, const char *fmt, va_list args) 84 { 85 va_list args2; 86 va_copy(args2, args); 87 int ret = vprintf_size(fmt, args2); 88 va_end(args2); 89 90 if (ret > 0) { 91 *strp = malloc(STR_BOUNDS(ret) + 1); 92 if (*strp == NULL) 93 return -1; 94 95 vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args); 96 } 97 98 return ret; 99 } 100 101 /** Allocate and print to string. 102 * 103 * @param strp Address of the pointer where to store the address of 104 * the newly allocated string. 105 * @fmt Format string. 78 106 * 79 107 * @return Number of characters printed or a negative error code. … … 84 112 va_list args; 85 113 va_start(args, fmt); 86 int ret = v printf_size(fmt, args);114 int ret = vasprintf(strp, fmt, args); 87 115 va_end(args); 88 89 if (ret > 0) {90 *strp = malloc(STR_BOUNDS(ret) + 1);91 if (*strp == NULL)92 return -1;93 94 va_start(args, fmt);95 vsnprintf(*strp, STR_BOUNDS(ret) + 1, fmt, args);96 va_end(args);97 }98 116 99 117 return ret; -
uspace/lib/c/generic/io/chardev.c
r3eb0c85 r8e7c9fe 29 29 #include <errno.h> 30 30 #include <mem.h> 31 #include <ipc/dev_iface.h> 32 #include <ddf/log.h> 33 34 #include "chardev.h" 35 36 // TODO make this shared 37 enum { 38 IPC_CHAR_READ = DEV_FIRST_CUSTOM_METHOD, 39 IPC_CHAR_WRITE, 40 }; 31 #include <io/chardev.h> 32 #include <ipc/chardev.h> 41 33 42 34 ssize_t chardev_read(async_exch_t *exch, void *data, size_t size) … … 48 40 49 41 sysarg_t message[4] = { 0 }; 50 const ssize_t ret = async_req_1_4(exch, IPC_CHAR_READ, size,42 const ssize_t ret = async_req_1_4(exch, CHARDEV_READ, size, 51 43 &message[0], &message[1], &message[2], &message[3]); 52 44 if (ret > 0 && (size_t)ret <= size) … … 64 56 sysarg_t message[3] = { 0 }; 65 57 memcpy(message, data, size); 66 return async_req_4_0(exch, IPC_CHAR_WRITE, size,58 return async_req_4_0(exch, CHARDEV_WRITE, size, 67 59 message[0], message[1], message[2]); 68 60 } -
uspace/lib/c/generic/io/console.c
r3eb0c85 r8e7c9fe 75 75 bool console_kcon(void) 76 76 { 77 return __SYSCALL0(SYS_DEBUG_ ACTIVATE_CONSOLE);77 return __SYSCALL0(SYS_DEBUG_CONSOLE); 78 78 } 79 79 -
uspace/lib/c/generic/io/input.c
r3eb0c85 r8e7c9fe 80 80 } 81 81 82 int input_ yield(input_t *input)82 int input_activate(input_t *input) 83 83 { 84 84 async_exch_t *exch = async_exchange_begin(input->sess); 85 86 int rc = async_req_0_0(exch, INPUT_YIELD); 85 int rc = async_req_0_0(exch, INPUT_ACTIVATE); 87 86 async_exchange_end(exch); 88 87 89 88 return rc; 90 89 } 91 90 92 int input_reclaim(input_t *input) 93 { 94 async_exch_t *exch = async_exchange_begin(input->sess); 95 96 int rc = async_req_0_0(exch, INPUT_RECLAIM); 97 async_exchange_end(exch); 98 99 return rc; 91 static void input_ev_active(input_t *input, ipc_callid_t callid, 92 ipc_call_t *call) 93 { 94 int rc = input->ev_ops->active(input); 95 async_answer_0(callid, rc); 96 } 97 98 static void input_ev_deactive(input_t *input, ipc_callid_t callid, 99 ipc_call_t *call) 100 { 101 int rc = input->ev_ops->deactive(input); 102 async_answer_0(callid, rc); 100 103 } 101 104 … … 178 181 179 182 switch (IPC_GET_IMETHOD(call)) { 183 case INPUT_EVENT_ACTIVE: 184 input_ev_active(input, callid, &call); 185 break; 186 case INPUT_EVENT_DEACTIVE: 187 input_ev_deactive(input, callid, &call); 188 break; 180 189 case INPUT_EVENT_KEY: 181 190 input_ev_key(input, callid, &call); -
uspace/lib/c/generic/iplink.c
r3eb0c85 r8e7c9fe 171 171 } 172 172 173 int iplink_set_mac48(iplink_t *iplink, addr48_t mac) 174 { 175 async_exch_t *exch = async_exchange_begin(iplink->sess); 176 177 ipc_call_t answer; 178 aid_t req = async_send_0(exch, IPLINK_GET_MAC48, &answer); 179 180 int rc = async_data_read_start(exch, mac, sizeof(addr48_t)); 181 182 loc_exchange_end(exch); 183 184 if (rc != EOK) { 185 async_forget(req); 186 return rc; 187 } 188 189 sysarg_t retval; 190 async_wait_for(req, &retval); 191 192 return (int) retval; 193 } 194 195 173 196 int iplink_addr_add(iplink_t *iplink, inet_addr_t *addr) 174 197 { … … 230 253 free(sdu.data); 231 254 async_answer_0(iid, rc); 255 } 256 257 static void iplink_ev_change_addr(iplink_t *iplink, ipc_callid_t iid, 258 ipc_call_t *icall) 259 { 260 addr48_t *addr; 261 size_t size; 262 263 int rc = async_data_write_accept((void **)&addr, false, 264 sizeof(addr48_t), sizeof(addr48_t), 0, &size); 265 if (rc != EOK) { 266 async_answer_0(iid, rc); 267 return; 268 } 269 270 rc = iplink->ev_ops->change_addr(iplink, *addr); 271 free(addr); 272 async_answer_0(iid, EOK); 232 273 } 233 274 … … 249 290 iplink_ev_recv(iplink, callid, &call); 250 291 break; 292 case IPLINK_EV_CHANGE_ADDR: 293 iplink_ev_change_addr(iplink, callid, &call); 251 294 default: 252 295 async_answer_0(callid, ENOTSUP); -
uspace/lib/c/generic/iplink_srv.c
r3eb0c85 r8e7c9fe 81 81 } 82 82 83 static void iplink_set_mac48_srv(iplink_srv_t *srv, ipc_callid_t iid, 84 ipc_call_t *icall) 85 { 86 int rc; 87 size_t size; 88 addr48_t mac; 89 ipc_callid_t callid; 90 91 rc = async_data_write_receive(&callid, &size); 92 if (rc != EOK) { 93 async_answer_0(callid, (sysarg_t) rc); 94 async_answer_0(iid, (sysarg_t) rc); 95 } 96 97 rc = srv->ops->set_mac48(srv, &mac); 98 if (rc != EOK) { 99 async_answer_0(iid, rc); 100 return; 101 } 102 103 rc = async_data_read_finalize(callid, &mac, sizeof(addr48_t)); 104 if (rc != EOK) 105 async_answer_0(callid, rc); 106 107 async_answer_0(iid, (sysarg_t) rc); 108 } 109 83 110 static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid, 84 111 ipc_call_t *icall) … … 252 279 iplink_get_mac48_srv(srv, callid, &call); 253 280 break; 281 case IPLINK_SET_MAC48: 282 iplink_set_mac48_srv(srv, callid, &call); 283 break; 254 284 case IPLINK_SEND: 255 285 iplink_send_srv(srv, callid, &call); … … 300 330 } 301 331 332 int iplink_ev_change_addr(iplink_srv_t *srv, addr48_t *addr) 333 { 334 if (srv->client_sess == NULL) 335 return EIO; 336 337 async_exch_t *exch = async_exchange_begin(srv->client_sess); 338 339 ipc_call_t answer; 340 aid_t req = async_send_0(exch, IPLINK_EV_CHANGE_ADDR, &answer); 341 342 int rc = async_data_write_start(exch, addr, sizeof(addr48_t)); 343 async_exchange_end(exch); 344 345 if (rc != EOK) { 346 async_forget(req); 347 return rc; 348 } 349 350 sysarg_t retval; 351 async_wait_for(req, &retval); 352 if (retval != EOK) 353 return retval; 354 355 return EOK; 356 } 357 302 358 /** @} 303 359 */ -
uspace/lib/c/generic/irq.c
r3eb0c85 r8e7c9fe 1 1 /* 2 * Copyright (c) 20 05 Jakub Jermar2 * Copyright (c) 2014 Martin Decky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup mips64mm29 /** @addtogroup libc 30 30 * @{ 31 31 */ … … 33 33 */ 34 34 35 #include <arch/mm/as.h> 36 #include <genarch/mm/as_ht.h> 37 #include <genarch/mm/page_ht.h> 38 #include <genarch/mm/asid_fifo.h> 39 #include <arch/mm/tlb.h> 40 #include <mm/tlb.h> 41 #include <mm/as.h> 42 #include <arch/cp0.h> 35 #include <ipc/irq.h> 36 #include <libc.h> 43 37 44 /** Architecture dependent address space init. */ 45 void as_arch_init(void) 38 /** Subscribe to IRQ notification. 39 * 40 * @param inr IRQ number. 41 * @param devno Device number of the device generating inr. 42 * @param method Use this method for notifying me. 43 * @param ucode Top-half pseudocode handler. 44 * 45 * @return Value returned by the kernel. 46 * 47 */ 48 int ipc_irq_subscribe(int inr, int devno, sysarg_t method, 49 const irq_code_t *ucode) 46 50 { 47 as_operations = &as_ht_operations;48 asid_fifo_init();51 return __SYSCALL4(SYS_IPC_IRQ_SUBSCRIBE, inr, devno, method, 52 (sysarg_t) ucode); 49 53 } 50 54 51 /** Install address space.55 /** Unsubscribe from IRQ notification. 52 56 * 53 * Install ASID. 57 * @param inr IRQ number. 58 * @param devno Device number of the device generating inr. 54 59 * 55 * @ param as Address space structure.60 * @return Value returned by the kernel. 56 61 * 57 62 */ 58 void as_install_arch(as_t *as)63 int ipc_irq_unsubscribe(int inr, int devno) 59 64 { 60 /* 61 * Install ASID. 62 */ 63 entry_hi_t hi; 64 hi.value = cp0_entry_hi_read(); 65 hi.asid = as->asid; 66 cp0_entry_hi_write(hi.value); 65 return __SYSCALL2(SYS_IPC_IRQ_UNSUBSCRIBE, inr, devno); 67 66 } 68 67 -
uspace/lib/c/generic/stacktrace.c
r3eb0c85 r8e7c9fe 42 42 static int stacktrace_read_uintptr(void *arg, uintptr_t addr, uintptr_t *data); 43 43 44 void stacktrace_print_fp_pc(uintptr_t fp, uintptr_t pc) 44 static stacktrace_ops_t basic_ops = { 45 .read_uintptr = stacktrace_read_uintptr 46 }; 47 48 void stacktrace_print_generic(stacktrace_ops_t *ops, void *arg, uintptr_t fp, 49 uintptr_t pc) 45 50 { 46 51 stacktrace_t st; 47 52 uintptr_t nfp; 53 int rc; 48 54 49 st.op_arg = NULL;50 st. read_uintptr = stacktrace_read_uintptr;55 st.op_arg = arg; 56 st.ops = ops; 51 57 52 58 while (stacktrace_fp_valid(&st, fp)) { 53 59 printf("%p: %p()\n", (void *) fp, (void *) pc); 54 (void) stacktrace_ra_get(&st, fp, &pc); 55 (void) stacktrace_fp_prev(&st, fp, &nfp); 60 rc = stacktrace_ra_get(&st, fp, &pc); 61 if (rc != EOK) 62 break; 63 rc = stacktrace_fp_prev(&st, fp, &nfp); 64 if (rc != EOK) 65 break; 56 66 fp = nfp; 57 67 } 68 } 69 70 void stacktrace_print_fp_pc(uintptr_t fp, uintptr_t pc) 71 { 72 stacktrace_print_generic(&basic_ops, NULL, fp, pc); 58 73 } 59 74 -
uspace/lib/c/generic/str.c
r3eb0c85 r8e7c9fe 1360 1360 } 1361 1361 1362 char *strtok(char *s, const char *delim) 1363 { 1364 static char *next; 1365 1366 return strtok_r(s, delim, &next); 1367 } 1368 1369 char *strtok_r(char *s, const char *delim, char **next) 1362 /** Split string by delimiters. 1363 * 1364 * @param s String to be tokenized. May not be NULL. 1365 * @param delim String with the delimiters. 1366 * @param next Variable which will receive the pointer to the 1367 * continuation of the string following the first 1368 * occurrence of any of the delimiter characters. 1369 * May be NULL. 1370 * @return Pointer to the prefix of @a s before the first 1371 * delimiter character. NULL if no such prefix 1372 * exists. 1373 */ 1374 char *str_tok(char *s, const char *delim, char **next) 1370 1375 { 1371 1376 char *start, *end; 1372 1377 1373 if (s == NULL) 1374 s = *next; 1378 if (!s) 1379 return NULL; 1380 1381 size_t len = str_size(s); 1382 size_t cur; 1383 size_t tmp; 1384 wchar_t ch; 1375 1385 1376 1386 /* Skip over leading delimiters. */ 1377 while (*s && (str_chr(delim, *s) != NULL)) ++s; 1378 start = s; 1387 for (tmp = cur = 0; 1388 (ch = str_decode(s, &tmp, len)) && str_chr(delim, ch); /**/) 1389 cur = tmp; 1390 start = &s[cur]; 1379 1391 1380 1392 /* Skip over token characters. */ 1381 while (*s && (str_chr(delim, *s) == NULL)) ++s; 1382 end = s; 1383 *next = (*s ? s + 1 : s); 1384 1385 if (start == end) { 1393 for (tmp = cur; 1394 (ch = str_decode(s, &tmp, len)) && !str_chr(delim, ch); /**/) 1395 cur = tmp; 1396 end = &s[cur]; 1397 if (next) 1398 *next = (ch ? &s[tmp] : &s[cur]); 1399 1400 if (start == end) 1386 1401 return NULL; /* No more tokens. */ 1387 }1388 1402 1389 1403 /* Overwrite delimiter with NULL terminator. */ -
uspace/lib/c/generic/task.c
r3eb0c85 r8e7c9fe 2 2 * Copyright (c) 2006 Jakub Jermar 3 3 * Copyright (c) 2008 Jiri Svoboda 4 * Copyright (c) 2014 Martin Sucha 4 5 * All rights reserved. 5 6 * … … 94 95 * 95 96 * @param id If not NULL, the ID of the task is stored here on success. 97 * @param wait If not NULL, setup waiting for task's return value and store 98 * the information necessary for waiting here on success. 96 99 * @param path Pathname of the binary to execute. 97 100 * @param argv Command-line arguments. … … 100 103 * 101 104 */ 102 int task_spawnv(task_id_t *id, const char *path, const char *const args[]) 105 int task_spawnv(task_id_t *id, task_wait_t *wait, const char *path, 106 const char *const args[]) 103 107 { 104 108 /* Send default files */ … … 125 129 files[3] = NULL; 126 130 127 return task_spawnvf(id, path, args, files);131 return task_spawnvf(id, wait, path, args, files); 128 132 } 129 133 … … 135 139 * 136 140 * @param id If not NULL, the ID of the task is stored here on success. 141 * @param wait If not NULL, setup waiting for task's return value and store 142 * the information necessary for waiting here on success. 137 143 * @param path Pathname of the binary to execute. 138 144 * @param argv Command-line arguments. … … 142 148 * 143 149 */ 144 int task_spawnvf(task_id_t *id, const char *path, const char *const args[],145 int *const files[])150 int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path, 151 const char *const args[], int *const files[]) 146 152 { 147 153 /* Connect to a program loader. */ … … 150 156 return EREFUSED; 151 157 158 bool wait_initialized = false; 159 152 160 /* Get task ID. */ 153 161 task_id_t task_id; … … 181 189 goto error; 182 190 191 /* Setup waiting for return value if needed */ 192 if (wait) { 193 rc = task_setup_wait(task_id, wait); 194 if (rc != EOK) 195 goto error; 196 wait_initialized = true; 197 } 198 183 199 /* Run it. */ 184 200 rc = loader_run(ldr); … … 193 209 194 210 error: 211 if (wait_initialized) 212 task_cancel_wait(wait); 213 195 214 /* Error exit */ 196 215 loader_abort(ldr); … … 204 223 * 205 224 * @param id If not NULL, the ID of the task is stored here on success. 225 * @param wait If not NULL, setup waiting for task's return value and store 226 * the information necessary for waiting here on success. 206 227 * @param path Pathname of the binary to execute. 207 228 * @param cnt Number of arguments. … … 211 232 * 212 233 */ 213 int task_spawn(task_id_t *task_id, const char *path, int cnt, va_list ap) 234 int task_spawn(task_id_t *task_id, task_wait_t *wait, const char *path, 235 int cnt, va_list ap) 214 236 { 215 237 /* Allocate argument list. */ … … 227 249 228 250 /* Spawn task. */ 229 int rc = task_spawnv(task_id, path, arglist);251 int rc = task_spawnv(task_id, wait, path, arglist); 230 252 231 253 /* Free argument list. */ … … 240 262 * 241 263 * @param id If not NULL, the ID of the task is stored here on success. 264 * @param wait If not NULL, setup waiting for task's return value and store 265 * the information necessary for waiting here on success. 242 266 * @param path Pathname of the binary to execute. 243 267 * @param ... Command-line arguments. … … 246 270 * 247 271 */ 248 int task_spawnl(task_id_t *task_id, const char *path, ...)272 int task_spawnl(task_id_t *task_id, task_wait_t *wait, const char *path, ...) 249 273 { 250 274 /* Count the number of arguments. */ … … 262 286 263 287 va_start(ap, path); 264 int rc = task_spawn(task_id, path, cnt, ap);288 int rc = task_spawn(task_id, wait, path, cnt, ap); 265 289 va_end(ap); 266 290 … … 268 292 } 269 293 270 int task_wait(task_id_t id, task_exit_t *texit, int *retval) 294 /** Setup waiting for a task. 295 * 296 * If the task finishes after this call succeeds, it is guaranteed that 297 * task_wait(wait, &texit, &retval) will return correct return value for 298 * the task. 299 * 300 * @param id ID of the task to setup waiting for. 301 * @param wait Information necessary for the later task_wait call is stored here. 302 * 303 * @return EOK on success, else error code. 304 */ 305 int task_setup_wait(task_id_t id, task_wait_t *wait) 306 { 307 async_exch_t *exch = async_exchange_begin(session_ns); 308 wait->aid = async_send_2(exch, NS_TASK_WAIT, LOWER32(id), UPPER32(id), 309 &wait->result); 310 async_exchange_end(exch); 311 312 return EOK; 313 } 314 315 /** Cancel waiting for a task. 316 * 317 * This can be called *instead of* task_wait if the caller is not interested 318 * in waiting for the task anymore. 319 * 320 * This function cannot be called if the task_wait was already called. 321 * 322 * @param wait task_wait_t previously initialized by task_setup_wait. 323 */ 324 void task_cancel_wait(task_wait_t *wait) { 325 async_forget(wait->aid); 326 } 327 328 /** Wait for a task to finish. 329 * 330 * This function returns correct values even if the task finished in 331 * between task_setup_wait and this task_wait call. 332 * 333 * This function cannot be called more than once with the same task_wait_t 334 * (it can be reused, but must be reinitialized with task_setup_wait first) 335 * 336 * @param wait task_wait_t previously initialized by task_setup_wait. 337 * @param texit Store type of task exit here. 338 * @param retval Store return value of the task here. 339 * 340 * @return EOK on success, else error code. 341 */ 342 int task_wait(task_wait_t *wait, task_exit_t *texit, int *retval) 271 343 { 272 344 assert(texit); 273 345 assert(retval); 274 275 async_exch_t *exch = async_exchange_begin(session_ns); 276 sysarg_t te, rv; 277 int rc = (int) async_req_2_2(exch, NS_TASK_WAIT, LOWER32(id), 278 UPPER32(id), &te, &rv); 279 async_exchange_end(exch); 280 281 *texit = te; 282 *retval = rv; 283 284 return rc; 346 347 sysarg_t rc; 348 async_wait_for(wait->aid, &rc); 349 350 if (rc == EOK) { 351 *texit = IPC_GET_ARG1(wait->result); 352 *retval = IPC_GET_ARG2(wait->result); 353 } 354 355 return rc; 356 } 357 358 /** Wait for a task to finish by its id. 359 * 360 * Note that this will fail with ENOENT if the task id is not registered in ns 361 * (e.g. if the task finished). If you are spawning a task and need to wait 362 * for its completion, use wait parameter of the task_spawn* functions instead 363 * to prevent a race where the task exits before you may have a chance to wait 364 * wait for it. 365 * 366 * @param id ID of the task to wait for. 367 * @param texit Store type of task exit here. 368 * @param retval Store return value of the task here. 369 * 370 * @return EOK on success, else error code. 371 */ 372 int task_wait_task_id(task_id_t id, task_exit_t *texit, int *retval) 373 { 374 task_wait_t wait; 375 int rc = task_setup_wait(id, &wait); 376 if (rc != EOK) 377 return rc; 378 379 return task_wait(&wait, texit, retval); 285 380 } 286 381 -
uspace/lib/c/generic/time.c
r3eb0c85 r8e7c9fe 555 555 } 556 556 557 void *addr ;557 void *addr = AS_AREA_ANY; 558 558 rc = physmem_map(faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE, 559 559 &addr);
Note:
See TracChangeset
for help on using the changeset viewer.
