Changeset 67f11a0 in mainline for kernel/generic/src/cap/cap.c


Ignore:
Timestamp:
2018-03-15T17:40:20Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
530f2de, e9e4068
Parents:
30f1a25 (diff), a36f442 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jakub Jermar <jakub@…> (2018-03-15 17:25:56)
git-committer:
Jakub Jermar <jakub@…> (2018-03-15 17:40:20)
Message:

Merge branch 'noreclaimers'

This commit removes the left-over from the original IPC phone life-cycle
management in which phones were freed lazily during an attempt to
allocate a new phone when the allocator found a hung-up phone with zero
active calls. This mechanism is the reason why kernel objects had to
have the reclaim method. This commit changes the behavior in that phones
are deallocated with their last reference. At the same time it makes
sure that each active call has its own reference on the phone.

This change also makes sure that each connected phone has a capability
via which it can be hung up by the user or cleaned up in ipc_cleanup().
A special mode for phone_alloc() was introduced that allows calls such
as IPC_M_CONNECT_ME_TO and IPC_M_CONNECT_TO_ME to allocate an
unpublished capability and publish it only when the phone is
successfully connected. This fixes a nasty race condition when the user
destroys the capability before the phone is connected and then this
phone becomes essentially invisible for ipc_cleanup().

Last but not least, ipc_cleanup() was slightly streamlined in that it
now knows for how many calls it has to wait from the answerbox's active
call count.

File:
1 edited

Legend:

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

    r30f1a25 r67f11a0  
    235235}
    236236
    237 static bool cap_reclaimer(ht_link_t *link, void *arg)
    238 {
    239         cap_t **result = (cap_t **) arg;
    240         cap_t *cap = hash_table_get_inst(link, cap_t, caps_link);
    241 
    242         if (cap->state == CAP_STATE_PUBLISHED && cap->kobject->ops->reclaim &&
    243             cap->kobject->ops->reclaim(cap->kobject)) {
    244                 kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
    245                     cap->kobject->type);
    246                 kobject_put(kobj);
    247                 cap_initialize(cap, cap->task, cap->handle);
    248                 *result = cap;
    249                 return false;
    250         }
    251 
    252         return true;
    253 }
    254 
    255237/** Allocate new capability
    256238 *
     
    263245errno_t cap_alloc(task_t *task, cap_handle_t *handle)
    264246{
    265         cap_t *cap = NULL;
    266 
    267         /*
    268          * First of all, see if we can reclaim a capability. Note that this
    269          * feature is only temporary and capability reclamaition will eventually
    270          * be phased out.
    271          */
    272         mutex_lock(&task->cap_info->lock);
    273         hash_table_apply(&task->cap_info->caps, cap_reclaimer, &cap);
    274 
    275         /*
    276          * If we don't have a capability by now, try to allocate a new one.
    277          */
     247        mutex_lock(&task->cap_info->lock);
     248        cap_t *cap = slab_alloc(cap_cache, FRAME_ATOMIC);
    278249        if (!cap) {
    279                 cap = slab_alloc(cap_cache, FRAME_ATOMIC);
    280                 if (!cap) {
    281                         mutex_unlock(&task->cap_info->lock);
    282                         return ENOMEM;
    283                 }
    284                 uintptr_t hbase;
    285                 if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) {
    286                         slab_free(cap_cache, cap);
    287                         mutex_unlock(&task->cap_info->lock);
    288                         return ENOMEM;
    289                 }
    290                 cap_initialize(cap, task, (cap_handle_t) hbase);
    291                 hash_table_insert(&task->cap_info->caps, &cap->caps_link);
    292         }
     250                mutex_unlock(&task->cap_info->lock);
     251                return ENOMEM;
     252        }
     253        uintptr_t hbase;
     254        if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) {
     255                slab_free(cap_cache, cap);
     256                mutex_unlock(&task->cap_info->lock);
     257                return ENOMEM;
     258        }
     259        cap_initialize(cap, task, (cap_handle_t) hbase);
     260        hash_table_insert(&task->cap_info->caps, &cap->caps_link);
    293261
    294262        cap->state = CAP_STATE_ALLOCATED;
Note: See TracChangeset for help on using the changeset viewer.