Changeset 91b60499 in mainline for kernel/generic/src


Ignore:
Timestamp:
2017-09-30T06:29:42Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
300f4c4
Parents:
d076f16 (diff), 6636fb19 (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.
Message:

Merge support for capabilities from lp:~jakub/helenos/caps

This commit introduces capabilities as task-local names for references to kernel
objects. Kernel objects are reference-counted wrappers for a select group of
objects allocated in and by the kernel that can be made accessible to userspace
in a controlled way via integer handles.

So far, a kernel object encapsulates either an irq_t or a phone_t.

Support for the former lead to the removal of kernel-assigned devnos and
unsecure deregistration of IRQs in which a random task was able to unregister
some other task's IRQ.

Location:
kernel/generic/src
Files:
1 added
3 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/adt/hash_table.c

    rd076f16 r91b60499  
    190190}
    191191
     192/** Remove an existing item from hash table.
     193 *
     194 * @param h     Hash table.
     195 * @param item  Item to remove from the hash table.
     196 */
     197void hash_table_remove_item(hash_table_t *h, link_t *item)
     198{
     199        assert(h);
     200        assert(h->op);
     201       
     202        list_remove(item);
     203        if (h->op->remove_callback)
     204                h->op->remove_callback(item);
     205}
     206
    192207/** @}
    193208 */
  • kernel/generic/src/console/kconsole.c

    rd076f16 r91b60499  
    5555#include <str.h>
    5656#include <sysinfo/sysinfo.h>
    57 #include <ddi/device.h>
    5857#include <symtab.h>
    5958#include <errno.h>
  • kernel/generic/src/ddi/irq.c

    rd076f16 r91b60499  
    3232/**
    3333 * @file
    34  * @brief IRQ dispatcher.
    35  *
    36  * This file provides means of connecting IRQs with particular devices and logic
    37  * for dispatching interrupts to IRQ handlers defined by those devices.
    38  *
    39  * This code is designed to support:
    40  * - multiple devices sharing single IRQ
    41  * - multiple IRQs per single device
    42  * - multiple instances of the same device
    43  *
    44  *
    45  * Note about architectures.
    46  *
    47  * Some architectures have the term IRQ well defined. Examples of such
    48  * architectures include amd64, ia32 and mips32. Some other architectures, such
    49  * as sparc64, don't use the term at all. In those cases, we boldly step forward
    50  * and define what an IRQ is.
    51  *
    52  * The implementation is generic enough and still allows the architectures to
    53  * use the hardware layout effectively.  For instance, on amd64 and ia32, where
    54  * there is only 16 IRQs, the irq_hash_table can be optimized to a
    55  * one-dimensional array. Next, when it is known that the IRQ numbers (aka
    56  * INR's) are unique, the claim functions can always return IRQ_ACCEPT.
    57  *
    58  *
    59  * Note about the irq_hash_table.
    60  *
    61  * The hash table is configured to use two keys: inr and devno.  However, the
    62  * hash index is computed only from inr. Moreover, if devno is -1, the match is
    63  * based on the return value of the claim() function instead of on devno.
     34 * @brief IRQ dispatcher
     35 *
     36 * This file provides means of connecting IRQs with respective device drivers
     37 * and logic for dispatching interrupts to IRQ handlers defined by those
     38 * drivers.
    6439 */
    6540
     
    7449#include <arch.h>
    7550
    76 #define KEY_INR    0
    77 #define KEY_DEVNO  1
    78 
    79 /** Spinlock protecting the kernel IRQ hash table.
     51slab_cache_t *irq_slab = NULL;
     52
     53/** Spinlock protecting the kernel IRQ hash table
    8054 *
    8155 * This lock must be taken only when interrupts are disabled.
     
    8761static hash_table_t irq_kernel_hash_table;
    8862
    89 /** Spinlock protecting the uspace IRQ hash table.
     63/** Spinlock protecting the uspace IRQ hash table
    9064 *
    9165 * This lock must be taken only when interrupts are disabled.
     
    9468IRQ_SPINLOCK_INITIALIZE(irq_uspace_hash_table_lock);
    9569
    96 /** The uspace IRQ hash table. */
     70/** The uspace IRQ hash table */
    9771hash_table_t irq_uspace_hash_table;
    9872
    99 /**
    100  * Hash table operations for cases when we know that there will be collisions
    101  * between different keys.
    102  */
    10373static size_t irq_ht_hash(sysarg_t *key);
    10474static bool irq_ht_compare(sysarg_t *key, size_t keys, link_t *item);
     
    11181};
    11282
    113 /**
    114  * Hash table operations for cases when we know that there will be no collisions
    115  * between different keys.  However, there might be still collisions among
    116  * elements with single key (sharing of one IRQ).
    117  */
    118 static size_t irq_lin_hash(sysarg_t *key);
    119 static bool irq_lin_compare(sysarg_t *key, size_t keys, link_t *item);
    120 static void irq_lin_remove(link_t *item);
    121 
    122 static hash_table_operations_t irq_lin_ops = {
    123         .hash = irq_lin_hash,
    124         .compare = irq_lin_compare,
    125         .remove_callback = irq_lin_remove,
    126 };
    127 
    128 /** Number of buckets in either of the hash tables. */
     83/** Number of buckets in either of the hash tables */
    12984static size_t buckets;
    13085
    131 /** Last valid INR. */
     86/** Last valid INR */
    13287inr_t last_inr = 0;
    13388
    134 /** Initialize IRQ subsystem.
    135  *
    136  * @param inrs   Numbers of unique IRQ numbers or INRs.
    137  * @param chains Number of chains in the hash table.
     89/** Initialize IRQ subsystem
     90 *
     91 * @param inrs    Numbers of unique IRQ numbers or INRs.
     92 * @param chains  Number of buckets in the hash table.
    13893 *
    13994 */
     
    14398        last_inr = inrs - 1;
    14499
    145         /*
    146          * Be smart about the choice of the hash table operations.  In cases in
    147          * which inrs equals the requested number of chains (i.e. where there is
    148          * no collision between different keys), we can use optimized set of
    149          * operations.
    150          */
    151         if (inrs == chains) {
    152                 hash_table_create(&irq_uspace_hash_table, chains, 2,
    153                     &irq_lin_ops);
    154                 hash_table_create(&irq_kernel_hash_table, chains, 2,
    155                     &irq_lin_ops);
    156         } else {
    157                 hash_table_create(&irq_uspace_hash_table, chains, 2,
    158                     &irq_ht_ops);
    159                 hash_table_create(&irq_kernel_hash_table, chains, 2,
    160                     &irq_ht_ops);
    161         }
    162 }
    163 
    164 /** Initialize one IRQ structure.
    165  *
    166  * @param irq Pointer to the IRQ structure to be initialized.
     100        irq_slab = slab_cache_create("irq_t", sizeof(irq_t), 0, NULL, NULL,
     101            FRAME_ATOMIC);
     102        assert(irq_slab);
     103
     104        hash_table_create(&irq_uspace_hash_table, chains, 2, &irq_ht_ops);
     105        hash_table_create(&irq_kernel_hash_table, chains, 2, &irq_ht_ops);
     106}
     107
     108/** Initialize one IRQ structure
     109 *
     110 * @param irq  Pointer to the IRQ structure to be initialized.
    167111 *
    168112 */
     
    172116        link_initialize(&irq->link);
    173117        irq_spinlock_initialize(&irq->lock, "irq.lock");
    174         link_initialize(&irq->notif_cfg.link);
    175118        irq->inr = -1;
    176         irq->devno = -1;
    177119       
    178120        irq_initialize_arch(irq);
    179121}
    180122
    181 /** Register IRQ for device.
     123/** Register IRQ for device
    182124 *
    183125 * The irq structure must be filled with information about the interrupt source
    184126 * and with the claim() function pointer and handler() function pointer.
    185127 *
    186  * @param irq IRQ structure belonging to a device.
     128 * @param irq  IRQ structure belonging to a device.
    187129 *
    188130 */
     
    190132{
    191133        sysarg_t key[] = {
    192                 (sysarg_t) irq->inr,
    193                 (sysarg_t) irq->devno
     134                [IRQ_HT_KEY_INR] = (sysarg_t) irq->inr,
     135                [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM
    194136        };
    195137       
     
    201143}
    202144
    203 /** Search and lock the uspace IRQ hash table.
    204  *
    205  */
     145/** Search and lock the uspace IRQ hash table */
    206146static irq_t *irq_dispatch_and_lock_uspace(inr_t inr)
    207147{
    208148        link_t *lnk;
    209149        sysarg_t key[] = {
    210                 (sysarg_t) inr,
    211                 (sysarg_t) -1    /* Search will use claim() instead of devno */
     150                [IRQ_HT_KEY_INR] = (sysarg_t) inr,
     151                [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM
    212152        };
    213153       
     
    224164}
    225165
    226 /** Search and lock the kernel IRQ hash table.
    227  *
    228  */
     166/** Search and lock the kernel IRQ hash table */
    229167static irq_t *irq_dispatch_and_lock_kernel(inr_t inr)
    230168{
    231169        link_t *lnk;
    232170        sysarg_t key[] = {
    233                 (sysarg_t) inr,
    234                 (sysarg_t) -1    /* Search will use claim() instead of devno */
     171                [IRQ_HT_KEY_INR] = (sysarg_t) inr,
     172                [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM
    235173        };
    236174       
     
    247185}
    248186
    249 /** Dispatch the IRQ.
     187/** Dispatch the IRQ
    250188 *
    251189 * We assume this function is only called from interrupt context (i.e. that
     
    255193 * return with interrupts disabled and holding the respective structure.
    256194 *
    257  * @param inr Interrupt number (aka inr or irq).
     195 * @param inr  Interrupt number (aka inr or irq).
    258196 *
    259197 * @return IRQ structure of the respective device
     
    285223}
    286224
    287 /** Compute hash index for the key.
    288  *
    289  * This function computes hash index into the IRQ hash table for which there can
    290  * be collisions between different INRs.
    291  *
    292  * The devno is not used to compute the hash.
    293  *
    294  * @param key The first of the keys is inr and the second is devno or -1.
     225/** Compute hash index for the key
     226 *
     227 * @param key  The first of the keys is inr and the second is mode. Only inr is
     228 *             used to compute the hash.
    295229 *
    296230 * @return Index into the hash table.
     
    299233size_t irq_ht_hash(sysarg_t key[])
    300234{
    301         inr_t inr = (inr_t) key[KEY_INR];
     235        inr_t inr = (inr_t) key[IRQ_HT_KEY_INR];
    302236        return inr % buckets;
    303237}
    304238
    305 /** Compare hash table element with a key.
    306  *
    307  * There are two things to note about this function.  First, it is used for the
    308  * more complex architecture setup in which there are way too many interrupt
    309  * numbers (i.e. inr's) to arrange the hash table so that collisions occur only
    310  * among same inrs of different devnos. So the explicit check for inr match must
    311  * be done.  Second, if devno is -1, the second key (i.e. devno) is not used for
    312  * the match and the result of the claim() function is used instead.
     239/** Compare hash table element with a key
     240 *
     241 * If mode is IRQ_HT_MODE_CLAIM, the result of the claim() function is used for
     242 * the match. Otherwise the key does not match.
    313243 *
    314244 * This function assumes interrupts are already disabled.
    315245 *
    316  * @param key  Keys (i.e. inr and devno).
    317  * @param keys This is 2.
    318  * @param item The item to compare the key with.
    319  *
    320  * @return true on match
    321  * @return false on no match
     246 * @param key   Keys (i.e. inr and mode).
     247 * @param keys  This is 2.
     248 * @param item  The item to compare the key with.
     249 *
     250 * @return True on match
     251 * @return False on no match
    322252 *
    323253 */
     
    325255{
    326256        irq_t *irq = hash_table_get_instance(item, irq_t, link);
    327         inr_t inr = (inr_t) key[KEY_INR];
    328         devno_t devno = (devno_t) key[KEY_DEVNO];
     257        inr_t inr = (inr_t) key[IRQ_HT_KEY_INR];
     258        irq_ht_mode_t mode = (irq_ht_mode_t) key[IRQ_HT_KEY_MODE];
    329259       
    330260        bool rv;
    331261       
    332262        irq_spinlock_lock(&irq->lock, false);
    333         if (devno == -1) {
     263        if (mode == IRQ_HT_MODE_CLAIM) {
    334264                /* Invoked by irq_dispatch_and_lock(). */
    335                 rv = ((irq->inr == inr) &&
    336                     (irq->claim(irq) == IRQ_ACCEPT));
     265                rv = ((irq->inr == inr) && (irq->claim(irq) == IRQ_ACCEPT));
    337266        } else {
    338267                /* Invoked by irq_find_and_lock(). */
    339                 rv = ((irq->inr == inr) && (irq->devno == devno));
     268                rv = false;
    340269        }
    341270       
     
    347276}
    348277
    349 /** Unlock IRQ structure after hash_table_remove().
    350  *
    351  * @param lnk Link in the removed and locked IRQ structure.
     278/** Unlock IRQ structure after hash_table_remove()
     279 *
     280 * @param lnk  Link in the removed and locked IRQ structure.
    352281 */
    353282void irq_ht_remove(link_t *lnk)
     
    358287}
    359288
    360 /** Compute hash index for the key.
    361  *
    362  * This function computes hash index into the IRQ hash table for which there are
    363  * no collisions between different INRs.
    364  *
    365  * @param key The first of the keys is inr and the second is devno or -1.
    366  *
    367  * @return Index into the hash table.
    368  *
    369  */
    370 size_t irq_lin_hash(sysarg_t key[])
    371 {
    372         inr_t inr = (inr_t) key[KEY_INR];
    373         return inr;
    374 }
    375 
    376 /** Compare hash table element with a key.
    377  *
    378  * There are two things to note about this function.  First, it is used for the
    379  * less complex architecture setup in which there are not too many interrupt
    380  * numbers (i.e. inr's) to arrange the hash table so that collisions occur only
    381  * among same inrs of different devnos. So the explicit check for inr match is
    382  * not done.  Second, if devno is -1, the second key (i.e. devno) is not used
    383  * for the match and the result of the claim() function is used instead.
    384  *
    385  * This function assumes interrupts are already disabled.
    386  *
    387  * @param key  Keys (i.e. inr and devno).
    388  * @param keys This is 2.
    389  * @param item The item to compare the key with.
    390  *
    391  * @return true on match
    392  * @return false on no match
    393  *
    394  */
    395 bool irq_lin_compare(sysarg_t key[], size_t keys, link_t *item)
    396 {
    397         irq_t *irq = list_get_instance(item, irq_t, link);
    398         devno_t devno = (devno_t) key[KEY_DEVNO];
    399         bool rv;
    400        
    401         irq_spinlock_lock(&irq->lock, false);
    402         if (devno == -1) {
    403                 /* Invoked by irq_dispatch_and_lock() */
    404                 rv = (irq->claim(irq) == IRQ_ACCEPT);
    405         } else {
    406                 /* Invoked by irq_find_and_lock() */
    407                 rv = (irq->devno == devno);
    408         }
    409        
    410         /* unlock only on non-match */
    411         if (!rv)
    412                 irq_spinlock_unlock(&irq->lock, false);
    413        
    414         return rv;
    415 }
    416 
    417 /** Unlock IRQ structure after hash_table_remove().
    418  *
    419  * @param lnk Link in the removed and locked IRQ structure.
    420  *
    421  */
    422 void irq_lin_remove(link_t *lnk)
    423 {
    424         irq_t *irq __attribute__((unused))
    425             = hash_table_get_instance(lnk, irq_t, link);
    426         irq_spinlock_unlock(&irq->lock, false);
    427 }
    428 
    429289/** @}
    430290 */
  • kernel/generic/src/ipc/ipc.c

    rd076f16 r91b60499  
    4343#include <synch/waitq.h>
    4444#include <ipc/ipc.h>
     45#include <ipc/ipcrsc.h>
    4546#include <abi/ipc/methods.h>
    4647#include <ipc/kbox.h>
     
    5859#include <arch/interrupt.h>
    5960#include <ipc/irq.h>
     61#include <cap/cap.h>
    6062
    6163static void ipc_forget_call(call_t *);
     
    6466answerbox_t *ipc_phone_0 = NULL;
    6567
    66 static slab_cache_t *ipc_call_slab;
    67 static slab_cache_t *ipc_answerbox_slab;
     68static slab_cache_t *call_slab;
     69static slab_cache_t *answerbox_slab;
     70
     71slab_cache_t *phone_slab = NULL;
    6872
    6973/** Initialize a call structure.
     
    9397                if (call->buffer)
    9498                        free(call->buffer);
    95                 slab_free(ipc_call_slab, call);
     99                slab_free(call_slab, call);
    96100        }
    97101}
     
    110114call_t *ipc_call_alloc(unsigned int flags)
    111115{
    112         call_t *call = slab_alloc(ipc_call_slab, flags);
     116        call_t *call = slab_alloc(call_slab, flags);
    113117        if (call) {
    114118                _ipc_call_init(call);
     
    145149        list_initialize(&box->answers);
    146150        list_initialize(&box->irq_notifs);
    147         list_initialize(&box->irq_list);
    148151        box->task = task;
    149152}
     
    151154/** Connect a phone to an answerbox.
    152155 *
    153  * @param phone Initialized phone structure.
    154  * @param box   Initialized answerbox structure.
    155  * @return      True if the phone was connected, false otherwise.
     156 * This function must be passed a reference to phone->kobject.
     157 *
     158 * @param phone  Initialized phone structure.
     159 * @param box    Initialized answerbox structure.
     160 * @return       True if the phone was connected, false otherwise.
    156161 */
    157162bool ipc_phone_connect(phone_t *phone, answerbox_t *box)
     
    166171                phone->state = IPC_PHONE_CONNECTED;
    167172                phone->callee = box;
     173                /* Pass phone->kobject reference to box->connected_phones */
    168174                list_append(&phone->link, &box->connected_phones);
    169175        }
     
    171177        irq_spinlock_unlock(&box->lock, true);
    172178        mutex_unlock(&phone->lock);
     179
     180        if (!active) {
     181                /* We still have phone->kobject's reference; drop it */
     182                kobject_put(phone->kobject);
     183        }
    173184
    174185        return active;
     
    188199        phone->state = IPC_PHONE_FREE;
    189200        atomic_set(&phone->active_calls, 0);
     201        phone->kobject = NULL;
    190202}
    191203
     
    200212int ipc_call_sync(phone_t *phone, call_t *request)
    201213{
    202         answerbox_t *mybox = slab_alloc(ipc_answerbox_slab, 0);
     214        answerbox_t *mybox = slab_alloc(answerbox_slab, 0);
    203215        ipc_answerbox_init(mybox, TASK);
    204216       
     
    208220        int rc = ipc_call(phone, request);
    209221        if (rc != EOK) {
    210                 slab_free(ipc_answerbox_slab, mybox);
     222                slab_free(answerbox_slab, mybox);
    211223                return rc;
    212224        }
     
    255267        assert(!answer || request == answer);
    256268       
    257         slab_free(ipc_answerbox_slab, mybox);
     269        slab_free(answerbox_slab, mybox);
    258270        return rc;
    259271}
     
    453465                list_remove(&phone->link);
    454466                irq_spinlock_unlock(&box->lock, true);
     467
     468                /* Drop the answerbox reference */
     469                kobject_put(phone->kobject);
    455470               
    456471                call_t *call = ipc_call_alloc(0);
     
    655670
    656671                        task_release(phone->caller);
     672
     673                        kobject_put(phone->kobject);
    657674                       
    658675                        /* Must start again */
     
    661678               
    662679                mutex_unlock(&phone->lock);
     680                kobject_put(phone->kobject);
    663681        }
    664682       
     
    707725                 * Nota bene: there may still be answers waiting for pick up.
    708726                 */
    709                 spinlock_unlock(&TASK->active_calls_lock);     
     727                spinlock_unlock(&TASK->active_calls_lock);
    710728                return;
    711729        }
     
    720738                 * call on the list.
    721739                 */
    722                 spinlock_unlock(&TASK->active_calls_lock);     
     740                spinlock_unlock(&TASK->active_calls_lock);
    723741                goto restart;
    724742        }
     
    727745
    728746        goto restart;
     747}
     748
     749static bool phone_cap_wait_cb(cap_t *cap, void *arg)
     750{
     751        phone_t *phone = cap->kobject->phone;
     752        bool *restart = (bool *) arg;
     753
     754        mutex_lock(&phone->lock);
     755        if ((phone->state == IPC_PHONE_HUNGUP) &&
     756            (atomic_get(&phone->active_calls) == 0)) {
     757                phone->state = IPC_PHONE_FREE;
     758                phone->callee = NULL;
     759        }
     760
     761        /*
     762         * We might have had some IPC_PHONE_CONNECTING phones at the beginning
     763         * of ipc_cleanup(). Depending on whether these were forgotten or
     764         * answered, they will eventually enter the IPC_PHONE_FREE or
     765         * IPC_PHONE_CONNECTED states, respectively.  In the latter case, the
     766         * other side may slam the open phones at any time, in which case we
     767         * will get an IPC_PHONE_SLAMMED phone.
     768         */
     769        if ((phone->state == IPC_PHONE_CONNECTED) ||
     770            (phone->state == IPC_PHONE_SLAMMED)) {
     771                mutex_unlock(&phone->lock);
     772                ipc_phone_hangup(phone);
     773                /*
     774                 * Now there may be one extra active call, which needs to be
     775                 * forgotten.
     776                 */
     777                ipc_forget_all_active_calls();
     778                *restart = true;
     779                return false;
     780        }
     781
     782        /*
     783         * If the hangup succeeded, it has sent a HANGUP message, the IPC is now
     784         * in HUNGUP state, we wait for the reply to come
     785         */
     786        if (phone->state != IPC_PHONE_FREE) {
     787                mutex_unlock(&phone->lock);
     788                return false;
     789        }
     790
     791        mutex_unlock(&phone->lock);
     792        return true;
    729793}
    730794
     
    733797{
    734798        call_t *call;
    735         size_t i;
     799        bool restart;
    736800
    737801restart:
     
    740804         * Locking is needed as there may be connection handshakes in progress.
    741805         */
    742         for (i = 0; i < IPC_MAX_PHONES; i++) {
    743                 phone_t *phone = &TASK->phones[i];
    744 
    745                 mutex_lock(&phone->lock);       
    746                 if ((phone->state == IPC_PHONE_HUNGUP) &&
    747                     (atomic_get(&phone->active_calls) == 0)) {
    748                         phone->state = IPC_PHONE_FREE;
    749                         phone->callee = NULL;
    750                 }
    751 
    752                 /*
    753                  * We might have had some IPC_PHONE_CONNECTING phones at the
    754                  * beginning of ipc_cleanup(). Depending on whether these were
    755                  * forgotten or answered, they will eventually enter the
    756                  * IPC_PHONE_FREE or IPC_PHONE_CONNECTED states, respectively.
    757                  * In the latter case, the other side may slam the open phones
    758                  * at any time, in which case we will get an IPC_PHONE_SLAMMED
    759                  * phone.
    760                  */
    761                 if ((phone->state == IPC_PHONE_CONNECTED) ||
    762                     (phone->state == IPC_PHONE_SLAMMED)) {
    763                         mutex_unlock(&phone->lock);
    764                         ipc_phone_hangup(phone);
    765                         /*
    766                          * Now there may be one extra active call, which needs
    767                          * to be forgotten.
    768                          */
    769                         ipc_forget_all_active_calls();
    770                         goto restart;
    771                 }
    772 
    773                 /*
    774                  * If the hangup succeeded, it has sent a HANGUP message, the
    775                  * IPC is now in HUNGUP state, we wait for the reply to come
    776                  */
    777                 if (phone->state != IPC_PHONE_FREE) {
    778                         mutex_unlock(&phone->lock);
    779                         break;
    780                 }
    781 
    782                 mutex_unlock(&phone->lock);
    783         }
    784                
    785         /* Got into cleanup */
    786         if (i == IPC_MAX_PHONES)
     806        restart = false;
     807        if (caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,
     808            phone_cap_wait_cb, &restart)) {
     809                /* Got into cleanup */
    787810                return;
    788                
     811        }
     812        if (restart)
     813                goto restart;
     814       
    789815        call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
    790816            SYNCH_FLAGS_NONE);
     
    795821        ipc_call_free(call);
    796822        goto restart;
     823}
     824
     825static bool phone_cap_cleanup_cb(cap_t *cap, void *arg)
     826{
     827        ipc_phone_hangup(cap->kobject->phone);
     828        return true;
     829}
     830
     831static bool irq_cap_cleanup_cb(cap_t *cap, void *arg)
     832{
     833        ipc_irq_unsubscribe(&TASK->answerbox, cap->handle);
     834        return true;
    797835}
    798836
     
    816854
    817855        /* Disconnect all our phones ('ipc_phone_hangup') */
    818         for (size_t i = 0; i < IPC_MAX_PHONES; i++)
    819                 ipc_phone_hangup(&TASK->phones[i]);
     856        caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE,
     857            phone_cap_cleanup_cb, NULL);
    820858       
    821859        /* Unsubscribe from any event notifications. */
    822860        event_cleanup_answerbox(&TASK->answerbox);
    823861       
    824         /* Disconnect all connected irqs */
    825         ipc_irq_cleanup(&TASK->answerbox);
     862        /* Disconnect all connected IRQs */
     863        caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_IRQ, irq_cap_cleanup_cb,
     864            NULL);
    826865       
    827866        /* Disconnect all phones connected to our regular answerbox */
     
    847886void ipc_init(void)
    848887{
    849         ipc_call_slab = slab_cache_create("call_t", sizeof(call_t), 0, NULL,
     888        call_slab = slab_cache_create("call_t", sizeof(call_t), 0, NULL,
    850889            NULL, 0);
    851         ipc_answerbox_slab = slab_cache_create("answerbox_t",
    852             sizeof(answerbox_t), 0, NULL, NULL, 0);
     890        phone_slab = slab_cache_create("phone_t", sizeof(phone_t), 0, NULL,
     891            NULL, 0);
     892        answerbox_slab = slab_cache_create("answerbox_t", sizeof(answerbox_t),
     893            0, NULL, NULL, 0);
    853894}
    854895
     
    885926}
    886927
     928static bool print_task_phone_cb(cap_t *cap, void *arg)
     929{
     930        phone_t *phone = cap->kobject->phone;
     931
     932        mutex_lock(&phone->lock);
     933        if (phone->state != IPC_PHONE_FREE) {
     934                printf("%-11d %7" PRIun " ", cap->handle,
     935                    atomic_get(&phone->active_calls));
     936               
     937                switch (phone->state) {
     938                case IPC_PHONE_CONNECTING:
     939                        printf("connecting");
     940                        break;
     941                case IPC_PHONE_CONNECTED:
     942                        printf("connected to %" PRIu64 " (%s)",
     943                            phone->callee->task->taskid,
     944                            phone->callee->task->name);
     945                        break;
     946                case IPC_PHONE_SLAMMED:
     947                        printf("slammed by %p", phone->callee);
     948                        break;
     949                case IPC_PHONE_HUNGUP:
     950                        printf("hung up by %p", phone->callee);
     951                        break;
     952                default:
     953                        break;
     954                }
     955               
     956                printf("\n");
     957        }
     958        mutex_unlock(&phone->lock);
     959
     960        return true;
     961}
     962
    887963/** List answerbox contents.
    888964 *
     
    894970        irq_spinlock_lock(&tasks_lock, true);
    895971        task_t *task = task_find_by_id(taskid);
    896        
    897972        if (!task) {
    898973                irq_spinlock_unlock(&tasks_lock, true);
    899974                return;
    900975        }
    901        
    902         /* Hand-over-hand locking */
    903         irq_spinlock_exchange(&tasks_lock, &task->lock);
    904        
    905         printf("[phone id] [calls] [state\n");
    906        
    907         size_t i;
    908         for (i = 0; i < IPC_MAX_PHONES; i++) {
    909                 if (SYNCH_FAILED(mutex_trylock(&task->phones[i].lock))) {
    910                         printf("%-10zu (mutex busy)\n", i);
    911                         continue;
    912                 }
    913                
    914                 if (task->phones[i].state != IPC_PHONE_FREE) {
    915                         printf("%-10zu %7" PRIun " ", i,
    916                             atomic_get(&task->phones[i].active_calls));
    917                        
    918                         switch (task->phones[i].state) {
    919                         case IPC_PHONE_CONNECTING:
    920                                 printf("connecting");
    921                                 break;
    922                         case IPC_PHONE_CONNECTED:
    923                                 printf("connected to %" PRIu64 " (%s)",
    924                                     task->phones[i].callee->task->taskid,
    925                                     task->phones[i].callee->task->name);
    926                                 break;
    927                         case IPC_PHONE_SLAMMED:
    928                                 printf("slammed by %p",
    929                                     task->phones[i].callee);
    930                                 break;
    931                         case IPC_PHONE_HUNGUP:
    932                                 printf("hung up by %p",
    933                                     task->phones[i].callee);
    934                                 break;
    935                         default:
    936                                 break;
    937                         }
    938                        
    939                         printf("\n");
    940                 }
    941                
    942                 mutex_unlock(&task->phones[i].lock);
    943         }
    944        
     976        task_hold(task);
     977        irq_spinlock_unlock(&tasks_lock, true);
     978       
     979        printf("[phone cap] [calls] [state\n");
     980       
     981        caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE,
     982            print_task_phone_cb, NULL);
     983       
     984        irq_spinlock_lock(&task->lock, true);
    945985        irq_spinlock_lock(&task->answerbox.lock, false);
    946986       
     
    9641004        irq_spinlock_unlock(&task->answerbox.lock, false);
    9651005        irq_spinlock_unlock(&task->lock, true);
     1006
     1007        task_release(task);
    9661008}
    9671009
  • kernel/generic/src/ipc/ipcrsc.c

    rd076f16 r91b60499  
    3939 *
    4040 * The pattern of usage of the resources is:
    41  * - allocate empty phone slot, connect | deallocate slot
     41 * - allocate empty phone capability slot, connect | deallocate slot
    4242 * - disconnect connected phone (some messages might be on the fly)
    4343 * - find phone in slot and send a message using phone
     
    5353 *   atomic on all platforms)
    5454 *
    55  * - To find an empty phone slot, the TASK must be locked
     55 * - To find an empty phone capability slot, the TASK must be locked
    5656 * - To answer a message, the answerbox must be locked
    5757 * - The locking of phone and answerbox is done at the ipc_ level.
     
    7777 *
    7878 * *** Connect_to_me ***
    79  * The caller sends IPC_M_CONNECT_TO_ME. 
     79 * The caller sends IPC_M_CONNECT_TO_ME.
    8080 * The server receives an automatically opened phoneid. If it accepts
    81  * (RETVAL=0), it can use the phoneid immediately.
    82  * Possible race condition can arise, when the client receives messages from new
    83  * connection before getting response for connect_to_me message. Userspace
    84  * should implement handshake protocol that would control it.
     81 * (RETVAL=0), it can use the phoneid immediately.  Possible race condition can
     82 * arise, when the client receives messages from new connection before getting
     83 * response for connect_to_me message. Userspace should implement handshake
     84 * protocol that would control it.
    8585 *
    8686 * Phone hangup
     
    8989 * - The phone is disconnected (no more messages can be sent over this phone),
    9090 *   all in-progress messages are correctly handled. The answerbox receives
    91  *   IPC_M_PHONE_HUNGUP call from the phone that hung up. When all async
    92  *   calls are answered, the phone is deallocated.
     91 *   IPC_M_PHONE_HUNGUP call from the phone that hung up. When all async calls
     92 *   are answered, the phone is deallocated.
    9393 *
    9494 * *** The answerbox hangs up (ipc_answer(EHANGUP))
    95  * - The phone is disconnected. EHANGUP response code is sent
    96  *   to the calling task. All new calls through this phone
    97  *   get a EHUNGUP error code, the task is expected to
    98  *   send an sys_ipc_hangup after cleaning up its internal structures.
     95 * - The phone is disconnected. EHANGUP response code is sent to the calling
     96 *   task. All new calls through this phone get a EHUNGUP error code, the task
     97 *   is expected to send an sys_ipc_hangup after cleaning up its internal
     98 *   structures.
     99 *
    99100 *
    100101 * Call forwarding
    101102 *
    102  * The call can be forwarded, so that the answer to call is passed directly
    103  * to the original sender. However, this poses special problems regarding
    104  * routing of hangup messages.
     103 * The call can be forwarded, so that the answer to call is passed directly to
     104 * the original sender. However, this poses special problems regarding routing
     105 * of hangup messages.
    105106 *
    106107 * sys_ipc_hangup -> IPC_M_PHONE_HUNGUP
     
    133134#include <assert.h>
    134135#include <abi/errno.h>
     136#include <cap/cap.h>
     137#include <mm/slab.h>
    135138
    136139/** Find call_t * in call table according to callid.
     
    138141 * @todo Some speedup (hash table?)
    139142 *
    140  * @param callid Userspace hash of the call. Currently it is the call
    141  *               structure kernel address.
    142  *
    143  * @return NULL on not found, otherwise pointer to the call
    144  *         structure.
     143 * @param callid Userspace hash of the call. Currently it is the call structure
     144 *               kernel address.
     145 *
     146 * @return NULL on not found, otherwise pointer to the call structure.
    145147 *
    146148 */
     
    162164}
    163165
    164 /** Get phone from the current task by ID.
    165  *
    166  * @param phoneid Phone ID.
    167  * @param phone   Place to store pointer to phone.
    168  *
    169  * @return EOK on success, EINVAL if ID is invalid.
    170  *
    171  */
    172 int phone_get(sysarg_t phoneid, phone_t **phone)
    173 {
    174         if (phoneid >= IPC_MAX_PHONES)
    175                 return EINVAL;
    176        
    177         *phone = &TASK->phones[phoneid];
    178         return EOK;
    179 }
    180 
    181 /** Allocate new phone slot in the specified task.
    182  *
    183  * @param task Task for which to allocate a new phone.
    184  *
    185  * @return New phone handle or -1 if the phone handle limit is
    186  *         exceeded.
    187  *
    188  */
    189 int phone_alloc(task_t *task)
    190 {
    191         irq_spinlock_lock(&task->lock, true);
    192        
    193         size_t i;
    194         for (i = 0; i < IPC_MAX_PHONES; i++) {
    195                 phone_t *phone = &task->phones[i];
    196 
    197                 if ((phone->state == IPC_PHONE_HUNGUP) &&
    198                     (atomic_get(&phone->active_calls) == 0))
    199                         phone->state = IPC_PHONE_FREE;
     166static bool phone_reclaim(kobject_t *kobj)
     167{
     168        bool gc = false;
     169
     170        mutex_lock(&kobj->phone->lock);
     171        if (kobj->phone->state == IPC_PHONE_HUNGUP &&
     172            atomic_get(&kobj->phone->active_calls) == 0)
     173                gc = true;
     174        mutex_unlock(&kobj->phone->lock);
     175
     176        return gc;
     177}
     178
     179static void phone_destroy(void *arg)
     180{
     181        phone_t *phone = (phone_t *) arg;
     182        slab_free(phone_slab, phone);
     183}
     184
     185static kobject_ops_t phone_kobject_ops = {
     186        .reclaim = phone_reclaim,
     187        .destroy = phone_destroy
     188};
     189
     190
     191/** Allocate new phone in the specified task.
     192 *
     193 * @param task  Task for which to allocate a new phone.
     194 *
     195 * @return  New phone capability handle.
     196 * @return  Negative error code if a new capability cannot be allocated.
     197 */
     198cap_handle_t phone_alloc(task_t *task)
     199{
     200        cap_handle_t handle = cap_alloc(task);
     201        if (handle >= 0) {
     202                phone_t *phone = slab_alloc(phone_slab, FRAME_ATOMIC);
     203                if (!phone) {
     204                        cap_free(TASK, handle);
     205                        return ENOMEM;
     206                }
     207                kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC);
     208                if (!kobject) {
     209                        cap_free(TASK, handle);
     210                        slab_free(phone_slab, phone);
     211                        return ENOMEM;
     212                }
     213
     214                ipc_phone_init(phone, task);
     215                phone->state = IPC_PHONE_CONNECTING;
     216
     217                kobject_initialize(kobject, KOBJECT_TYPE_PHONE, phone,
     218                    &phone_kobject_ops);
     219                phone->kobject = kobject;
    200220               
    201                 if (phone->state == IPC_PHONE_FREE) {
    202                         phone->state = IPC_PHONE_CONNECTING;
    203                         break;
    204                 }
     221                cap_publish(task, handle, kobject);
    205222        }
    206223       
    207         irq_spinlock_unlock(&task->lock, true);
    208        
    209         if (i == IPC_MAX_PHONES)
    210                 return -1;
    211        
    212         return i;
    213 }
    214 
    215 /** Mark a phone structure free.
    216  *
    217  * @param phone Phone structure to be marked free.
    218  *
    219  */
    220 static void phone_deallocp(phone_t *phone)
    221 {
    222         assert(phone->state == IPC_PHONE_CONNECTING);
    223        
    224         /* Atomic operation */
    225         phone->state = IPC_PHONE_FREE;
     224        return handle;
    226225}
    227226
     
    230229 * All already sent messages will be correctly processed.
    231230 *
    232  * @param phoneid Phone handle of the phone to be freed.
    233  *
    234  */
    235 void phone_dealloc(int phoneid)
    236 {
    237         phone_deallocp(&TASK->phones[phoneid]);
     231 * @param handle Phone capability handle of the phone to be freed.
     232 *
     233 */
     234void phone_dealloc(cap_handle_t handle)
     235{
     236        kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_PHONE);
     237        if (!kobj)
     238                return;
     239       
     240        assert(kobj->phone);
     241        assert(kobj->phone->state == IPC_PHONE_CONNECTING);
     242       
     243        kobject_put(kobj);
     244        cap_free(TASK, handle);
    238245}
    239246
    240247/** Connect phone to a given answerbox.
    241248 *
    242  * @param phoneid Phone handle to be connected.
    243  * @param box     Answerbox to which to connect the phone handle.
     249 * @param handle  Capability handle of the phone to be connected.
     250 * @param box     Answerbox to which to connect the phone.
    244251 * @return        True if the phone was connected, false otherwise.
    245  *
    246  * The procedure _enforces_ that the user first marks the phone
    247  * busy (e.g. via phone_alloc) and then connects the phone, otherwise
    248  * race condition may appear.
    249  *
    250  */
    251 bool phone_connect(int phoneid, answerbox_t *box)
    252 {
    253         phone_t *phone = &TASK->phones[phoneid];
    254        
    255         assert(phone->state == IPC_PHONE_CONNECTING);
    256         return ipc_phone_connect(phone, box);
     252 */
     253bool phone_connect(cap_handle_t handle, answerbox_t *box)
     254{
     255        kobject_t *phone_obj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     256        if (!phone_obj)
     257                return false;
     258       
     259        assert(phone_obj->phone->state == IPC_PHONE_CONNECTING);
     260       
     261        /* Hand over phone_obj reference to the answerbox */
     262        return ipc_phone_connect(phone_obj->phone, box);
    257263}
    258264
  • kernel/generic/src/ipc/irq.c

    rd076f16 r91b60499  
    3737 *
    3838 * This framework allows applications to subscribe to receive a notification
    39  * when interrupt is detected. The application may provide a simple 'top-half'
    40  * handler as part of its registration, which can perform simple operations
    41  * (read/write port/memory, add information to notification IPC message).
     39 * when an interrupt is detected. The application may provide a simple
     40 * 'top-half' handler as part of its registration, which can perform simple
     41 * operations (read/write port/memory, add information to notification IPC
     42 * message).
    4243 *
    4344 * The structure of a notification message is as follows:
     
    5051 * - in_phone_hash: interrupt counter (may be needed to assure correct order
    5152 *                  in multithreaded drivers)
    52  *
    53  * Note on synchronization for ipc_irq_subscribe(), ipc_irq_unsubscribe(),
    54  * ipc_irq_cleanup() and IRQ handlers:
    55  *
    56  *   By always taking all of the uspace IRQ hash table lock, IRQ structure lock
    57  *   and answerbox lock, we can rule out race conditions between the
    58  *   registration functions and also the cleanup function. Thus the observer can
    59  *   either see the IRQ structure present in both the hash table and the
    60  *   answerbox list or absent in both. Views in which the IRQ structure would be
    61  *   linked in the hash table but not in the answerbox list, or vice versa, are
    62  *   not possible.
    63  *
    64  *   By always taking the hash table lock and the IRQ structure lock, we can
    65  *   rule out a scenario in which we would free up an IRQ structure, which is
    66  *   still referenced by, for example, an IRQ handler. The locking scheme forces
    67  *   us to lock the IRQ structure only after any progressing IRQs on that
    68  *   structure are finished. Because we hold the hash table lock, we prevent new
    69  *   IRQs from taking new references to the IRQ structure.
    70  *
    7153 */
    7254
     
    8466#include <print.h>
    8567#include <macros.h>
     68#include <cap/cap.h>
    8669
    8770static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
     
    118101        }
    119102       
    120         /* Rewrite the pseudocode addresses from physical to kernel virtual. */
     103        /* Rewrite the IRQ code addresses from physical to kernel virtual. */
    121104        for (size_t i = 0; i < cmdcount; i++) {
    122105                uintptr_t addr;
     
    176159}
    177160
    178 /** Statically check the top-half pseudocode
    179  *
    180  * Check the top-half pseudocode for invalid or unsafe
    181  * constructs.
     161/** Statically check the top-half IRQ code
     162 *
     163 * Check the top-half IRQ code for invalid or unsafe constructs.
    182164 *
    183165 */
     
    216198}
    217199
    218 /** Free the top-half pseudocode.
    219  *
    220  * @param code Pointer to the top-half pseudocode.
     200/** Free the top-half IRQ code.
     201 *
     202 * @param code Pointer to the top-half IRQ code.
    221203 *
    222204 */
     
    231213}
    232214
    233 /** Copy the top-half pseudocode from userspace into the kernel.
    234  *
    235  * @param ucode Userspace address of the top-half pseudocode.
    236  *
    237  * @return Kernel address of the copied pseudocode.
     215/** Copy the top-half IRQ code from userspace into the kernel.
     216 *
     217 * @param ucode Userspace address of the top-half IRQ code.
     218 *
     219 * @return Kernel address of the copied IRQ code.
    238220 *
    239221 */
     
    289271}
    290272
     273static void irq_destroy(void *arg)
     274{
     275        irq_t *irq = (irq_t *) arg;
     276
     277        /* Free up the IRQ code and associated structures. */
     278        code_free(irq->notif_cfg.code);
     279        slab_free(irq_slab, irq);
     280}
     281
     282static kobject_ops_t irq_kobject_ops = {
     283        .destroy = irq_destroy
     284};
     285
    291286/** Subscribe an answerbox as a receiving end for IRQ notifications.
    292287 *
    293288 * @param box     Receiving answerbox.
    294289 * @param inr     IRQ number.
    295  * @param devno   Device number.
    296  * @param imethod Interface and method to be associated with the
    297  *                notification.
    298  * @param ucode   Uspace pointer to top-half pseudocode.
    299  *
    300  * @return EOK on success or a negative error code.
    301  *
    302  */
    303 int ipc_irq_subscribe(answerbox_t *box, inr_t inr, devno_t devno,
    304     sysarg_t imethod, irq_code_t *ucode)
     290 * @param imethod Interface and method to be associated with the notification.
     291 * @param ucode   Uspace pointer to top-half IRQ code.
     292 *
     293 * @return  IRQ capability handle.
     294 * @return  Negative error code.
     295 *
     296 */
     297int ipc_irq_subscribe(answerbox_t *box, inr_t inr, sysarg_t imethod,
     298    irq_code_t *ucode)
    305299{
    306300        sysarg_t key[] = {
    307                 (sysarg_t) inr,
    308                 (sysarg_t) devno
     301                [IRQ_HT_KEY_INR] = (sysarg_t) inr,
     302                [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM
    309303        };
    310304       
     
    321315       
    322316        /*
    323          * Allocate and populate the IRQ structure.
     317         * Allocate and populate the IRQ kernel object.
    324318         */
    325         irq_t *irq = malloc(sizeof(irq_t), 0);
     319        cap_handle_t handle = cap_alloc(TASK);
     320        if (handle < 0)
     321                return handle;
     322       
     323        irq_t *irq = (irq_t *) slab_alloc(irq_slab, FRAME_ATOMIC);
     324        if (!irq) {
     325                cap_free(TASK, handle);
     326                return ENOMEM;
     327        }
     328
     329        kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC);
     330        if (!kobject) {
     331                cap_free(TASK, handle);
     332                slab_free(irq_slab, irq);
     333                return ENOMEM;
     334        }
    326335       
    327336        irq_initialize(irq);
    328         irq->devno = devno;
    329337        irq->inr = inr;
    330338        irq->claim = ipc_irq_top_half_claim;
     
    337345       
    338346        /*
    339          * Enlist the IRQ structure in the uspace IRQ hash table and the
    340          * answerbox's list.
     347         * Insert the IRQ structure into the uspace IRQ hash table.
    341348         */
    342349        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    343        
    344         link_t *hlp = hash_table_find(&irq_uspace_hash_table, key);
    345         if (hlp) {
    346                 irq_t *hirq = hash_table_get_instance(hlp, irq_t, link);
    347                
    348                 /* hirq is locked */
    349                 irq_spinlock_unlock(&hirq->lock, false);
    350                 code_free(code);
    351                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    352                
    353                 free(irq);
    354                 return EEXIST;
    355         }
    356        
    357         /* Locking is not really necessary, but paranoid */
    358350        irq_spinlock_lock(&irq->lock, false);
    359         irq_spinlock_lock(&box->irq_lock, false);
    360        
     351       
     352        irq->notif_cfg.hashed_in = true;
    361353        hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
    362         list_append(&irq->notif_cfg.link, &box->irq_list);
    363        
    364         irq_spinlock_unlock(&box->irq_lock, false);
     354       
    365355        irq_spinlock_unlock(&irq->lock, false);
    366356        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     357
     358        kobject_initialize(kobject, KOBJECT_TYPE_IRQ, irq, &irq_kobject_ops);
     359        cap_publish(TASK, handle, kobject);
     360       
     361        return handle;
     362}
     363
     364/** Unsubscribe task from IRQ notification.
     365 *
     366 * @param box     Answerbox associated with the notification.
     367 * @param handle  IRQ capability handle.
     368 *
     369 * @return EOK on success or a negative error code.
     370 *
     371 */
     372int ipc_irq_unsubscribe(answerbox_t *box, int handle)
     373{
     374        kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_IRQ);
     375        if (!kobj)
     376                return ENOENT;
     377       
     378        assert(kobj->irq->notif_cfg.answerbox == box);
     379
     380        irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
     381        irq_spinlock_lock(&kobj->irq->lock, false);
     382       
     383        if (kobj->irq->notif_cfg.hashed_in) {
     384                /* Remove the IRQ from the uspace IRQ hash table. */
     385                hash_table_remove_item(&irq_uspace_hash_table,
     386                    &kobj->irq->link);
     387                kobj->irq->notif_cfg.hashed_in = false;
     388        }
     389
     390        /* kobj->irq->lock unlocked by the hash table remove_callback */
     391        irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
     392
     393        kobject_put(kobj);
     394        cap_free(TASK, handle);
    367395       
    368396        return EOK;
    369 }
    370 
    371 /** Unsubscribe task from IRQ notification.
    372  *
    373  * @param box   Answerbox associated with the notification.
    374  * @param inr   IRQ number.
    375  * @param devno Device number.
    376  *
    377  * @return EOK on success or a negative error code.
    378  *
    379  */
    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        
    390         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 */
    400         irq_spinlock_lock(&box->irq_lock, false);
    401        
    402         assert(irq->notif_cfg.answerbox == box);
    403        
    404         /* Remove the IRQ from the answerbox's list. */
    405         list_remove(&irq->notif_cfg.link);
    406        
    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        
    416         /* Remove the IRQ from the uspace IRQ hash table. */
    417         hash_table_remove(&irq_uspace_hash_table, key, 2);
    418        
    419         irq_spinlock_unlock(&box->irq_lock, false);
    420         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    421        
    422         /* Free up the pseudo code and associated structures. */
    423         code_free(irq->notif_cfg.code);
    424        
    425         /* Free up the IRQ structure. */
    426         free(irq);
    427        
    428         return EOK;
    429 }
    430 
    431 /** Disconnect all IRQ notifications from an answerbox.
    432  *
    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.
    436  *
    437  * @param box Answerbox for which we want to carry out the cleanup.
    438  *
    439  */
    440 void ipc_irq_cleanup(answerbox_t *box)
    441 {
    442 loop:
    443         irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    444         irq_spinlock_lock(&box->irq_lock, false);
    445        
    446         while (!list_empty(&box->irq_list)) {
    447                 DEADLOCK_PROBE_INIT(p_irqlock);
    448                
    449                 irq_t *irq = list_get_instance(list_first(&box->irq_list), irq_t,
    450                     notif_cfg.link);
    451                
    452                 if (!irq_spinlock_trylock(&irq->lock)) {
    453                         /*
    454                          * Avoid deadlock by trying again.
    455                          */
    456                         irq_spinlock_unlock(&box->irq_lock, false);
    457                         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    458                         DEADLOCK_PROBE(p_irqlock, DEADLOCK_THRESHOLD);
    459                         goto loop;
    460                 }
    461                
    462                 sysarg_t key[2];
    463                 key[0] = irq->inr;
    464                 key[1] = irq->devno;
    465                
    466                 assert(irq->notif_cfg.answerbox == box);
    467                
    468                 /* Unlist from the answerbox. */
    469                 list_remove(&irq->notif_cfg.link);
    470                
    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                
    480                 /* Remove from the hash table. */
    481                 hash_table_remove(&irq_uspace_hash_table, key, 2);
    482                
    483                 /*
    484                  * Release both locks so that we can free the pseudo code.
    485                  */
    486                 irq_spinlock_unlock(&box->irq_lock, false);
    487                 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    488                
    489                 code_free(irq->notif_cfg.code);
    490                 free(irq);
    491                
    492                 /* Reacquire both locks before taking another round. */
    493                 irq_spinlock_lock(&irq_uspace_hash_table_lock, true);
    494                 irq_spinlock_lock(&box->irq_lock, false);
    495         }
    496        
    497         irq_spinlock_unlock(&box->irq_lock, false);
    498         irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
    499397}
    500398
     
    516414}
    517415
    518 /** Apply the top-half pseudo code to find out whether to accept the IRQ or not.
     416/** Apply the top-half IRQ code to find out whether to accept the IRQ or not.
    519417 *
    520418 * @param irq IRQ structure.
    521419 *
    522  * @return IRQ_ACCEPT if the interrupt is accepted by the
    523  *         pseudocode, IRQ_DECLINE otherwise.
     420 * @return IRQ_ACCEPT if the interrupt is accepted by the IRQ code.
     421 * @return IRQ_DECLINE if the interrupt is not accepted byt the IRQ code.
    524422 *
    525423 */
  • kernel/generic/src/ipc/kbox.c

    rd076f16 r91b60499  
    206206 * cleanup code.
    207207 *
    208  * @return Phone id on success, or negative error code.
     208 * @return Phone capability handle on success, or negative error code.
    209209 *
    210210 */
     
    236236        }
    237237       
    238         int newphid = phone_alloc(TASK);
    239         if (newphid < 0) {
    240                 mutex_unlock(&task->kb.cleanup_lock);
    241                 return ELIMIT;
    242         }
    243        
     238        cap_handle_t phone_handle = phone_alloc(TASK);
     239        if (phone_handle < 0) {
     240                mutex_unlock(&task->kb.cleanup_lock);
     241                return phone_handle;
     242        }
     243       
     244        kobject_t *phone_obj = kobject_get(TASK, phone_handle,
     245            KOBJECT_TYPE_PHONE);
    244246        /* Connect the newly allocated phone to the kbox */
    245         (void) ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
     247        /* Hand over phone_obj's reference to ipc_phone_connect() */
     248        (void) ipc_phone_connect(phone_obj->phone, &task->kb.box);
    246249       
    247250        if (task->kb.thread != NULL) {
    248251                mutex_unlock(&task->kb.cleanup_lock);
    249                 return newphid;
     252                return phone_handle;
    250253        }
    251254       
     
    263266        mutex_unlock(&task->kb.cleanup_lock);
    264267       
    265         return newphid;
     268        return phone_handle;
    266269}
    267270
  • kernel/generic/src/ipc/ops/conctmeto.c

    rd076f16 r91b60499  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
    3  * Copyright (c) 2012 Jakub Jermar 
     3 * Copyright (c) 2012 Jakub Jermar
    44 * All rights reserved.
    55 *
     
    4242static int request_preprocess(call_t *call, phone_t *phone)
    4343{
    44         int newphid = phone_alloc(TASK);
     44        cap_handle_t phone_handle = phone_alloc(TASK);
    4545
    46         /* Remember the phoneid or the error. */
    47         call->priv = newphid;
    48         if (newphid < 0)
    49                 return ELIMIT;
    50                
     46        /* Remember the phone capability or the error. */
     47        call->priv = phone_handle;
     48        if (phone_handle < 0)
     49                return phone_handle;
     50
    5151        /* Set arg5 for server */
    52         IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
     52        kobject_t *phone_obj = kobject_get(TASK, phone_handle,
     53            KOBJECT_TYPE_PHONE);
     54        /* Hand over phone_obj's reference to ARG5 */
     55        IPC_SET_ARG5(call->data, (sysarg_t) phone_obj->phone);
    5356
    5457        return EOK;
     
    5760static int request_forget(call_t *call)
    5861{
    59         phone_dealloc(call->priv);
     62        cap_handle_t phone_handle = (cap_handle_t) call->priv;
     63        phone_dealloc(phone_handle);
     64        /* Hand over reference from ARG5 to phone->kobject */
     65        phone_t *phone = (phone_t *) IPC_GET_ARG5(call->data);
     66        /* Drop phone_obj's reference */
     67        kobject_put(phone->kobject);
    6068        return EOK;
    6169}
     
    6371static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    6472{
     73        /* Hand over reference from ARG5 to phone */
    6574        phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
    6675
    6776        /* If the user accepted call, connect */
    68         if (IPC_GET_RETVAL(answer->data) == EOK)
     77        if (IPC_GET_RETVAL(answer->data) == EOK) {
     78                /* Hand over reference from phone to the answerbox */
    6979                (void) ipc_phone_connect(phone, &TASK->answerbox);
     80        } else {
     81                kobject_put(phone->kobject);
     82        }
    7083
    7184        return EOK;
     
    7487static int answer_process(call_t *answer)
    7588{
    76         int newphid = (int) answer->priv;
     89        cap_handle_t phone_handle = (cap_handle_t) answer->priv;
    7790
    7891        if (IPC_GET_RETVAL(answer->data)) {
    79                 if (newphid >= 0) {
     92                if (phone_handle >= 0) {
    8093                        /*
    8194                         * The phone was indeed allocated and now needs
    8295                         * to be deallocated.
    8396                         */
    84                         phone_dealloc(newphid);
     97                        phone_dealloc(phone_handle);
    8598                }
    8699        } else {
    87                 IPC_SET_ARG5(answer->data, newphid);
     100                IPC_SET_ARG5(answer->data, phone_handle);
    88101        }
    89102       
  • kernel/generic/src/ipc/ops/concttome.c

    rd076f16 r91b60499  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
    3  * Copyright (c) 2012 Jakub Jermar 
     3 * Copyright (c) 2012 Jakub Jermar
    44 * All rights reserved.
    55 *
     
    4242static int request_process(call_t *call, answerbox_t *box)
    4343{
    44         int phoneid = phone_alloc(TASK);
     44        cap_handle_t phone_handle = phone_alloc(TASK);
    4545
    46         IPC_SET_ARG5(call->data, phoneid);
     46        IPC_SET_ARG5(call->data, phone_handle);
    4747       
    4848        return EOK;
     
    5151static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
    5252{
    53         int phoneid = (int) IPC_GET_ARG5(*olddata);
     53        cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata);
    5454
    55         if (phoneid >= 0)
    56                 phone_dealloc(phoneid);
     55        if (phone_handle >= 0)
     56                phone_dealloc(phone_handle);
    5757
    5858        return EOK;
     
    6161static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
    6262{
    63         int phoneid = (int) IPC_GET_ARG5(*olddata);
     63        cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata);
    6464
    6565        if (IPC_GET_RETVAL(answer->data) != EOK) {
    6666                /* The connection was not accepted */
    6767                answer_cleanup(answer, olddata);
    68         } else if (phoneid >= 0) {
     68        } else if (phone_handle >= 0) {
    6969                /* The connection was accepted */
    70                 if (phone_connect(phoneid, &answer->sender->answerbox)) {
    71                         /* Set 'phone hash' as arg5 of response */
     70                if (phone_connect(phone_handle, &answer->sender->answerbox)) {
     71                        /* Set 'phone hash' as ARG5 of response */
     72                        kobject_t *phone_obj = kobject_get(TASK, phone_handle,
     73                            KOBJECT_TYPE_PHONE);
    7274                        IPC_SET_ARG5(answer->data,
    73                             (sysarg_t) &TASK->phones[phoneid]);
     75                            (sysarg_t) phone_obj->phone);
     76                        kobject_put(phone_obj);
    7477                } else {
    7578                        /* The answerbox is shutting down. */
  • kernel/generic/src/ipc/ops/stchngath.c

    rd076f16 r91b60499  
    4343static int request_preprocess(call_t *call, phone_t *phone)
    4444{
    45         phone_t *sender_phone;
    4645        task_t *other_task_s;
    4746
    48         if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
     47        kobject_t *sender_obj = kobject_get(TASK, IPC_GET_ARG5(call->data),
     48            KOBJECT_TYPE_PHONE);
     49        if (!sender_obj)
    4950                return ENOENT;
    5051
    51         mutex_lock(&sender_phone->lock);
    52         if (sender_phone->state != IPC_PHONE_CONNECTED) {
    53                 mutex_unlock(&sender_phone->lock);
     52        mutex_lock(&sender_obj->phone->lock);
     53        if (sender_obj->phone->state != IPC_PHONE_CONNECTED) {
     54                mutex_unlock(&sender_obj->phone->lock);
     55                kobject_put(sender_obj);
    5456                return EINVAL;
    5557        }
    5658
    57         other_task_s = sender_phone->callee->task;
     59        other_task_s = sender_obj->phone->callee->task;
    5860
    59         mutex_unlock(&sender_phone->lock);
     61        mutex_unlock(&sender_obj->phone->lock);
    6062
    6163        /* Remember the third party task hash. */
    6264        IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
    6365
     66        kobject_put(sender_obj);
    6467        return EOK;
    6568}
     
    7174        if (!IPC_GET_RETVAL(answer->data)) {
    7275                /* The recipient authorized the change of state. */
    73                 phone_t *recipient_phone;
    7476                task_t *other_task_s;
    7577                task_t *other_task_r;
    7678
    77                 rc = phone_get(IPC_GET_ARG1(answer->data),
    78                     &recipient_phone);
    79                 if (rc != EOK) {
     79                kobject_t *recipient_obj = kobject_get(TASK,
     80                    IPC_GET_ARG1(answer->data), KOBJECT_TYPE_PHONE);
     81                if (!recipient_obj) {
    8082                        IPC_SET_RETVAL(answer->data, ENOENT);
    8183                        return ENOENT;
    8284                }
    8385
    84                 mutex_lock(&recipient_phone->lock);
    85                 if (recipient_phone->state != IPC_PHONE_CONNECTED) {
    86                         mutex_unlock(&recipient_phone->lock);
     86                mutex_lock(&recipient_obj->phone->lock);
     87                if (recipient_obj->phone->state != IPC_PHONE_CONNECTED) {
     88                        mutex_unlock(&recipient_obj->phone->lock);
    8789                        IPC_SET_RETVAL(answer->data, EINVAL);
     90                        kobject_put(recipient_obj);
    8891                        return EINVAL;
    8992                }
    9093
    91                 other_task_r = recipient_phone->callee->task;
     94                other_task_r = recipient_obj->phone->callee->task;
    9295                other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
    9396
     
    110113                }
    111114
    112                 mutex_unlock(&recipient_phone->lock);
     115                mutex_unlock(&recipient_obj->phone->lock);
     116                kobject_put(recipient_obj);
    113117        }
    114118
  • kernel/generic/src/ipc/sysipc.c

    rd076f16 r91b60499  
    8585{
    8686        switch (imethod) {
    87         case IPC_M_CONNECTION_CLONE:
    88         case IPC_M_CLONE_ESTABLISH:
    8987        case IPC_M_PHONE_HUNGUP:
    9088                /* This message is meant only for the original recipient. */
     
    135133{
    136134        switch (IPC_GET_IMETHOD(call->data)) {
    137         case IPC_M_CONNECTION_CLONE:
    138         case IPC_M_CLONE_ESTABLISH:
    139135        case IPC_M_CONNECT_TO_ME:
    140136        case IPC_M_CONNECT_ME_TO:
     
    264260/** Make a call over IPC and wait for reply.
    265261 *
    266  * @param phoneid     Phone handle for the call.
    267  * @param data[inout] Structure with request/reply data.
    268  * @param priv        Value to be stored in call->priv.
     262 * @param handle       Phone capability handle for the call.
     263 * @param data[inout]  Structure with request/reply data.
     264 * @param priv         Value to be stored in call->priv.
    269265 *
    270266 * @return EOK on success.
     
    272268 *
    273269 */
    274 int ipc_req_internal(int phoneid, ipc_data_t *data, sysarg_t priv)
    275 {
    276         phone_t *phone;
    277         if (phone_get(phoneid, &phone) != EOK)
     270int ipc_req_internal(cap_handle_t handle, ipc_data_t *data, sysarg_t priv)
     271{
     272        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     273        if (!kobj->phone)
    278274                return ENOENT;
    279275       
     
    282278        memcpy(call->data.args, data->args, sizeof(data->args));
    283279       
    284         int rc = request_preprocess(call, phone);
     280        int rc = request_preprocess(call, kobj->phone);
    285281        if (!rc) {
    286282#ifdef CONFIG_UDEBUG
     
    289285
    290286                ipc_call_hold(call);
    291                 rc = ipc_call_sync(phone, call);
     287                rc = ipc_call_sync(kobj->phone, call);
    292288                spinlock_lock(&call->forget_lock);
    293289                bool forgotten = call->forget;
     
    316312                                assert(rc == EINTR);
    317313                        }
    318                         return rc;     
     314                        kobject_put(kobj);
     315                        return rc;
    319316                }
    320317
     
    325322        memcpy(data->args, call->data.args, sizeof(data->args));
    326323        ipc_call_free(call);
     324        kobject_put(kobj);
    327325       
    328326        return EOK;
     
    350348 * the generic function sys_ipc_call_async_slow().
    351349 *
    352  * @param phoneid Phone handle for the call.
    353  * @param imethod Interface and method of the call.
    354  * @param arg1    Service-defined payload argument.
    355  * @param arg2    Service-defined payload argument.
    356  * @param arg3    Service-defined payload argument.
    357  * @param arg4    Service-defined payload argument.
     350 * @param handle   Phone capability handle for the call.
     351 * @param imethod  Interface and method of the call.
     352 * @param arg1     Service-defined payload argument.
     353 * @param arg2     Service-defined payload argument.
     354 * @param arg3     Service-defined payload argument.
     355 * @param arg4     Service-defined payload argument.
    358356 *
    359357 * @return Call hash on success.
     
    363361 *
    364362 */
    365 sysarg_t sys_ipc_call_async_fast(sysarg_t phoneid, sysarg_t imethod,
     363sysarg_t sys_ipc_call_async_fast(sysarg_t handle, sysarg_t imethod,
    366364    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
    367365{
    368         phone_t *phone;
    369         if (phone_get(phoneid, &phone) != EOK)
     366        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     367        if (!kobj)
    370368                return IPC_CALLRET_FATAL;
    371369       
    372         if (check_call_limit(phone))
     370        if (check_call_limit(kobj->phone)) {
     371                kobject_put(kobj);
    373372                return IPC_CALLRET_TEMPORARY;
     373        }
    374374       
    375375        call_t *call = ipc_call_alloc(0);
     
    386386        IPC_SET_ARG5(call->data, 0);
    387387       
    388         int res = request_preprocess(call, phone);
     388        int res = request_preprocess(call, kobj->phone);
    389389       
    390390        if (!res)
    391                 ipc_call(phone, call);
     391                ipc_call(kobj->phone, call);
    392392        else
    393                 ipc_backsend_err(phone, call, res);
    394        
     393                ipc_backsend_err(kobj->phone, call, res);
     394       
     395        kobject_put(kobj);
    395396        return (sysarg_t) call;
    396397}
     
    398399/** Make an asynchronous IPC call allowing to transmit the entire payload.
    399400 *
    400  * @param phoneid Phone handle for the call.
     401 * @param handle  Phone capability for the call.
    401402 * @param data    Userspace address of call data with the request.
    402403 *
     
    404405 *
    405406 */
    406 sysarg_t sys_ipc_call_async_slow(sysarg_t phoneid, ipc_data_t *data)
    407 {
    408         phone_t *phone;
    409         if (phone_get(phoneid, &phone) != EOK)
     407sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data)
     408{
     409        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     410        if (!kobj)
    410411                return IPC_CALLRET_FATAL;
    411412
    412         if (check_call_limit(phone))
     413        if (check_call_limit(kobj->phone)) {
     414                kobject_put(kobj);
    413415                return IPC_CALLRET_TEMPORARY;
     416        }
    414417
    415418        call_t *call = ipc_call_alloc(0);
     
    418421        if (rc != 0) {
    419422                ipc_call_free(call);
     423                kobject_put(kobj);
    420424                return (sysarg_t) rc;
    421425        }
    422426       
    423         int res = request_preprocess(call, phone);
     427        int res = request_preprocess(call, kobj->phone);
    424428       
    425429        if (!res)
    426                 ipc_call(phone, call);
     430                ipc_call(kobj->phone, call);
    427431        else
    428                 ipc_backsend_err(phone, call, res);
    429        
     432                ipc_backsend_err(kobj->phone, call, res);
     433       
     434        kobject_put(kobj);
    430435        return (sysarg_t) call;
    431436}
     
    435440 * Common code for both the fast and the slow version.
    436441 *
    437  * @param callid  Hash of the call to forward.
    438  * @param phoneid Phone handle to use for forwarding.
    439  * @param imethod New interface and method to use for the forwarded call.
    440  * @param arg1    New value of the first argument for the forwarded call.
    441  * @param arg2    New value of the second argument for the forwarded call.
    442  * @param arg3    New value of the third argument for the forwarded call.
    443  * @param arg4    New value of the fourth argument for the forwarded call.
    444  * @param arg5    New value of the fifth argument for the forwarded call.
    445  * @param mode    Flags that specify mode of the forward operation.
    446  * @param slow    If true, arg3, arg4 and arg5 are considered. Otherwise
    447  *                the function considers only the fast version arguments:
    448  *                i.e. arg1 and arg2.
     442 * @param callid   Hash of the call to forward.
     443 * @param handle   Phone capability to use for forwarding.
     444 * @param imethod  New interface and method to use for the forwarded call.
     445 * @param arg1     New value of the first argument for the forwarded call.
     446 * @param arg2     New value of the second argument for the forwarded call.
     447 * @param arg3     New value of the third argument for the forwarded call.
     448 * @param arg4     New value of the fourth argument for the forwarded call.
     449 * @param arg5     New value of the fifth argument for the forwarded call.
     450 * @param mode     Flags that specify mode of the forward operation.
     451 * @param slow     If true, arg3, arg4 and arg5 are considered. Otherwise
     452 *                 the function considers only the fast version arguments:
     453 *                 i.e. arg1 and arg2.
    449454 *
    450455 * @return 0 on succes, otherwise an error code.
     
    453458 *
    454459 */
    455 static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phoneid,
     460static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t handle,
    456461    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    457462    sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow)
     
    468473        bool after_forward = false;
    469474        int rc;
    470         phone_t *phone;
    471        
    472         if (phone_get(phoneid, &phone) != EOK) {
     475
     476        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     477        if (!kobj) {
    473478                rc = ENOENT;
    474479                goto error;
     
    516521        }
    517522       
    518         rc = ipc_forward(call, phone, &TASK->answerbox, mode);
     523        rc = ipc_forward(call, kobj->phone, &TASK->answerbox, mode);
    519524        if (rc != EOK) {
    520525                after_forward = true;
     
    522527        }
    523528
     529        kobject_put(kobj);
    524530        return EOK;
    525531
     
    532538                ipc_answer(&TASK->answerbox, call);
    533539
     540        if (kobj)
     541                kobject_put(kobj);
    534542        return rc;
    535543}
     
    544552 * arguments are not set and these values are ignored.
    545553 *
    546  * @param callid  Hash of the call to forward.
    547  * @param phoneid Phone handle to use for forwarding.
    548  * @param imethod New interface and method to use for the forwarded call.
    549  * @param arg1    New value of the first argument for the forwarded call.
    550  * @param arg2    New value of the second argument for the forwarded call.
    551  * @param mode    Flags that specify mode of the forward operation.
     554 * @param callid   Hash of the call to forward.
     555 * @param handle  Phone handle to use for forwarding.
     556 * @param imethod  New interface and method to use for the forwarded call.
     557 * @param arg1     New value of the first argument for the forwarded call.
     558 * @param arg2     New value of the second argument for the forwarded call.
     559 * @param mode     Flags that specify mode of the forward operation.
    552560 *
    553561 * @return 0 on succes, otherwise an error code.
    554562 *
    555563 */
    556 sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t phoneid,
     564sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t handle,
    557565    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    558566{
    559         return sys_ipc_forward_common(callid, phoneid, imethod, arg1, arg2, 0, 0,
     567        return sys_ipc_forward_common(callid, handle, imethod, arg1, arg2, 0, 0,
    560568            0, mode, false);
    561569}
     
    571579 *
    572580 * @param callid  Hash of the call to forward.
    573  * @param phoneid Phone handle to use for forwarding.
     581 * @param handle Phone handle to use for forwarding.
    574582 * @param data    Userspace address of the new IPC data.
    575583 * @param mode    Flags that specify mode of the forward operation.
     
    578586 *
    579587 */
    580 sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid,
     588sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t handle,
    581589    ipc_data_t *data, unsigned int mode)
    582590{
     
    587595                return (sysarg_t) rc;
    588596       
    589         return sys_ipc_forward_common(callid, phoneid,
     597        return sys_ipc_forward_common(callid, handle,
    590598            IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata),
    591599            IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata),
     
    685693/** Hang up a phone.
    686694 *
    687  * @param Phone handle of the phone to be hung up.
     695 * @param handle  Phone capability handle of the phone to be hung up.
    688696 *
    689697 * @return 0 on success or an error code.
    690698 *
    691699 */
    692 sysarg_t sys_ipc_hangup(sysarg_t phoneid)
    693 {
    694         phone_t *phone;
    695        
    696         if (phone_get(phoneid, &phone) != EOK)
     700sysarg_t sys_ipc_hangup(sysarg_t handle)
     701{
     702        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     703        if (!kobj)
    697704                return ENOENT;
    698705       
    699         if (ipc_phone_hangup(phone))
     706        if (ipc_phone_hangup(kobj->phone)) {
     707                kobject_put(kobj);
    700708                return -1;
    701        
     709        }
     710       
     711        kobject_put(kobj);
    702712        return 0;
    703713}
     
    802812 *
    803813 * @param inr     IRQ number.
    804  * @param devno   Device number.
    805814 * @param imethod Interface and method to be associated with the notification.
    806815 * @param ucode   Uspace pointer to the top-half pseudocode.
    807816 *
    808  * @return EPERM or a return code returned by ipc_irq_subscribe().
    809  *
    810  */
    811 sysarg_t sys_ipc_irq_subscribe(inr_t inr, devno_t devno, sysarg_t imethod,
    812     irq_code_t *ucode)
     817 * @return IRQ kernel object capability
     818 * @return EPERM
     819 * @return Error code returned by ipc_irq_subscribe().
     820 *
     821 */
     822sysarg_t sys_ipc_irq_subscribe(inr_t inr, sysarg_t imethod, irq_code_t *ucode)
    813823{
    814824        if (!(perm_get(TASK) & PERM_IRQ_REG))
    815825                return EPERM;
    816826       
    817         return ipc_irq_subscribe(&TASK->answerbox, inr, devno, imethod, ucode);
     827        return ipc_irq_subscribe(&TASK->answerbox, inr, imethod, ucode);
    818828}
    819829
     
    826836 *
    827837 */
    828 sysarg_t sys_ipc_irq_unsubscribe(inr_t inr, devno_t devno)
     838sysarg_t sys_ipc_irq_unsubscribe(sysarg_t cap)
    829839{
    830840        if (!(perm_get(TASK) & PERM_IRQ_REG))
    831841                return EPERM;
    832842       
    833         ipc_irq_unsubscribe(&TASK->answerbox, inr, devno);
     843        ipc_irq_unsubscribe(&TASK->answerbox, cap);
    834844       
    835845        return 0;
  • kernel/generic/src/ipc/sysipc_ops.c

    rd076f16 r91b60499  
    3838
    3939/* Forward declarations. */
    40 sysipc_ops_t ipc_m_connection_clone_ops;
    41 sysipc_ops_t ipc_m_clone_establish_ops;
    4240sysipc_ops_t ipc_m_connect_to_me_ops;
    4341sysipc_ops_t ipc_m_connect_me_to_ops;
     
    5149
    5250static sysipc_ops_t *sysipc_ops[] = {
    53         [IPC_M_CONNECTION_CLONE] = &ipc_m_connection_clone_ops,
    54         [IPC_M_CLONE_ESTABLISH] = &ipc_m_clone_establish_ops,
    5551        [IPC_M_CONNECT_TO_ME] = &ipc_m_connect_to_me_ops,
    5652        [IPC_M_CONNECT_ME_TO] = &ipc_m_connect_me_to_ops,
  • kernel/generic/src/proc/task.c

    rd076f16 r91b60499  
    5050#include <adt/btree.h>
    5151#include <adt/list.h>
     52#include <cap/cap.h>
    5253#include <ipc/ipc.h>
    5354#include <ipc/ipcrsc.h>
     
    8384static void task_kill_internal(task_t *);
    8485static int tsk_constructor(void *, unsigned int);
     86static size_t tsk_destructor(void *obj);
    8587
    8688/** Initialize kernel tasks support.
     
    9294        avltree_create(&tasks_tree);
    9395        task_slab = slab_cache_create("task_t", sizeof(task_t), 0,
    94             tsk_constructor, NULL, 0);
     96            tsk_constructor, tsk_destructor, 0);
    9597}
    9698
     
    167169        list_initialize(&task->threads);
    168170       
     171        caps_task_alloc(task);
     172       
    169173        ipc_answerbox_init(&task->answerbox, task);
    170174       
    171         size_t i;
    172         for (i = 0; i < IPC_MAX_PHONES; i++)
    173                 ipc_phone_init(&task->phones[i], task);
    174 
    175175        spinlock_initialize(&task->active_calls_lock, "active_calls_lock");
    176176        list_initialize(&task->active_calls);
     
    186186}
    187187
     188size_t tsk_destructor(void *obj)
     189{
     190        task_t *task = (task_t *) obj;
     191       
     192        caps_task_free(task);
     193        return 0;
     194}
     195
    188196/** Create new task with no threads.
    189197 *
     
    206214        task->ucycles = 0;
    207215        task->kcycles = 0;
     216
     217        caps_task_init(task);
    208218
    209219        task->ipc_info.call_sent = 0;
     
    228238       
    229239        if ((ipc_phone_0) &&
    230             (container_check(ipc_phone_0->task->container, task->container)))
    231                 (void) ipc_phone_connect(&task->phones[0], ipc_phone_0);
     240            (container_check(ipc_phone_0->task->container, task->container))) {
     241                cap_handle_t phone_handle = phone_alloc(task);
     242                kobject_t *phone_obj = kobject_get(task, phone_handle,
     243                    KOBJECT_TYPE_PHONE);
     244                (void) ipc_phone_connect(phone_obj->phone, ipc_phone_0);
     245        }
    232246       
    233247        futex_task_init(task);
     
    603617        if (*additional)
    604618                printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c "
    605                     "%9" PRIua, task->taskid, ucycles, usuffix, kcycles,
     619                    "%9" PRIua "\n", task->taskid, ucycles, usuffix, kcycles,
    606620                    ksuffix, atomic_get(&task->refcount));
    607621        else
     
    609623                    task->taskid, task->name, task->container, task, task->as);
    610624#endif
    611        
    612         if (*additional) {
    613                 size_t i;
    614                 for (i = 0; i < IPC_MAX_PHONES; i++) {
    615                         if (task->phones[i].callee)
    616                                 printf(" %zu:%p", i, task->phones[i].callee);
    617                 }
    618                 printf("\n");
    619         }
    620625       
    621626        irq_spinlock_unlock(&task->lock, false);
  • kernel/generic/src/proc/thread.c

    rd076f16 r91b60499  
    228228#endif
    229229       
    230         return 1;  /* One page freed */
     230        return STACK_FRAMES;  /* number of frames freed */
    231231}
    232232
  • kernel/generic/src/syscall/syscall.c

    rd076f16 r91b60499  
    4545#include <arch.h>
    4646#include <debug.h>
    47 #include <ddi/device.h>
    4847#include <interrupt.h>
    4948#include <ipc/sysipc.h>
     
    175174       
    176175        /* DDI related syscalls. */
    177         [SYS_DEVICE_ASSIGN_DEVNO] = (syshandler_t) sys_device_assign_devno,
    178176        [SYS_PHYSMEM_MAP] = (syshandler_t) sys_physmem_map,
    179177        [SYS_PHYSMEM_UNMAP] = (syshandler_t) sys_physmem_unmap,
  • kernel/generic/src/sysinfo/sysinfo.c

    rd076f16 r91b60499  
    700700       
    701701        sysinfo_return_t ret;
     702        ret.tag = SYSINFO_VAL_UNDEFINED;
    702703       
    703704        if (subtree != NULL) {
     
    730731                        ret.data.size = size;
    731732                }
    732         } else {
    733                 /* No item in the fixed sysinfo tree */
    734                 ret.tag = SYSINFO_VAL_UNDEFINED;
    735733        }
    736734       
Note: See TracChangeset for help on using the changeset viewer.