Changeset f0cc1c64 in mainline for uspace/lib/c/generic/async/ports.c


Ignore:
Timestamp:
2025-06-20T19:26:13Z (3 days ago)
Author:
Miroslav Cimerman <mc@…>
Children:
817cb83
Parents:
f0360ec (diff), 5caad1d (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 upstream into helenraid

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async/ports.c

    rf0360ec rf0cc1c64  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2006 Ondrej Palkovsky
    34 * All rights reserved.
     
    5960        iface_t iface;
    6061
    61         /** Interface ports */
    62         hash_table_t port_hash_table;
    63 
    64         /** Next available port ID */
    65         port_id_t port_id_avail;
     62        /** Interface connection handler */
     63        async_port_handler_t handler;
     64
     65        /** Client data */
     66        void *data;
    6667} interface_t;
    6768
     
    7374        port_id_t id;
    7475
    75         /** Port connection handler */
    76         async_port_handler_t handler;
    77 
    78         /** Client data */
    79         void *data;
     76        /** Port interfaces */
     77        hash_table_t interface_hash_table;
    8078} port_t;
    8179
     
    9896static void *fallback_port_data = NULL;
    9997
    100 /** Futex guarding the interface hash table. */
    101 static fibril_rmutex_t interface_mutex;
    102 static hash_table_t interface_hash_table;
     98/** Futex guarding the port hash table. */
     99static fibril_rmutex_t port_mutex;
     100static hash_table_t port_hash_table;
     101/** Next available port ID */
     102static port_id_t port_id_avail = 0;
    103103
    104104static size_t interface_key_hash(const void *key)
     
    158158};
    159159
    160 static interface_t *async_new_interface(iface_t iface)
     160static interface_t *async_new_interface(port_t *port, iface_t iface,
     161    async_port_handler_t handler, void *data)
    161162{
    162163        interface_t *interface =
     
    164165        if (!interface)
    165166                return NULL;
    166 
    167         bool ret = hash_table_create(&interface->port_hash_table, 0, 0,
    168             &port_hash_table_ops);
    169         if (!ret) {
    170                 free(interface);
    171                 return NULL;
    172         }
    173 
    174167        interface->iface = iface;
    175         interface->port_id_avail = 0;
    176 
    177         hash_table_insert(&interface_hash_table, &interface->link);
     168        interface->handler = handler;
     169        interface->data = data;
     170
     171        hash_table_insert(&port->interface_hash_table, &interface->link);
    178172
    179173        return interface;
    180174}
    181175
    182 static port_t *async_new_port(interface_t *interface,
    183     async_port_handler_t handler, void *data)
     176static port_t *async_new_port(void)
    184177{
    185178        // TODO: Move the malloc out of critical section.
     
    188181                return NULL;
    189182
    190         port_id_t id = interface->port_id_avail;
    191         interface->port_id_avail++;
     183        bool ret = hash_table_create(&port->interface_hash_table, 0, 0,
     184            &interface_hash_table_ops);
     185        if (!ret) {
     186                free(port);
     187                return NULL;
     188        }
     189
     190        port_id_t id = port_id_avail;
     191        port_id_avail++;
    192192
    193193        port->id = id;
    194         port->handler = handler;
    195         port->data = data;
    196 
    197         hash_table_insert(&interface->port_hash_table, &port->link);
     194        hash_table_insert(&port_hash_table, &port->link);
    198195
    199196        return port;
     197}
     198
     199static bool destroy_if(ht_link_t *link, void *arg)
     200{
     201        port_t *port = (port_t *)arg;
     202
     203        hash_table_remove_item(&port->interface_hash_table, link);
     204        return false;
     205}
     206
     207static void async_delete_port(port_t *port)
     208{
     209        /* Destroy interfaces */
     210        hash_table_apply(&port->interface_hash_table, destroy_if, port);
     211
     212        hash_table_destroy(&port->interface_hash_table);
     213        free(port);
    200214}
    201215
     
    205219        interface_t *interface;
    206220
    207         fibril_rmutex_lock(&interface_mutex);
    208 
    209         ht_link_t *link = hash_table_find(&interface_hash_table, &iface);
    210         if (link)
    211                 interface = hash_table_get_inst(link, interface_t, link);
    212         else
    213                 interface = async_new_interface(iface);
    214 
    215         if (!interface) {
    216                 fibril_rmutex_unlock(&interface_mutex);
     221        fibril_rmutex_lock(&port_mutex);
     222
     223        port_t *port = async_new_port();
     224        if (port == NULL) {
     225                fibril_rmutex_unlock(&port_mutex);
    217226                return ENOMEM;
    218227        }
    219228
    220         port_t *port = async_new_port(interface, handler, data);
    221         if (!port) {
    222                 fibril_rmutex_unlock(&interface_mutex);
     229        interface = async_new_interface(port, iface, handler, data);
     230        if (interface == NULL) {
     231                async_delete_port(port);
     232                fibril_rmutex_unlock(&port_mutex);
    223233                return ENOMEM;
    224234        }
    225235
    226236        *port_id = port->id;
    227 
    228         fibril_rmutex_unlock(&interface_mutex);
    229 
     237        fibril_rmutex_unlock(&port_mutex);
     238        return EOK;
     239}
     240
     241errno_t async_port_create_interface(port_id_t port_id, iface_t iface,
     242    async_port_handler_t handler, void *data)
     243{
     244        ht_link_t *link;
     245        port_t *port;
     246        interface_t *interface;
     247
     248        fibril_rmutex_lock(&port_mutex);
     249        link = hash_table_find(&port_hash_table, &port_id);
     250        assert(link != NULL);
     251        port = hash_table_get_inst(link, port_t, link);
     252
     253        interface = async_new_interface(port, iface, handler, data);
     254        if (interface == NULL) {
     255                fibril_rmutex_unlock(&port_mutex);
     256                return ENOMEM;
     257        }
     258
     259        fibril_rmutex_unlock(&port_mutex);
    230260        return EOK;
    231261}
     
    248278}
    249279
    250 static port_t *async_find_port(iface_t iface, port_id_t port_id)
    251 {
    252         port_t *port = NULL;
    253 
    254         fibril_rmutex_lock(&interface_mutex);
    255 
    256         ht_link_t *link = hash_table_find(&interface_hash_table, &iface);
    257         if (link) {
    258                 interface_t *interface =
    259                     hash_table_get_inst(link, interface_t, link);
    260 
    261                 link = hash_table_find(&interface->port_hash_table, &port_id);
    262                 if (link)
    263                         port = hash_table_get_inst(link, port_t, link);
    264         }
    265 
    266         fibril_rmutex_unlock(&interface_mutex);
    267 
    268         return port;
    269 }
    270 
    271 async_port_handler_t async_get_port_handler(iface_t iface, port_id_t port_id,
    272     void **data)
     280typedef struct {
     281        iface_t iface;
     282        interface_t *interface;
     283} find_if_port_t;
     284
     285static bool find_if_port(ht_link_t *link, void *arg)
     286{
     287        find_if_port_t *fip = (find_if_port_t *)arg;
     288        port_t *port;
     289        interface_t *interface;
     290
     291        (void)arg;
     292        port = hash_table_get_inst(link, port_t, link);
     293
     294        ht_link_t *ilink = hash_table_find(&port->interface_hash_table,
     295            &fip->iface);
     296        if (ilink) {
     297                interface = hash_table_get_inst(ilink, interface_t,
     298                    link);
     299                fip->interface = interface;
     300                return false;
     301        }
     302
     303        return true;
     304}
     305
     306static interface_t *async_find_interface(iface_t iface, port_id_t port_id)
     307{
     308        interface_t *interface = NULL;
     309        find_if_port_t fip;
     310
     311        (void)port_id; // XXX !!!
     312
     313        fibril_rmutex_lock(&port_mutex);
     314
     315        /*
     316         * XXX Find any port implementing that interface. In reality we should
     317         * only look at port with ID port_id - but server.c does not
     318         * provide us with a correct port ID
     319         */
     320
     321        fip.iface = iface;
     322        fip.interface = NULL;
     323        hash_table_apply(&port_hash_table, find_if_port, (void *)&fip);
     324        interface = fip.interface;
     325
     326        fibril_rmutex_unlock(&port_mutex);
     327        return interface;
     328}
     329
     330async_port_handler_t async_get_interface_handler(iface_t iface,
     331    port_id_t port_id, void **data)
    273332{
    274333        assert(data);
     
    277336        *data = fallback_port_data;
    278337
    279         port_t *port = async_find_port(iface, port_id);
    280         if (port) {
    281                 handler = port->handler;
    282                 *data = port->data;
     338        interface_t *interface = async_find_interface(iface, port_id);
     339        if (interface != NULL) {
     340                handler = interface->handler;
     341                *data = interface->data;
    283342        }
    284343
     
    286345}
    287346
    288 /** Initialize the async framework.
     347void async_port_destroy(port_id_t port_id)
     348{
     349        ht_link_t *link;
     350        port_t *port;
     351
     352        fibril_rmutex_lock(&port_mutex);
     353        link = hash_table_find(&port_hash_table, &port_id);
     354        assert(link != NULL);
     355        port = hash_table_get_inst(link, port_t, link);
     356        async_delete_port(port);
     357        fibril_rmutex_unlock(&port_mutex);
     358}
     359
     360/** Initialize the async framework ports.
    289361 *
    290362 */
    291363void __async_ports_init(void)
    292364{
    293         if (fibril_rmutex_initialize(&interface_mutex) != EOK)
     365        if (fibril_rmutex_initialize(&port_mutex) != EOK)
    294366                abort();
    295367
    296         if (!hash_table_create(&interface_hash_table, 0, 0,
    297             &interface_hash_table_ops))
     368        if (!hash_table_create(&port_hash_table, 0, 0, &port_hash_table_ops))
    298369                abort();
    299370}
     
    301372void __async_ports_fini(void)
    302373{
    303         fibril_rmutex_destroy(&interface_mutex);
    304 }
     374        fibril_rmutex_destroy(&port_mutex);
     375}
Note: See TracChangeset for help on using the changeset viewer.