Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f527f58 in mainline


Ignore:
Timestamp:
2016-08-03T11:12:24Z (6 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial
Children:
96ef672
Parents:
e657635
Message:

Reference-count endpoint_t structures

Track explicit references to USB endpoints. Call endpoint_destroy()
only after the last reference is destroyed. This prevents the scenario
in which removal was attempted on an endpoint while there was a transfer
in progress.

Location:
uspace/lib/usbhost
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    re657635 rf527f58  
    4040#include <fibril_synch.h>
    4141#include <usb/usb.h>
     42#include <atomic.h>
    4243
    4344/** Host controller side endpoint structure. */
    4445typedef struct endpoint {
     46        /** Reference count. */
     47        atomic_t refcnt;       
    4548        /** Part of linked list. */
    4649        link_t link;
     
    9194void endpoint_destroy(endpoint_t *instance);
    9295
     96void endpoint_add_ref(endpoint_t *instance);
     97void endpoint_del_ref(endpoint_t *instance);
     98
    9399void endpoint_set_hc_data(endpoint_t *instance,
    94100    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
  • uspace/lib/usbhost/src/endpoint.c

    re657635 rf527f58  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusbhost
    2930 * @{
     
    3738#include <assert.h>
    3839#include <stdlib.h>
     40#include <atomic.h>
    3941
    4042/** Allocate ad initialize endpoint_t structure.
     
    5557        endpoint_t *instance = malloc(sizeof(endpoint_t));
    5658        if (instance) {
     59                atomic_set(&instance->refcnt, 0);
    5760                instance->address = address;
    5861                instance->endpoint = endpoint;
     
    8386{
    8487        assert(instance);
    85         //TODO: Do something about waiting fibrils.
    8688        assert(!instance->active);
    8789        assert(instance->hc_data.data == NULL);
    8890        free(instance);
     91}
     92
     93void endpoint_add_ref(endpoint_t *instance)
     94{
     95        atomic_inc(&instance->refcnt);
     96}
     97
     98void endpoint_del_ref(endpoint_t *instance)
     99{
     100        if (atomic_predec(&instance->refcnt) == 0)
     101                endpoint_destroy(instance);
    89102}
    90103
     
    122135{
    123136        assert(instance);
     137        /* Add reference for active endpoint. */
     138        endpoint_add_ref(instance);
    124139        fibril_mutex_lock(&instance->guard);
    125140        while (instance->active)
     
    139154        fibril_mutex_unlock(&instance->guard);
    140155        fibril_condvar_signal(&instance->avail);
     156        /* Drop reference for active endpoint. */
     157        endpoint_del_ref(instance);
    141158}
    142159
     
    171188        fibril_mutex_unlock(&instance->guard);
    172189}
     190
    173191/**
    174192 * @}
  • uspace/lib/usbhost/src/hcd.c

    re657635 rf527f58  
    241241                usb_transfer_batch_destroy(batch);
    242242
     243        /* Drop our own reference to ep. */
     244        endpoint_del_ref(ep);
     245
    243246        return ret;
    244247}
  • uspace/lib/usbhost/src/usb_bus.c

    re657635 rf527f58  
    242242                return EEXIST;
    243243        }
     244        /* Add endpoint list's reference to ep. */
     245        endpoint_add_ref(ep);
    244246        list_append(&ep->link, get_list(instance, ep->address));
    245247
     
    274276            ep->endpoint, usb_str_transfer_type_short(ep->transfer_type),
    275277            usb_str_direction(ep->direction));
     278        /* Drop endpoint list's reference to ep. */
     279        endpoint_del_ref(ep);
    276280        fibril_mutex_unlock(&instance->guard);
    277281        return EOK;
     
    289293        fibril_mutex_lock(&instance->guard);
    290294        endpoint_t *ep = find_locked(instance, address, endpoint, direction);
     295        if (ep) {
     296                /* We are exporting ep to the outside world, add reference. */
     297                endpoint_add_ref(ep);
     298        }
    291299        fibril_mutex_unlock(&instance->guard);
    292300        return ep;
     
    350358        }
    351359
     360        /* Add our reference to ep. */
     361        endpoint_add_ref(ep);
     362
    352363        if (callback) {
    353364                const int ret = callback(ep, arg);
    354365                if (ret != EOK) {
    355366                        fibril_mutex_unlock(&instance->guard);
    356                         endpoint_destroy(ep);
     367                        endpoint_del_ref(ep);
    357368                        return ret;
    358369                }
    359370        }
     371       
     372        /* Add endpoint list's reference to ep. */
     373        endpoint_add_ref(ep);
    360374        list_append(&ep->link, get_list(instance, ep->address));
    361375
    362376        instance->free_bw -= ep->bandwidth;
    363377        fibril_mutex_unlock(&instance->guard);
     378
     379        /* Drop our reference to ep. */
     380        endpoint_del_ref(ep);
     381
    364382        return EOK;
    365383}
     
    392410                callback(ep, arg);
    393411        }
    394         endpoint_destroy(ep);
     412        /* Drop endpoint list's reference to ep. */
     413        endpoint_del_ref(ep);
    395414        return EOK;
    396415}
     
    445464                        if (callback)
    446465                                callback(ep, arg);
    447                         endpoint_destroy(ep);
     466                        /* Drop endpoint list's reference to ep. */
     467                        endpoint_del_ref(ep);
    448468                }
    449469        }
Note: See TracChangeset for help on using the changeset viewer.