Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/cap/cap.c

    r455241b rb596d0d  
    9393
    9494#define CAPS_START      ((intptr_t) CAP_NIL + 1)
    95 #define CAPS_LAST       ((intptr_t) INT_MAX - 1)
    96 #define CAPS_SIZE       (CAPS_LAST - CAPS_START + 1)
     95#define CAPS_SIZE       (INT_MAX - (int) CAPS_START)
     96#define CAPS_LAST       (CAPS_SIZE - 1)
    9797
    9898static slab_cache_t *cap_cache;
     99static slab_cache_t *kobject_cache;
    99100
    100101kobject_ops_t *kobject_ops[KOBJECT_TYPE_MAX] = {
     
    124125}
    125126
    126 static void caps_remove_callback(ht_link_t *item)
    127 {
    128         cap_t *cap = hash_table_get_inst(item, cap_t, caps_link);
    129 
    130         if (cap->kobject) {
    131                 kobject_t *kobj = cap->kobject;
    132 
    133                 mutex_lock(&kobj->caps_list_lock);
    134                 cap->kobject = NULL;
    135                 list_remove(&cap->kobj_link);
    136                 mutex_unlock(&kobj->caps_list_lock);
    137 
    138                 kobject_put(kobj);
    139         }
    140 
    141         list_remove(&cap->type_link);
    142 
    143         slab_free(cap_cache, cap);
    144 }
    145 
    146127static const hash_table_ops_t caps_ops = {
    147128        .hash = caps_hash,
    148129        .key_hash = caps_key_hash,
    149         .key_equal = caps_key_equal,
    150         .remove_callback = caps_remove_callback,
     130        .key_equal = caps_key_equal
    151131};
    152132
     
    155135        cap_cache = slab_cache_create("cap_t", sizeof(cap_t), 0, NULL,
    156136            NULL, 0);
     137        kobject_cache = slab_cache_create("kobject_t", sizeof(kobject_t), 0,
     138            NULL, NULL, 0);
    157139}
    158140
     
    166148        if (!task->cap_info)
    167149                return ENOMEM;
    168 
    169         if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops)) {
    170                 free(task->cap_info);
    171                 return ENOMEM;
    172         }
    173 
     150        task->cap_info->handles = ra_arena_create();
     151        if (!task->cap_info->handles)
     152                goto error_handles;
     153        if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE))
     154                goto error_span;
     155        if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops))
     156                goto error_span;
     157        return EOK;
     158
     159error_span:
     160        ra_arena_destroy(task->cap_info->handles);
     161error_handles:
     162        free(task->cap_info);
     163        return ENOMEM;
     164}
     165
     166/** Initialize the capability info structure
     167 *
     168 * @param task  Task for which to initialize the info structure.
     169 */
     170void caps_task_init(task_t *task)
     171{
    174172        mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE);
    175 
    176         task->cap_info->handles = NULL;
    177173
    178174        for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
    179175                list_initialize(&task->cap_info->type_list[t]);
    180 
    181         return EOK;
    182 }
    183 
    184 /** Initialize the capability info structure
    185  *
    186  * @param task  Task for which to initialize the info structure.
    187  */
    188 errno_t caps_task_init(task_t *task)
    189 {
    190         assert(task->cap_info);
    191         assert(!task->cap_info->handles);
    192 
    193         task->cap_info->handles = ra_arena_create();
    194         if (!task->cap_info->handles)
    195                 return ENOMEM;
    196 
    197         if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE)) {
    198                 ra_arena_destroy(task->cap_info->handles);
    199                 return ENOMEM;
    200         }
    201 
    202         return EOK;
    203 }
    204 
    205 void caps_task_clear(task_t *task)
    206 {
    207         mutex_lock(&task->cap_info->lock);
    208 
    209         hash_table_clear(&task->cap_info->caps);
    210 
    211         if (task->cap_info->handles) {
    212                 ra_arena_destroy(task->cap_info->handles);
    213                 task->cap_info->handles = NULL;
    214         }
    215 
    216         for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
    217                 list_initialize(&task->cap_info->type_list[t]);
    218 
    219         mutex_unlock(&task->cap_info->lock);
    220176}
    221177
     
    227183{
    228184        hash_table_destroy(&task->cap_info->caps);
    229 
    230         if (task->cap_info->handles)
    231                 ra_arena_destroy(task->cap_info->handles);
    232 
     185        ra_arena_destroy(task->cap_info->handles);
    233186        free(task->cap_info);
    234187}
     
    347300cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj)
    348301{
    349         mutex_lock(&task->cap_info->lock);
    350302        mutex_lock(&kobj->caps_list_lock);
     303        mutex_lock(&task->cap_info->lock);
    351304        cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED);
    352305        assert(cap);
     
    356309        list_append(&cap->kobj_link, &kobj->caps_list);
    357310        list_append(&cap->type_link, &task->cap_info->type_list[kobj->type]);
     311        mutex_unlock(&task->cap_info->lock);
    358312        mutex_unlock(&kobj->caps_list_lock);
    359         mutex_unlock(&task->cap_info->lock);
    360313}
    361314
     
    387340        kobject_t *kobj = NULL;
    388341
     342restart:
    389343        mutex_lock(&task->cap_info->lock);
    390344        cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED);
     
    393347                        /* Hand over cap's reference to kobj */
    394348                        kobj = cap->kobject;
    395 
    396                         mutex_lock(&kobj->caps_list_lock);
     349                        if (mutex_trylock(&kobj->caps_list_lock) != EOK) {
     350                                mutex_unlock(&task->cap_info->lock);
     351                                kobj = NULL;
     352                                goto restart;
     353                        }
    397354                        cap_unpublish_unsafe(cap);
    398355                        mutex_unlock(&kobj->caps_list_lock);
     
    419376{
    420377        mutex_lock(&kobj->caps_list_lock);
    421 
    422         while (!list_empty(&kobj->caps_list)) {
    423                 cap_t *cap = list_get_instance(list_first(&kobj->caps_list), cap_t, kobj_link);
    424 
    425                 /* We're trying to acquire the two locks in reverse order. */
    426                 if (mutex_trylock(&cap->task->cap_info->lock) != EOK) {
    427                         mutex_unlock(&kobj->caps_list_lock);
    428                         mutex_lock(&kobj->caps_list_lock);
    429                         continue;
    430                 }
    431 
     378        list_foreach_safe(kobj->caps_list, cur, hlp) {
     379                cap_t *cap = list_get_instance(cur, cap_t, kobj_link);
     380                mutex_lock(&cap->task->cap_info->lock);
    432381                cap_unpublish_unsafe(cap);
    433382                /* Drop the reference for the unpublished capability */
    434383                kobject_put(kobj);
    435 
    436384                mutex_unlock(&cap->task->cap_info->lock);
    437385        }
    438 
    439386        mutex_unlock(&kobj->caps_list_lock);
    440387}
     
    457404        hash_table_remove_item(&task->cap_info->caps, &cap->caps_link);
    458405        ra_free(task->cap_info->handles, cap_handle_raw(handle), 1);
    459         mutex_unlock(&task->cap_info->lock);
     406        slab_free(cap_cache, cap);
     407        mutex_unlock(&task->cap_info->lock);
     408}
     409
     410kobject_t *kobject_alloc(unsigned int flags)
     411{
     412        return slab_alloc(kobject_cache, flags);
     413}
     414
     415void kobject_free(kobject_t *kobj)
     416{
     417        slab_free(kobject_cache, kobj);
    460418}
    461419
     
    464422 * @param kobj  Kernel object to initialize.
    465423 * @param type  Type of the kernel object.
    466  */
    467 void kobject_initialize(kobject_t *kobj, kobject_type_t type)
    468 {
    469         refcount_init(&kobj->refcnt);
     424 * @param raw   Raw pointer to the encapsulated object.
     425 */
     426void kobject_initialize(kobject_t *kobj, kobject_type_t type, void *raw)
     427{
     428        atomic_store(&kobj->refcnt, 1);
    470429
    471430        mutex_initialize(&kobj->caps_list_lock, MUTEX_PASSIVE);
     
    473432
    474433        kobj->type = type;
     434        kobj->raw = raw;
    475435}
    476436
     
    495455                if (cap->kobject->type == type) {
    496456                        kobj = cap->kobject;
    497                         refcount_up(&kobj->refcnt);
     457                        atomic_inc(&kobj->refcnt);
    498458                }
    499459        }
     
    509469void kobject_add_ref(kobject_t *kobj)
    510470{
    511         refcount_up(&kobj->refcnt);
     471        atomic_inc(&kobj->refcnt);
    512472}
    513473
     
    521481void kobject_put(kobject_t *kobj)
    522482{
    523         if (refcount_down(&kobj->refcnt)) {
    524                 KOBJECT_OP(kobj)->destroy(kobj);
     483        if (atomic_postdec(&kobj->refcnt) == 1) {
     484                KOBJECT_OP(kobj)->destroy(kobj->raw);
     485                kobject_free(kobj);
    525486        }
    526487}
Note: See TracChangeset for help on using the changeset viewer.