Changeset 5bccec3 in mainline


Ignore:
Timestamp:
2018-01-18T02:48:17Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9b8dac4
Parents:
a9fcd73
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-18 02:27:04)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-18 02:48:17)
Message:

usb port: disconnect handler shall run in separate fibril too

Location:
uspace/lib/usb
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/include/usb/port.h

    ra9fcd73 r5bccec3  
    5656        PORT_ENUMERATED,/* Device enumerated. Fibril finished succesfully. */
    5757        PORT_CONNECTING,/* A connected event received, fibril running. */
     58        PORT_DISCONNECTING,/* A disconnected event received, fibril running. */
    5859        PORT_ERROR,     /* An error "in-progress". Fibril still running. */
    5960} usb_port_state_t;
  • uspace/lib/usb/src/port.c

    ra9fcd73 r5bccec3  
    102102
    103103        if (port->state != PORT_DISABLED) {
    104                 usb_log_warning("A connected event come for port that is not disabled.");
     104                usb_log_warning("a connected event come for port that is not disabled.");
    105105                ret = EINVAL;
    106106                goto out;
     
    137137}
    138138
     139struct remove_worker_args {
     140        usb_port_t *port;
     141        usb_port_remove_t handler;
     142};
     143
     144static int remove_worker(void *arg)
     145{
     146        struct remove_worker_args * const args = arg;
     147        usb_port_t *port = args->port;
     148        usb_port_remove_t handler = args->handler;
     149        free(args);
     150
     151        fibril_mutex_lock(&port->guard);
     152        assert(port->state == PORT_DISCONNECTING);
     153
     154        handler(port);
     155
     156        port->state = PORT_DISABLED;
     157        fibril_condvar_broadcast(&port->finished_cv);
     158        fibril_mutex_unlock(&port->guard);
     159        return EOK;
     160}
     161
     162static void fork_remove_worker(usb_port_t *port, usb_port_remove_t handler)
     163{
     164        struct remove_worker_args *args = malloc(sizeof(*args));
     165        if (!args)
     166                return;
     167
     168        fid_t fibril = fibril_create(&remove_worker, args);
     169        if (!fibril) {
     170                free(args);
     171                return;
     172        }
     173
     174        args->port = port;
     175        args->handler = handler;
     176
     177        port->state = PORT_DISCONNECTING;
     178        fibril_add_ready(fibril);
     179}
     180
    139181void usb_port_disabled(usb_port_t *port, usb_port_remove_t handler)
    140182{
     
    144186        switch (port->state) {
    145187        case PORT_ENUMERATED:
    146                 handler(port);
    147                 port->state = PORT_DISABLED;
     188                fork_remove_worker(port, handler);
    148189                break;
    149190
     
    154195                fibril_condvar_wait(&port->finished_cv, &port->guard);
    155196                /* fallthrough */
     197        case PORT_DISCONNECTING:
    156198        case PORT_DISABLED:
    157199                break;
    158200        }
    159201
    160         assert(port->state == PORT_DISABLED);
     202        assert(port->state == PORT_DISABLED || port->state == PORT_DISCONNECTING);
    161203        fibril_mutex_unlock(&port->guard);
    162204}
     
    190232                /* fallthrough */
    191233        case PORT_ERROR:
     234        case PORT_DISCONNECTING:
    192235                fibril_condvar_wait(&port->finished_cv, &port->guard);
    193236                break;
Note: See TracChangeset for help on using the changeset viewer.