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

Changeset c1f68b0 in mainline


Ignore:
Timestamp:
2017-10-28T11:40:41Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
eca820c
Parents:
15d9fe6
Message:

Use recursive mutex to protect task_t::cap_info

This makes it possible to use the mutex-protected capability APIs even
inside caps_apply_to_kobject_type() callbacks. Now there is no need to
provide eg. cap_unpublish_locked() and cap_free_locked(). Likewise,
ipc_irq_unsubscribe() can be used when the task's cap_info is already
locked by the current thread inside of a callback.

Location:
kernel/generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/cap/cap.h

    r15d9fe6 rc1f68b0  
    121121extern void cap_publish(struct task *, cap_handle_t, kobject_t *);
    122122extern kobject_t *cap_unpublish(struct task *, cap_handle_t, kobject_type_t);
    123 extern kobject_t *cap_unpublish_locked(struct task *, cap_handle_t,
    124     kobject_type_t);
    125123extern void cap_free(struct task *, cap_handle_t);
    126 extern void cap_free_locked(struct task *, cap_handle_t);
    127124
    128125extern void kobject_initialize(kobject_t *, kobject_type_t, void *,
  • kernel/generic/src/cap/cap.c

    r15d9fe6 rc1f68b0  
    148148void caps_task_init(task_t *task)
    149149{
    150         mutex_initialize(&task->cap_info->lock, MUTEX_PASSIVE);
     150        mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE);
    151151
    152152        for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
     
    238238        if (cap->state == CAP_STATE_PUBLISHED && cap->kobject->ops->reclaim &&
    239239            cap->kobject->ops->reclaim(cap->kobject)) {
    240                 kobject_t *kobj = cap_unpublish_locked(cap->task, cap->handle,
     240                kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
    241241                    cap->kobject->type);
    242242                kobject_put(kobj);
     
    318318}
    319319
    320 /** @copydoc cap_unpublish()
    321  *
    322  * Can only be called internally by the capability subsytem or from a
    323  * caps_apply_to_kobject_type() callback.
    324  */
    325 kobject_t *
    326 cap_unpublish_locked(task_t *task, cap_handle_t handle, kobject_type_t type)
     320/** Unpublish published capability
     321 *
     322 * The kernel object is moved out of the capability. In other words, the
     323 * capability's reference to the objects is handed over to the kernel object
     324 * pointer returned by this function. Once unpublished, the capability does not
     325 * refer to any kernel object anymore.
     326 *
     327 * @param task    Task in which to unpublish the capability.
     328 * @param handle  Capability handle.
     329 * @param type    Kernel object type of the object associated with the
     330 *                capability.
     331 */
     332kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type)
    327333{
    328334        kobject_t *kobj = NULL;
    329335
     336        mutex_lock(&task->cap_info->lock);
    330337        cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED);
    331338        if (cap) {
     
    338345                }
    339346        }
     347        mutex_unlock(&task->cap_info->lock);
    340348
    341349        return kobj;
    342350}
    343351
    344 /** Unpublish published capability
    345  *
    346  * The kernel object is moved out of the capability. In other words, the
    347  * capability's reference to the objects is handed over to the kernel object
    348  * pointer returned by this function. Once unpublished, the capability does not
    349  * refer to any kernel object anymore.
    350  *
    351  * @param task    Task in which to unpublish the capability.
     352/** Free allocated capability
     353 *
     354 * @param task    Task in which to free the capability.
    352355 * @param handle  Capability handle.
    353  * @param type    Kernel object type of the object associated with the
    354  *                capability.
    355  */
    356 kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type)
    357 {
    358 
    359         mutex_lock(&task->cap_info->lock);
    360         kobject_t *kobj = cap_unpublish_locked(task, handle, type);
    361         mutex_unlock(&task->cap_info->lock);
    362 
    363         return kobj;
    364 }
    365 
    366 /** @copydoc cap_free()
    367  *
    368  * Can only be called internally by the capability subsytem or from a
    369  * caps_apply_to_kobject_type() callback.
    370  */
    371 void cap_free_locked(task_t *task, cap_handle_t handle)
     356 */
     357void cap_free(task_t *task, cap_handle_t handle)
    372358{
    373359        assert(handle >= 0);
    374360        assert(handle < MAX_CAPS);
    375361
     362        mutex_lock(&task->cap_info->lock);
    376363        cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED);
    377364
     
    381368        ra_free(task->cap_info->handles, handle, 1);
    382369        slab_free(cap_slab, cap);
    383 }
    384 
    385 /** Free allocated capability
    386  *
    387  * @param task    Task in which to free the capability.
    388  * @param handle  Capability handle.
    389  */
    390 void cap_free(task_t *task, cap_handle_t handle)
    391 {
    392         mutex_lock(&task->cap_info->lock);
    393         cap_free_locked(task, handle);
    394370        mutex_unlock(&task->cap_info->lock);
    395371}
  • kernel/generic/src/ipc/ipc.c

    r15d9fe6 rc1f68b0  
    829829{
    830830        ipc_phone_hangup(cap->kobject->phone);
    831         kobject_t *kobj = cap_unpublish_locked(cap->task, cap->handle,
     831        kobject_t *kobj = cap_unpublish(cap->task, cap->handle,
    832832            KOBJECT_TYPE_PHONE);
    833833        kobject_put(kobj);
    834         cap_free_locked(cap->task, cap->handle);
     834        cap_free(cap->task, cap->handle);
    835835        return true;
    836836}
     
    839839{
    840840        ipc_irq_unsubscribe(&TASK->answerbox, cap->handle);
    841         kobject_t *kobj = cap_unpublish_locked(cap->task, cap->handle,
    842             KOBJECT_TYPE_IRQ);
    843         kobject_put(kobj);
    844         cap_free_locked(cap->task, cap->handle);
    845841        return true;
    846842}
  • kernel/generic/src/ipc/irq.c

    r15d9fe6 rc1f68b0  
    271271}
    272272
     273static void irq_hash_out(irq_t *irq)
     274{
     275        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     276        irq_spinlock_lock(&irq->lock, false);
     277       
     278        if (irq->notif_cfg.hashed_in) {
     279                /* Remove the IRQ from the uspace IRQ hash table. */
     280                hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
     281                irq->notif_cfg.hashed_in = false;
     282        }
     283
     284        irq_spinlock_unlock(&irq->lock, false);
     285        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     286}
     287
    273288static void irq_destroy(void *arg)
    274289{
    275290        irq_t *irq = (irq_t *) arg;
     291
     292        irq_hash_out(irq);
    276293
    277294        /* Free up the IRQ code and associated structures. */
     
    373390        assert(kobj->irq->notif_cfg.answerbox == box);
    374391
    375         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    376         irq_spinlock_lock(&kobj->irq->lock, false);
    377        
    378         if (kobj->irq->notif_cfg.hashed_in) {
    379                 /* Remove the IRQ from the uspace IRQ hash table. */
    380                 hash_table_remove_item(&irq_uspace_hash_table,
    381                     &kobj->irq->link);
    382                 kobj->irq->notif_cfg.hashed_in = false;
    383         }
    384 
    385         irq_spinlock_unlock(&kobj->irq->lock, false);
    386         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     392        irq_hash_out(kobj->irq);
    387393
    388394        kobject_put(kobj);
Note: See TracChangeset for help on using the changeset viewer.