Changeset 48bcf49 in mainline for kernel/generic/src/cap/cap.c


Ignore:
Timestamp:
2017-09-28T22:08:15Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6636fb19
Parents:
dd20cbb
Message:

Introduce reference-counted kobjects

Capabilities are thus reduced to task-local names for references to kobjects.

File:
1 edited

Legend:

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

    rdd20cbb r48bcf49  
    4040#include <adt/list.h>
    4141
    42 void cap_initialize(cap_t *cap, int handle)
    43 {
    44         cap->type = CAP_TYPE_INVALID;
     42static kobject_t *cap_unpublish_locked(task_t *, cap_handle_t, kobject_type_t);
     43
     44void cap_initialize(cap_t *cap, cap_handle_t handle)
     45{
     46        cap->state = CAP_STATE_FREE;
    4547        cap->handle = handle;
    46         cap->can_reclaim = NULL;
    4748        link_initialize(&cap->link);
    4849}
     
    5859        mutex_initialize(&task->cap_info->lock, MUTEX_PASSIVE);
    5960
    60         for (int i = 0; i < CAP_TYPE_MAX; i++)
    61                 list_initialize(&task->cap_info->type_list[i]);
    62 
    63         for (int i = 0; i < MAX_CAPS; i++)
    64                 cap_initialize(&task->cap_info->caps[i], i);
     61        for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
     62                list_initialize(&task->cap_info->type_list[t]);
     63
     64        for (cap_handle_t h = 0; h < MAX_CAPS; h++)
     65                cap_initialize(&task->cap_info->caps[h], h);
    6566}
    6667
     
    7172}
    7273
    73 bool caps_apply_to_type(task_t *task, cap_type_t type,
     74bool caps_apply_to_kobject_type(task_t *task, kobject_type_t type,
    7475    bool (*cb)(cap_t *, void *), void *arg)
    7576{
     
    8889}
    8990
    90 void caps_lock(task_t *task)
    91 {
    92         mutex_lock(&task->cap_info->lock);
    93 }
    94 
    95 void caps_unlock(task_t *task)
    96 {
    97         mutex_unlock(&task->cap_info->lock);
    98 }
    99 
    100 cap_t *cap_get(task_t *task, int handle, cap_type_t type)
     91static cap_t *cap_get(task_t *task, cap_handle_t handle, cap_state_t state)
    10192{
    10293        assert(mutex_locked(&task->cap_info->lock));
     
    10495        if ((handle < 0) || (handle >= MAX_CAPS))
    10596                return NULL;
    106         if (task->cap_info->caps[handle].type != type)
     97        if (task->cap_info->caps[handle].state != state)
    10798                return NULL;
    10899        return &task->cap_info->caps[handle];
    109100}
    110101
    111 int cap_alloc(task_t *task)
    112 {
    113         int handle;
    114 
    115         mutex_lock(&task->cap_info->lock);
    116         for (handle = 0; handle < MAX_CAPS; handle++) {
     102cap_handle_t cap_alloc(task_t *task)
     103{
     104        mutex_lock(&task->cap_info->lock);
     105        for (cap_handle_t handle = 0; handle < MAX_CAPS; handle++) {
    117106                cap_t *cap = &task->cap_info->caps[handle];
    118                 if (cap->type > CAP_TYPE_ALLOCATED) {
    119                         if (cap->can_reclaim && cap->can_reclaim(cap)) {
    120                                 list_remove(&cap->link);
    121                                 cap_initialize(cap, handle);
    122                         }
    123                 }
    124                 if (cap->type == CAP_TYPE_INVALID) {
    125                         cap->type = CAP_TYPE_ALLOCATED;
     107                /* See if the capability should be garbage-collected */
     108                if (cap->state == CAP_STATE_PUBLISHED &&
     109                    cap->kobject->ops->reclaim &&
     110                    cap->kobject->ops->reclaim(cap->kobject)) {
     111                        kobject_t *kobj = cap_unpublish_locked(task, handle,
     112                            cap->kobject->type);
     113                        kobject_put(kobj);
     114                        cap_initialize(&task->cap_info->caps[handle], handle);
     115                }
     116                if (cap->state == CAP_STATE_FREE) {
     117                        cap->state = CAP_STATE_ALLOCATED;
    126118                        mutex_unlock(&task->cap_info->lock);
    127119                        return handle;
     
    133125}
    134126
    135 void cap_publish(task_t *task, int handle, cap_type_t type, void *kobject)
    136 {
    137         mutex_lock(&task->cap_info->lock);
    138         cap_t *cap = cap_get(task, handle, CAP_TYPE_ALLOCATED);
     127void
     128cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj)
     129{
     130        mutex_lock(&task->cap_info->lock);
     131        cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED);
    139132        assert(cap);
    140         cap->type = type;
    141         cap->kobject = kobject;
    142         list_append(&cap->link, &task->cap_info->type_list[type]);
    143         mutex_unlock(&task->cap_info->lock);
    144 }
    145 
    146 cap_t *cap_unpublish(task_t *task, int handle, cap_type_t type)
    147 {
    148         cap_t *cap;
    149 
    150         mutex_lock(&task->cap_info->lock);
    151         cap = cap_get(task, handle, type);
     133        cap->state = CAP_STATE_PUBLISHED;
     134        /* Hand over kobj's reference to cap */
     135        cap->kobject = kobj;
     136        list_append(&cap->link, &task->cap_info->type_list[kobj->type]);
     137        mutex_unlock(&task->cap_info->lock);
     138}
     139
     140static kobject_t *
     141cap_unpublish_locked(task_t *task, cap_handle_t handle, kobject_type_t type)
     142{
     143        kobject_t *kobj = NULL;
     144
     145        cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED);
    152146        if (cap) {
    153                 list_remove(&cap->link);
    154                 cap->type = CAP_TYPE_ALLOCATED;
    155         }
    156         mutex_unlock(&task->cap_info->lock);
    157 
    158         return cap;
    159 }
    160 
    161 void cap_free(task_t *task, int handle)
     147                if (cap->kobject->type == type) {
     148                        /* Hand over cap's reference to kobj */
     149                        kobj = cap->kobject;
     150                        cap->kobject = NULL;
     151                        list_remove(&cap->link);
     152                        cap->state = CAP_STATE_ALLOCATED;
     153                }
     154        }
     155
     156        return kobj;
     157}
     158kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type)
     159{
     160
     161        mutex_lock(&task->cap_info->lock);
     162        kobject_t *kobj = cap_unpublish_locked(task, handle, type);
     163        mutex_unlock(&task->cap_info->lock);
     164
     165        return kobj;
     166}
     167
     168void cap_free(task_t *task, cap_handle_t handle)
    162169{
    163170        assert(handle >= 0);
    164171        assert(handle < MAX_CAPS);
    165         assert(task->cap_info->caps[handle].type == CAP_TYPE_ALLOCATED);
     172        assert(task->cap_info->caps[handle].state == CAP_STATE_ALLOCATED);
    166173
    167174        mutex_lock(&task->cap_info->lock);
     
    170177}
    171178
     179void kobject_initialize(kobject_t *kobj, kobject_type_t type, void *raw,
     180    kobject_ops_t *ops)
     181{
     182        atomic_set(&kobj->refcnt, 1);
     183        kobj->type = type;
     184        kobj->raw = raw;
     185        kobj->ops = ops;
     186}
     187
     188kobject_t *
     189kobject_get(struct task *task, cap_handle_t handle, kobject_type_t type)
     190{
     191        kobject_t *kobj = NULL;
     192
     193        mutex_lock(&task->cap_info->lock);
     194        cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED);
     195        if (cap) {
     196                if (cap->kobject->type == type) {
     197                        kobj = cap->kobject;
     198                        atomic_inc(&kobj->refcnt);
     199                }
     200        }
     201        mutex_unlock(&task->cap_info->lock);
     202
     203        return kobj;
     204}
     205
     206void kobject_put(kobject_t *kobj)
     207{
     208        if (atomic_postdec(&kobj->refcnt) == 1) {
     209                kobj->ops->destroy(kobj->raw);
     210                free(kobj);
     211        }
     212}
     213
    172214/** @}
    173215 */
Note: See TracChangeset for help on using the changeset viewer.