Changeset 8e7c9fe in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2014-09-12T03:45:25Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
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.
Message:

merge mainline changes

most usb changes were reverted. blink and usbmass were fixed
known problems:
ehci won't initialize
usbmast asserts on unmount (happens on mainline too)

Location:
uspace/lib/c/generic
Files:
2 added
19 edited
3 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/adt/hash_table.c

    r3eb0c85 r8e7c9fe  
    370370                         */
    371371                        if (!f(cur_link, arg))
    372                                 return;
    373                 }
    374         }
    375        
     372                                goto out;
     373                }
     374        }
     375out:
    376376        h->apply_ongoing = false;
    377377       
  • uspace/lib/c/generic/async.c

    r3eb0c85 r8e7c9fe  
    101101#undef LIBC_ASYNC_C_
    102102
     103#include <ipc/irq.h>
     104#include <ipc/event.h>
    103105#include <futex.h>
    104106#include <fibril.h>
     
    116118#include "private/libc.h"
    117119
    118 
    119120/** Session data */
    120121struct async_sess {
     
    242243        async_client_conn_t cfibril;
    243244} connection_t;
     245
     246/* Notification data */
     247typedef 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;
    244259
    245260/** Identifier of the incoming connection handled by the current fibril. */
     
    335350}
    336351
    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 
    350352static 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;
     353static size_t notification_handler_stksz = FIBRIL_DFLT_STK_SIZE;
    353354
    354355/** Setter for client_connection function pointer.
     
    363364}
    364365
    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.
    376367 *
    377368 * @param size Stack size in bytes.
    378369 */
    379 void async_set_interrupt_handler_stack_size(size_t size)
    380 {
    381         interrupt_handler_stksz = size;
     370void async_set_notification_handler_stack_size(size_t size)
     371{
     372        notification_handler_stksz = size;
    382373}
    383374
     
    399390static hash_table_t client_hash_table;
    400391static hash_table_t conn_hash_table;
     392static hash_table_t notification_hash_table;
    401393static LIST_INITIALIZE(timeout_list);
    402394
    403 static size_t client_key_hash(void *k)
    404 {
    405         task_id_t key = *(task_id_t*)k;
    406         return key;
     395static sysarg_t notification_avail = 0;
     396
     397static size_t client_key_hash(void *key)
     398{
     399        task_id_t in_task_id = *(task_id_t *) key;
     400        return in_task_id;
    407401}
    408402
     
    413407}
    414408
    415 static bool client_key_equal(void *k, const ht_link_t *item)
    416 {
    417         task_id_t key = *(task_id_t*)k;
     409static bool client_key_equal(void *key, const ht_link_t *item)
     410{
     411        task_id_t in_task_id = *(task_id_t *) key;
    418412        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}
    422415
    423416/** Operations for the client hash table. */
     
    439432static size_t conn_key_hash(void *key)
    440433{
    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;
    443436}
    444437
     
    451444static bool conn_key_equal(void *key, const ht_link_t *item)
    452445{
    453         sysarg_t in_phone_hash = *(sysarg_t*)key;
     446        sysarg_t in_phone_hash = *(sysarg_t *) key;
    454447        connection_t *conn = hash_table_get_inst(item, connection_t, link);
    455448        return (in_phone_hash == conn->in_phone_hash);
    456449}
    457 
    458450
    459451/** Operations for the connection hash table. */
     
    462454        .key_hash = conn_key_hash,
    463455        .key_equal = conn_key_equal,
     456        .equal = NULL,
     457        .remove_callback = NULL
     458};
     459
     460static size_t notification_key_hash(void *key)
     461{
     462        sysarg_t id = *(sysarg_t *) key;
     463        return id;
     464}
     465
     466static 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(&notification->imethod);
     471}
     472
     473static 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. */
     482static hash_table_ops_t notification_hash_table_ops = {
     483        .hash = notification_hash,
     484        .key_hash = notification_key_hash,
     485        .key_equal = notification_key_equal,
    464486        .equal = NULL,
    465487        .remove_callback = NULL
     
    511533        futex_down(&async_futex);
    512534       
    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) {
    516537                futex_up(&async_futex);
    517538                return false;
    518539        }
    519540       
    520         connection_t *conn = hash_table_get_inst(hlp, connection_t, link);
     541        connection_t *conn = hash_table_get_inst(link, connection_t, link);
    521542       
    522543        msg_t *msg = malloc(sizeof(*msg));
     
    553574 *
    554575 * 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.
    556578 *
    557579 * @param arg Message structure pointer.
     
    565587       
    566588        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(&notification_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);
    568607       
    569608        free(msg);
     
    571610}
    572611
    573 /** Process interrupt notification.
     612/** Process notification.
    574613 *
    575614 * A new fibril is created which would process the notification.
     
    598637       
    599638        fid_t fid = fibril_create_generic(notification_fibril, msg,
    600             interrupt_handler_stksz);
     639            notification_handler_stksz);
    601640        if (fid == 0) {
    602641                free(msg);
     
    609648        futex_up(&async_futex);
    610649        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 */
     663int 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(&notification_hash_table, &notification->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 */
     695int 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 */
     712int 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(&notification_hash_table, &notification->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 */
     745int 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(&notification_hash_table, &notification->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 */
     776int 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 */
     788int async_event_task_unmask(event_task_type_t evno)
     789{
     790        return ipc_event_task_unmask(evno);
    611791}
    612792
     
    702882
    703883        futex_down(&async_futex);
    704         ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id);
    705         if (lnk) {
    706                 client = hash_table_get_inst(lnk, 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);
    707887                atomic_inc(&client->refcnt);
    708888        } else if (create) {
     
    11061286       
    11071287        if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))
     1288                abort();
     1289       
     1290        if (!hash_table_create(&notification_hash_table, 0, 0,
     1291            &notification_hash_table_ops))
    11081292                abort();
    11091293       
  • uspace/lib/c/generic/bd.c

    r3eb0c85 r8e7c9fe  
    150150}
    151151
     152int 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
    152163int bd_get_block_size(bd_t *bd, size_t *rbsize)
    153164{
  • uspace/lib/c/generic/bd_srv.c

    r3eb0c85 r8e7c9fe  
    128128}
    129129
     130static 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
    130149static void bd_write_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
    131150    ipc_call_t *call)
     
    190209        bd_srv_t *srv;
    191210
    192         srv = calloc(1, sizeof(srv));
     211        srv = calloc(1, sizeof(bd_srv_t));
    193212        if (srv == NULL)
    194213                return NULL;
     
    244263                        bd_read_toc_srv(srv, callid, &call);
    245264                        break;
     265                case BD_SYNC_CACHE:
     266                        bd_sync_cache_srv(srv, callid, &call);
     267                        break;
    246268                case BD_WRITE_BLOCKS:
    247269                        bd_write_blocks_srv(srv, callid, &call);
  • uspace/lib/c/generic/ddi.c

    r3eb0c85 r8e7c9fe  
    7171 * @param flags Flags for the new address space area.
    7272 * @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.
    7779 * @return ENOMEM if there was some problem in creating
    7880 *         the address space area.
     
    8587}
    8688
     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 */
     99int 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 */
    87124int dmamem_map(void *virt, size_t size, unsigned int map_flags,
    88125    unsigned int flags, uintptr_t *phys)
     
    93130}
    94131
     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 */
    95152int dmamem_map_anonymous(size_t size, uintptr_t constraint,
    96153    unsigned int map_flags, unsigned int flags, uintptr_t *phys, void **virt)
     
    137194       
    138195        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 */
     211static 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);
    139220}
    140221
     
    221302        size_t pages = SIZE2PAGES(offset + size);
    222303       
    223         void *virt_page;
     304        void *virt_page = AS_AREA_ANY;
    224305        int rc = physmem_map(phys_frame, pages,
    225306            AS_AREA_READ | AS_AREA_WRITE, &virt_page);
     
    231312}
    232313
     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 */
     323int 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
    233334void pio_write_8(ioport8_t *reg, uint8_t val)
    234335{
     
    270371}
    271372
    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 
    301373/** @}
    302374 */
  • uspace/lib/c/generic/device/clock_dev.c

    r3eb0c85 r8e7c9fe  
    2727 */
    2828
    29  /** @addtogroup libc
     29/** @addtogroup libc
    3030 * @{
    3131 */
  • uspace/lib/c/generic/device/led_dev.c

    r3eb0c85 r8e7c9fe  
    11/*
    2  * Copyright (c) 2011 Jan Vesely
     2 * Copyright (c) 2014 Martin Decky
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvmouse
     28
     29/** @addtogroup libc
    2930 * @{
    3031 */
    3132/** @file
    32  * @brief ps/2 mouse driver.
    3333 */
    3434
    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>
    3740
    38 #include <libarch/types.h>
    39 #include <async.h>
     41int 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}
    4055
    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/** @}
    4757 */
  • uspace/lib/c/generic/event.c

    r3eb0c85 r8e7c9fe  
    3838
    3939#include <libc.h>
    40 #include <event.h>
     40#include <ipc/event.h>
    4141
    42 /** Subscribe event notifications.
     42/** Subscribe to event notifications.
    4343 *
    4444 * @param evno    Event type to subscribe.
     
    4848 *
    4949 */
    50 int event_subscribe(event_type_t evno, sysarg_t imethod)
     50int ipc_event_subscribe(event_type_t evno, sysarg_t imethod)
    5151{
    52         return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
     52        return __SYSCALL2(SYS_IPC_EVENT_SUBSCRIBE, (sysarg_t) evno,
    5353            (sysarg_t) imethod);
    5454}
    5555
    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 */
     64int ipc_event_task_subscribe(event_task_type_t evno, sysarg_t imethod)
    5765{
    58         return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
     66        return __SYSCALL2(SYS_IPC_EVENT_SUBSCRIBE, (sysarg_t) evno,
    5967            (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 */
     77int 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 */
     89int ipc_event_task_unsubscribe(event_task_type_t evno)
     90{
     91        return __SYSCALL1(SYS_IPC_EVENT_UNSUBSCRIBE, (sysarg_t) evno);
    6092}
    6193
     
    6799 *
    68100 */
    69 int event_unmask(event_type_t evno)
     101int ipc_event_unmask(event_type_t evno)
    70102{
    71         return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
     103        return __SYSCALL1(SYS_IPC_EVENT_UNMASK, (sysarg_t) evno);
    72104}
    73105
    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 */
     113int ipc_event_task_unmask(event_task_type_t evno)
    75114{
    76         return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
     115        return __SYSCALL1(SYS_IPC_EVENT_UNMASK, (sysarg_t) evno);
    77116}
    78117
  • uspace/lib/c/generic/fibril.c

    r3eb0c85 r8e7c9fe  
    5959static LIST_INITIALIZE(serialized_list);
    6060static LIST_INITIALIZE(manager_list);
     61static LIST_INITIALIZE(fibril_list);
    6162
    6263/** Number of threads that are executing a manager fibril. */
     
    116117       
    117118        fibril->waits_for = NULL;
     119        list_append(&fibril->all_link, &fibril_list);
    118120       
    119121        return fibril;
     
    122124void fibril_teardown(fibril_t *fibril)
    123125{
     126        list_remove(&fibril->all_link);
    124127        tls_free(fibril->tcb);
    125128        free(fibril);
  • uspace/lib/c/generic/fibril_synch.c

    r3eb0c85 r8e7c9fe  
    448448        int rc;
    449449
    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;
    460474                }
    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
    476482        return 0;
    477483}
     
    481487 * @return              New timer on success, @c NULL if out of memory.
    482488 */
    483 fibril_timer_t *fibril_timer_create(void)
     489fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock)
    484490{
    485491        fid_t fid;
     
    501507        timer->fibril = fid;
    502508        timer->state = fts_not_set;
     509        timer->lockp = (lock != NULL) ? lock : &timer->lock;
    503510
    504511        fibril_add_ready(fid);
    505 
    506512        return timer;
    507513}
     
    513519void fibril_timer_destroy(fibril_timer_t *timer)
    514520{
    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. */
    517525        timer->state = fts_cleanup;
    518526        fibril_condvar_broadcast(&timer->cv);
    519         fibril_mutex_unlock(&timer->lock);
     527        fibril_mutex_unlock(timer->lockp);
    520528}
    521529
     
    533541    fibril_timer_fun_t fun, void *arg)
    534542{
    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 */
     558void 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);
    536563        timer->state = fts_active;
    537564        timer->delay = delay;
     
    539566        timer->arg = arg;
    540567        fibril_condvar_broadcast(&timer->cv);
    541         fibril_mutex_unlock(&timer->lock);
    542568}
    543569
     
    557583        fibril_timer_state_t old_state;
    558584
    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 */
     604fibril_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
    560613        old_state = timer->state;
    561614        timer->state = fts_not_set;
     
    565618        timer->arg = NULL;
    566619        fibril_condvar_broadcast(&timer->cv);
    567         fibril_mutex_unlock(&timer->lock);
    568620
    569621        return old_state;
  • uspace/lib/c/generic/inet.c

    r3eb0c85 r8e7c9fe  
    11/*
    2  * Copyright (c) 2012 Jiri Svoboda
     2 * Copyright (c) 2013 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3434#include <ipc/services.h>
    3535#include <loc.h>
     36#include <stdlib.h>
    3637
    3738static void inet_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
     
    224225       
    225226        rc = inet_ev_ops->recv(&dgram);
     227        free(dgram.data);
    226228        async_answer_0(iid, rc);
    227229}
  • uspace/lib/c/generic/io/asprintf.c

    r3eb0c85 r8e7c9fe  
    7676 *             the newly allocated string.
    7777 * @fmt        Format string.
     78 * @args       Variable argument list
     79 *
     80 * @return Number of characters printed or a negative error code.
     81 *
     82 */
     83int 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.
    78106 *
    79107 * @return Number of characters printed or a negative error code.
     
    84112        va_list args;
    85113        va_start(args, fmt);
    86         int ret = vprintf_size(fmt, args);
     114        int ret = vasprintf(strp, fmt, args);
    87115        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         }
    98116       
    99117        return ret;
  • uspace/lib/c/generic/io/chardev.c

    r3eb0c85 r8e7c9fe  
    2929#include <errno.h>
    3030#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>
    4133
    4234ssize_t chardev_read(async_exch_t *exch, void *data, size_t size)
     
    4840
    4941        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,
    5143            &message[0], &message[1], &message[2], &message[3]);
    5244        if (ret > 0 && (size_t)ret <= size)
     
    6456        sysarg_t message[3] = { 0 };
    6557        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,
    6759            message[0], message[1], message[2]);
    6860}
  • uspace/lib/c/generic/io/console.c

    r3eb0c85 r8e7c9fe  
    7575bool console_kcon(void)
    7676{
    77         return __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
     77        return __SYSCALL0(SYS_DEBUG_CONSOLE);
    7878}
    7979
  • uspace/lib/c/generic/io/input.c

    r3eb0c85 r8e7c9fe  
    8080}
    8181
    82 int input_yield(input_t *input)
     82int input_activate(input_t *input)
    8383{
    8484        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);
    8786        async_exchange_end(exch);
    88 
     87       
    8988        return rc;
    9089}
    9190
    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;
     91static 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
     98static 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);
    100103}
    101104
     
    178181
    179182                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;
    180189                case INPUT_EVENT_KEY:
    181190                        input_ev_key(input, callid, &call);
  • uspace/lib/c/generic/iplink.c

    r3eb0c85 r8e7c9fe  
    171171}
    172172
     173int 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
    173196int iplink_addr_add(iplink_t *iplink, inet_addr_t *addr)
    174197{
     
    230253        free(sdu.data);
    231254        async_answer_0(iid, rc);
     255}
     256
     257static 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);
    232273}
    233274
     
    249290                        iplink_ev_recv(iplink, callid, &call);
    250291                        break;
     292                case IPLINK_EV_CHANGE_ADDR:
     293                        iplink_ev_change_addr(iplink, callid, &call);
    251294                default:
    252295                        async_answer_0(callid, ENOTSUP);
  • uspace/lib/c/generic/iplink_srv.c

    r3eb0c85 r8e7c9fe  
    8181}
    8282
     83static 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
    83110static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid,
    84111    ipc_call_t *icall)
     
    252279                        iplink_get_mac48_srv(srv, callid, &call);
    253280                        break;
     281                case IPLINK_SET_MAC48:
     282                        iplink_set_mac48_srv(srv, callid, &call);
     283                        break;
    254284                case IPLINK_SEND:
    255285                        iplink_send_srv(srv, callid, &call);
     
    300330}
    301331
     332int 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
    302358/** @}
    303359 */
  • uspace/lib/c/generic/irq.c

    r3eb0c85 r8e7c9fe  
    11/*
    2  * Copyright (c) 2005 Jakub Jermar
     2 * Copyright (c) 2014 Martin Decky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup mips64mm
     29/** @addtogroup libc
    3030 * @{
    3131 */
     
    3333 */
    3434
    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>
    4337
    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 */
     48int ipc_irq_subscribe(int inr, int devno, sysarg_t method,
     49    const irq_code_t *ucode)
    4650{
    47         as_operations = &as_ht_operations;
    48         asid_fifo_init();
     51        return __SYSCALL4(SYS_IPC_IRQ_SUBSCRIBE, inr, devno, method,
     52            (sysarg_t) ucode);
    4953}
    5054
    51 /** Install address space.
     55/** Unsubscribe from IRQ notification.
    5256 *
    53  * Install ASID.
     57 * @param inr   IRQ number.
     58 * @param devno Device number of the device generating inr.
    5459 *
    55  * @param as Address space structure.
     60 * @return Value returned by the kernel.
    5661 *
    5762 */
    58 void as_install_arch(as_t *as)
     63int ipc_irq_unsubscribe(int inr, int devno)
    5964{
    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);
    6766}
    6867
  • uspace/lib/c/generic/stacktrace.c

    r3eb0c85 r8e7c9fe  
    4242static int stacktrace_read_uintptr(void *arg, uintptr_t addr, uintptr_t *data);
    4343
    44 void stacktrace_print_fp_pc(uintptr_t fp, uintptr_t pc)
     44static stacktrace_ops_t basic_ops = {
     45        .read_uintptr = stacktrace_read_uintptr
     46};
     47
     48void stacktrace_print_generic(stacktrace_ops_t *ops, void *arg, uintptr_t fp,
     49    uintptr_t pc)
    4550{
    4651        stacktrace_t st;
    4752        uintptr_t nfp;
     53        int rc;
    4854
    49         st.op_arg = NULL;
    50         st.read_uintptr = stacktrace_read_uintptr;
     55        st.op_arg = arg;
     56        st.ops = ops;
    5157
    5258        while (stacktrace_fp_valid(&st, fp)) {
    5359                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;
    5666                fp = nfp;
    5767        }
     68}
     69
     70void stacktrace_print_fp_pc(uintptr_t fp, uintptr_t pc)
     71{
     72        stacktrace_print_generic(&basic_ops, NULL, fp, pc);
    5873}
    5974
  • uspace/lib/c/generic/str.c

    r3eb0c85 r8e7c9fe  
    13601360}
    13611361
    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 */
     1374char *str_tok(char *s, const char *delim, char **next)
    13701375{
    13711376        char *start, *end;
    13721377
    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;
    13751385
    13761386        /* 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];
    13791391
    13801392        /* 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)
    13861401                return NULL;    /* No more tokens. */
    1387         }
    13881402
    13891403        /* Overwrite delimiter with NULL terminator. */
  • uspace/lib/c/generic/task.c

    r3eb0c85 r8e7c9fe  
    22 * Copyright (c) 2006 Jakub Jermar
    33 * Copyright (c) 2008 Jiri Svoboda
     4 * Copyright (c) 2014 Martin Sucha
    45 * All rights reserved.
    56 *
     
    9495 *
    9596 * @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.
    9699 * @param path Pathname of the binary to execute.
    97100 * @param argv Command-line arguments.
     
    100103 *
    101104 */
    102 int task_spawnv(task_id_t *id, const char *path, const char *const args[])
     105int task_spawnv(task_id_t *id, task_wait_t *wait, const char *path,
     106    const char *const args[])
    103107{
    104108        /* Send default files */
     
    125129        files[3] = NULL;
    126130       
    127         return task_spawnvf(id, path, args, files);
     131        return task_spawnvf(id, wait, path, args, files);
    128132}
    129133
     
    135139 *
    136140 * @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.
    137143 * @param path  Pathname of the binary to execute.
    138144 * @param argv  Command-line arguments.
     
    142148 *
    143149 */
    144 int task_spawnvf(task_id_t *id, const char *path, const char *const args[],
    145     int *const files[])
     150int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
     151    const char *const args[], int *const files[])
    146152{
    147153        /* Connect to a program loader. */
     
    150156                return EREFUSED;
    151157       
     158        bool wait_initialized = false;
     159       
    152160        /* Get task ID. */
    153161        task_id_t task_id;
     
    181189                goto error;
    182190       
     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       
    183199        /* Run it. */
    184200        rc = loader_run(ldr);
     
    193209       
    194210error:
     211        if (wait_initialized)
     212                task_cancel_wait(wait);
     213       
    195214        /* Error exit */
    196215        loader_abort(ldr);
     
    204223 *
    205224 * @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.
    206227 * @param path Pathname of the binary to execute.
    207228 * @param cnt  Number of arguments.
     
    211232 *
    212233 */
    213 int task_spawn(task_id_t *task_id, const char *path, int cnt, va_list ap)
     234int task_spawn(task_id_t *task_id, task_wait_t *wait, const char *path,
     235    int cnt, va_list ap)
    214236{
    215237        /* Allocate argument list. */
     
    227249       
    228250        /* Spawn task. */
    229         int rc = task_spawnv(task_id, path, arglist);
     251        int rc = task_spawnv(task_id, wait, path, arglist);
    230252       
    231253        /* Free argument list. */
     
    240262 *
    241263 * @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.
    242266 * @param path Pathname of the binary to execute.
    243267 * @param ...  Command-line arguments.
     
    246270 *
    247271 */
    248 int task_spawnl(task_id_t *task_id, const char *path, ...)
     272int task_spawnl(task_id_t *task_id, task_wait_t *wait, const char *path, ...)
    249273{
    250274        /* Count the number of arguments. */
     
    262286       
    263287        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);
    265289        va_end(ap);
    266290       
     
    268292}
    269293
    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 */
     305int 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 */
     324void 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 */
     342int task_wait(task_wait_t *wait, task_exit_t *texit, int *retval)
    271343{
    272344        assert(texit);
    273345        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 */
     372int 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);
    285380}
    286381
  • uspace/lib/c/generic/time.c

    r3eb0c85 r8e7c9fe  
    555555                }
    556556               
    557                 void *addr;
     557                void *addr = AS_AREA_ANY;
    558558                rc = physmem_map(faddr, 1, AS_AREA_READ | AS_AREA_CACHEABLE,
    559559                    &addr);
Note: See TracChangeset for help on using the changeset viewer.