Changeset e9d15d9 in mainline for kernel/generic


Ignore:
Timestamp:
2017-08-18T21:15:26Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
24abb85d
Parents:
1c85bae
Message:

Turn IRQ structures into kernel objects

ipc_irq_subscribe() now returns a capability for the underlying IRQ kernel
object. ipc_irq_unsubscribe() can now be done only with a valid IRQ capability.

Location:
kernel/generic
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/irq.h

    r1c85bae re9d15d9  
    5353extern void ipc_irq_top_half_handler(irq_t *);
    5454
    55 extern int ipc_irq_unsubscribe(answerbox_t *, inr_t, devno_t);
     55extern int ipc_irq_unsubscribe(answerbox_t *, int);
    5656extern void ipc_irq_cleanup(answerbox_t *);
    5757
  • kernel/generic/include/ipc/sysipc.h

    r1c85bae re9d15d9  
    5757
    5858extern sysarg_t sys_ipc_irq_subscribe(inr_t, devno_t, sysarg_t, irq_code_t *);
    59 extern sysarg_t sys_ipc_irq_unsubscribe(inr_t, devno_t);
     59extern sysarg_t sys_ipc_irq_unsubscribe(sysarg_t);
    6060
    6161#ifdef __32_BITS__
  • kernel/generic/include/kobject/kobject.h

    r1c85bae re9d15d9  
    3838#include <typedefs.h>
    3939#include <ipc/ipc.h>
     40#include <ddi/irq.h>
    4041
    4142#define MAX_KERNEL_OBJECTS  64
    42 
    43 #define KOBJECT_INVALID_CAP -1
    4443
    4544typedef enum {
    4645        KOBJECT_TYPE_INVALID,
    4746        KOBJECT_TYPE_ALLOCATED,
    48         KOBJECT_TYPE_PHONE
     47        KOBJECT_TYPE_PHONE,
     48        KOBJECT_TYPE_IRQ
    4949} kobject_type_t;
    5050
     
    5555        union {
    5656                phone_t phone;
     57                irq_t irq;
    5758        };
    5859} kobject_t;
     
    6061struct task;
    6162
    62 extern void kobject_init(kobject_t *);
     63extern void kobject_initialize(kobject_t *);
    6364extern kobject_t *kobject_get(struct task *, int, kobject_type_t);
    6465extern kobject_t *kobject_get_current(int, kobject_type_t);
  • kernel/generic/include/proc/task.h

    r1c85bae re9d15d9  
    3737
    3838#include <cpu.h>
    39 #include <kobject/kobject.h>
    4039#include <ipc/ipc.h>
    4140#include <ipc/event.h>
     
    6665
    6766struct thread;
     67struct kobject;
    6868
    6969/** Task structure. */
     
    9898
    9999        /** Kernel objects */
    100         kobject_t kobject[MAX_KERNEL_OBJECTS];
     100        struct kobject *kobject;
    101101       
    102102        /* IPC stuff */
  • kernel/generic/src/ipc/ipc.c

    r1c85bae re9d15d9  
    5959#include <arch/interrupt.h>
    6060#include <ipc/irq.h>
     61#include <kobject/kobject.h>
    6162
    6263static void ipc_forget_call(call_t *);
  • kernel/generic/src/ipc/ipcrsc.c

    r1c85bae re9d15d9  
    133133#include <assert.h>
    134134#include <abi/errno.h>
     135#include <kobject/kobject.h>
    135136
    136137/** Find call_t * in call table according to callid.
     
    198199 *
    199200 * @return  New phone capability.
    200  * @return  KOBJECT_INVALID_CAP if a new capability cannot be allocated.
     201 * @return  Negative error code if a new capability cannot be allocated.
    201202 */
    202203int phone_alloc(task_t *task)
    203204{
    204205        int cap = kobject_alloc(task);
    205         if (cap != KOBJECT_INVALID_CAP) {
     206        if (cap >= 0) {
    206207                irq_spinlock_lock(&task->lock, true);
    207208                kobject_t *kobj = &task->kobject[cap];
  • kernel/generic/src/ipc/irq.c

    r1c85bae re9d15d9  
    8484#include <print.h>
    8585#include <macros.h>
     86#include <kobject/kobject.h>
    8687
    8788static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
     
    298299 * @param ucode   Uspace pointer to top-half pseudocode.
    299300 *
    300  * @return EOK on success or a negative error code.
     301 * @return  IRQ capability.
     302 * @return  Negative error code.
    301303 *
    302304 */
     
    321323       
    322324        /*
    323          * Allocate and populate the IRQ structure.
     325         * Allocate and populate the IRQ kernel object.
    324326         */
    325         irq_t *irq = malloc(sizeof(irq_t), 0);
    326        
     327        int cap = kobject_alloc(TASK);
     328        if (cap < 0)
     329                return cap;
     330        kobject_t *kobj = kobject_get_current(cap, KOBJECT_TYPE_ALLOCATED);
     331        assert(kobj);
     332        kobj->type = KOBJECT_TYPE_IRQ;
     333
     334        irq_t *irq = &kobj->irq;
    327335        irq_initialize(irq);
    328336        irq->devno = devno;
     
    351359                irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    352360               
    353                 free(irq);
     361                kobject_free(TASK, cap);
    354362                return EEXIST;
    355363        }
     
    366374        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    367375       
    368         return EOK;
     376        return cap;
    369377}
    370378
    371379/** Unsubscribe task from IRQ notification.
    372380 *
    373  * @param box   Answerbox associated with the notification.
    374  * @param inr   IRQ number.
    375  * @param devno Device number.
     381 * @param box      Answerbox associated with the notification.
     382 * @param irq_cap  IRQ capability.
    376383 *
    377384 * @return EOK on success or a negative error code.
    378385 *
    379386 */
    380 int ipc_irq_unsubscribe(answerbox_t *box, inr_t inr, devno_t devno)
    381 {
    382         sysarg_t key[] = {
    383                 (sysarg_t) inr,
    384                 (sysarg_t) devno
    385         };
    386        
    387         if ((inr < 0) || (inr > last_inr))
    388                 return ELIMIT;
    389        
     387int ipc_irq_unsubscribe(answerbox_t *box, int irq_cap)
     388{
     389        kobject_t *kobj = kobject_get_current(irq_cap, KOBJECT_TYPE_IRQ);
     390        if (!kobj)
     391                return ENOENT;
     392        irq_t *irq = &kobj->irq;
     393
    390394        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    391         link_t *lnk = hash_table_find(&irq_uspace_hash_table, key);
    392         if (!lnk) {
    393                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    394                 return ENOENT;
    395         }
    396        
    397         irq_t *irq = hash_table_get_instance(lnk, irq_t, link);
    398        
    399         /* irq is locked */
     395        irq_spinlock_lock(&irq->lock, false);
    400396        irq_spinlock_lock(&box->irq_lock, false);
    401397       
     
    405401        list_remove(&irq->notif_cfg.link);
    406402       
    407         /*
    408          * We need to drop the IRQ lock now because hash_table_remove() will try
    409          * to reacquire it. That basically violates the natural locking order,
    410          * but a deadlock in hash_table_remove() is prevented by the fact that
    411          * we already held the IRQ lock and didn't drop the hash table lock in
    412          * the meantime.
    413          */
    414         irq_spinlock_unlock(&irq->lock, false);
    415        
    416403        /* Remove the IRQ from the uspace IRQ hash table. */
    417         hash_table_remove(&irq_uspace_hash_table, key, 2);
     404        hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
    418405       
    419406        irq_spinlock_unlock(&box->irq_lock, false);
     407        /* irq->lock unlocked by the hash table remove_callback */
    420408        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    421409       
     
    423411        code_free(irq->notif_cfg.code);
    424412       
    425         /* Free up the IRQ structure. */
    426         free(irq);
     413        /* Free up the IRQ kernel object. */
     414        kobject_free(TASK, irq_cap);
    427415       
    428416        return EOK;
     
    431419/** Disconnect all IRQ notifications from an answerbox.
    432420 *
    433  * This function is effective because the answerbox contains
    434  * list of all irq_t structures that are subscribed to
    435  * send notifications to it.
     421 * This function is effective because the answerbox contains list of all irq_t
     422 * structures that are subscribed to send notifications to it.
    436423 *
    437424 * @param box Answerbox for which we want to carry out the cleanup.
     
    460447                }
    461448               
    462                 sysarg_t key[2];
    463                 key[0] = irq->inr;
    464                 key[1] = irq->devno;
    465                
    466449                assert(irq->notif_cfg.answerbox == box);
    467450               
     
    469452                list_remove(&irq->notif_cfg.link);
    470453               
    471                 /*
    472                  * We need to drop the IRQ lock now because hash_table_remove()
    473                  * will try to reacquire it. That basically violates the natural
    474                  * locking order, but a deadlock in hash_table_remove() is
    475                  * prevented by the fact that we already held the IRQ lock and
    476                  * didn't drop the hash table lock in the meantime.
    477                  */
    478                 irq_spinlock_unlock(&irq->lock, false);
    479                
    480454                /* Remove from the hash table. */
    481                 hash_table_remove(&irq_uspace_hash_table, key, 2);
     455                hash_table_remove_item(&irq_uspace_hash_table, &irq->link);
    482456               
    483457                /*
     
    488462               
    489463                code_free(irq->notif_cfg.code);
    490                 free(irq);
     464               
     465                // XXX: what to do about the irq capability? The task is in
     466                // clean-up anyway.
    491467               
    492468                /* Reacquire both locks before taking another round. */
  • kernel/generic/src/ipc/sysipc.c

    r1c85bae re9d15d9  
    805805 * @param ucode   Uspace pointer to the top-half pseudocode.
    806806 *
    807  * @return EPERM or a return code returned by ipc_irq_subscribe().
     807 * @return IRQ kernel object capability
     808 * @return EPERM
     809 * @return Error code returned by ipc_irq_subscribe().
    808810 *
    809811 */
     
    825827 *
    826828 */
    827 sysarg_t sys_ipc_irq_unsubscribe(inr_t inr, devno_t devno)
     829sysarg_t sys_ipc_irq_unsubscribe(sysarg_t cap)
    828830{
    829831        if (!(perm_get(TASK) & PERM_IRQ_REG))
    830832                return EPERM;
    831833       
    832         ipc_irq_unsubscribe(&TASK->answerbox, inr, devno);
     834        ipc_irq_unsubscribe(&TASK->answerbox, cap);
    833835       
    834836        return 0;
  • kernel/generic/src/kobject/kobject.c

    r1c85bae re9d15d9  
    3636#include <proc/task.h>
    3737#include <synch/spinlock.h>
     38#include <abi/errno.h>
    3839
    39 void kobject_init(kobject_t *kobj)
     40void kobject_initialize(kobject_t *kobj)
    4041{
    4142        kobj->type = KOBJECT_TYPE_INVALID;
     
    6667                if (kobj->type > KOBJECT_TYPE_ALLOCATED) {
    6768                        if (kobj->can_reclaim && kobj->can_reclaim(kobj))
    68                                 kobject_init(kobj);
     69                                kobject_initialize(kobj);
    6970                }
    7071                if (kobj->type == KOBJECT_TYPE_INVALID) {
     
    7677        irq_spinlock_unlock(&task->lock, true);
    7778
    78         return KOBJECT_INVALID_CAP;
     79        return ELIMIT;
    7980}
    8081
     
    8687
    8788        irq_spinlock_lock(&task->lock, true);
    88         kobject_init(&task->kobject[cap]);
     89        kobject_initialize(&task->kobject[cap]);
    8990        irq_spinlock_unlock(&task->lock, true);
    9091}
  • kernel/generic/src/proc/task.c

    r1c85bae re9d15d9  
    5050#include <adt/btree.h>
    5151#include <adt/list.h>
     52#include <kobject/kobject.h>
    5253#include <ipc/ipc.h>
    5354#include <ipc/ipcrsc.h>
     
    166167       
    167168        list_initialize(&task->threads);
    168 
    169         int cap;
    170         for (cap = 0; cap < MAX_KERNEL_OBJECTS; cap++)
    171                 kobject_init(&task->kobject[cap]);
     169       
     170        task->kobject = malloc(sizeof(kobject_t) * MAX_KERNEL_OBJECTS, 0);
    172171       
    173172        ipc_answerbox_init(&task->answerbox, task);
     
    206205        task->ucycles = 0;
    207206        task->kcycles = 0;
     207
     208        int cap;
     209        for (cap = 0; cap < MAX_KERNEL_OBJECTS; cap++)
     210                kobject_initialize(&task->kobject[cap]);
    208211
    209212        task->ipc_info.call_sent = 0;
     
    282285        as_release(task->as);
    283286       
     287        free(task->kobject);
     288
    284289        slab_free(task_slab, task);
    285290}
Note: See TracChangeset for help on using the changeset viewer.