Ignore:
File:
1 edited

Legend:

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

    rcb20b05 r0db0df2  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
    32 * Copyright (c) 2006 Ondrej Palkovsky
    43 * All rights reserved.
     
    6059        iface_t iface;
    6160
    62         /** Interface connection handler */
    63         async_port_handler_t handler;
    64 
    65         /** Client data */
    66         void *data;
     61        /** Interface ports */
     62        hash_table_t port_hash_table;
     63
     64        /** Next available port ID */
     65        port_id_t port_id_avail;
    6766} interface_t;
    6867
     
    7473        port_id_t id;
    7574
    76         /** Port interfaces */
    77         hash_table_t interface_hash_table;
     75        /** Port connection handler */
     76        async_port_handler_t handler;
     77
     78        /** Client data */
     79        void *data;
    7880} port_t;
    7981
     
    9698static void *fallback_port_data = NULL;
    9799
    98 /** Futex guarding the port hash table. */
    99 static fibril_rmutex_t port_mutex;
    100 static hash_table_t port_hash_table;
    101 /** Next available port ID */
    102 static port_id_t port_id_avail = 0;
     100/** Futex guarding the interface hash table. */
     101static fibril_rmutex_t interface_mutex;
     102static hash_table_t interface_hash_table;
    103103
    104104static size_t interface_key_hash(const void *key)
     
    158158};
    159159
    160 static interface_t *async_new_interface(port_t *port, iface_t iface,
    161     async_port_handler_t handler, void *data)
     160static interface_t *async_new_interface(iface_t iface)
    162161{
    163162        interface_t *interface =
     
    165164        if (!interface)
    166165                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
    167174        interface->iface = iface;
    168         interface->handler = handler;
    169         interface->data = data;
    170 
    171         hash_table_insert(&port->interface_hash_table, &interface->link);
     175        interface->port_id_avail = 0;
     176
     177        hash_table_insert(&interface_hash_table, &interface->link);
    172178
    173179        return interface;
    174180}
    175181
    176 static port_t *async_new_port(void)
     182static port_t *async_new_port(interface_t *interface,
     183    async_port_handler_t handler, void *data)
    177184{
    178185        // TODO: Move the malloc out of critical section.
     
    181188                return NULL;
    182189
    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++;
     190        port_id_t id = interface->port_id_avail;
     191        interface->port_id_avail++;
    192192
    193193        port->id = id;
    194         hash_table_insert(&port_hash_table, &port->link);
     194        port->handler = handler;
     195        port->data = data;
     196
     197        hash_table_insert(&interface->port_hash_table, &port->link);
    195198
    196199        return port;
    197 }
    198 
    199 static 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 
    207 static 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);
    214200}
    215201
     
    219205        interface_t *interface;
    220206
    221         fibril_rmutex_lock(&port_mutex);
    222 
    223         port_t *port = async_new_port();
    224         if (port == NULL) {
    225                 fibril_rmutex_unlock(&port_mutex);
     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);
    226217                return ENOMEM;
    227218        }
    228219
    229         interface = async_new_interface(port, iface, handler, data);
    230         if (interface == NULL) {
    231                 async_delete_port(port);
    232                 fibril_rmutex_unlock(&port_mutex);
     220        port_t *port = async_new_port(interface, handler, data);
     221        if (!port) {
     222                fibril_rmutex_unlock(&interface_mutex);
    233223                return ENOMEM;
    234224        }
    235225
    236226        *port_id = port->id;
    237         fibril_rmutex_unlock(&port_mutex);
    238         return EOK;
    239 }
    240 
    241 errno_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);
     227
     228        fibril_rmutex_unlock(&interface_mutex);
     229
    260230        return EOK;
    261231}
     
    278248}
    279249
    280 typedef struct {
    281         iface_t iface;
    282         interface_t *interface;
    283 } find_if_port_t;
    284 
    285 static 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 
    306 static 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 
    330 async_port_handler_t async_get_interface_handler(iface_t iface,
    331     port_id_t port_id, void **data)
     250static 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
     271async_port_handler_t async_get_port_handler(iface_t iface, port_id_t port_id,
     272    void **data)
    332273{
    333274        assert(data);
     
    336277        *data = fallback_port_data;
    337278
    338         interface_t *interface = async_find_interface(iface, port_id);
    339         if (interface != NULL) {
    340                 handler = interface->handler;
    341                 *data = interface->data;
     279        port_t *port = async_find_port(iface, port_id);
     280        if (port) {
     281                handler = port->handler;
     282                *data = port->data;
    342283        }
    343284
     
    345286}
    346287
    347 void 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.
     288/** Initialize the async framework.
    361289 *
    362290 */
    363291void __async_ports_init(void)
    364292{
    365         if (fibril_rmutex_initialize(&port_mutex) != EOK)
     293        if (fibril_rmutex_initialize(&interface_mutex) != EOK)
    366294                abort();
    367295
    368         if (!hash_table_create(&port_hash_table, 0, 0, &port_hash_table_ops))
     296        if (!hash_table_create(&interface_hash_table, 0, 0,
     297            &interface_hash_table_ops))
    369298                abort();
    370299}
     
    372301void __async_ports_fini(void)
    373302{
    374         fibril_rmutex_destroy(&port_mutex);
    375 }
     303        fibril_rmutex_destroy(&interface_mutex);
     304}
Note: See TracChangeset for help on using the changeset viewer.