Changeset eb3d379 in mainline


Ignore:
Timestamp:
2006-06-04T15:58:01Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8adafa0
Parents:
7669bcf
Message:

Slightly remodelled ipc hangups to facilitate correct cleanup.
Doc updates for frame allocator.

Location:
generic
Files:
6 edited

Legend:

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

    r7669bcf reb3d379  
    179179
    180180typedef enum {
    181         IPC_BUSY_FREE = 0,
    182         IPC_BUSY_CONNECTING,
    183         IPC_BUSY_CONNECTED
    184 } ipc_busy_t;
     181        IPC_PHONE_FREE = 0,     /**< Phone is free and can be allocated */
     182        IPC_PHONE_CONNECTING,   /**< Phone is connecting somewhere */
     183        IPC_PHONE_CONNECTED,    /**< Phone is connected */
     184        IPC_PHONE_HUNGUP,  /**< Phone is hung up, waiting for answers to come */
     185        IPC_PHONE_SLAMMED       /**< Phone was hungup from server */
     186} ipc_phone_state_t;
    185187
    186188struct phone_s {
     
    188190        link_t list;
    189191        answerbox_t *callee;
    190         ipc_busy_t busy;
     192        ipc_phone_state_t state;
    191193        atomic_t active_calls;
    192194};
     
    223225extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox);
    224226extern void ipc_cleanup(task_t *task);
    225 extern int ipc_phone_hangup(phone_t *phone);
     227extern int ipc_phone_hangup(phone_t *phone, int aggressive);
    226228extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err);
    227229
  • generic/include/proc/task.h

    r7669bcf reb3d379  
    5252        answerbox_t answerbox;  /**< Communication endpoint */
    5353        phone_t phones[IPC_MAX_PHONES];
    54         atomic_t active_calls;  /**< Active asynchronous messages */
     54        atomic_t active_calls;  /**< Active asynchronous messages.
     55                                 *   It is used for limiting uspace to
     56                                 *   certain extent. */
    5557       
    5658        task_arch_t arch;       /**< Architecture specific task data. */
  • generic/src/ipc/ipc.c

    r7669bcf reb3d379  
    112112
    113113        ASSERT(!phone->callee);
    114         phone->busy = IPC_BUSY_CONNECTED;
     114        phone->state = IPC_PHONE_CONNECTED;
    115115        phone->callee = box;
    116116
     
    128128        spinlock_initialize(&phone->lock, "phone_lock");
    129129        phone->callee = NULL;
    130         phone->busy = IPC_BUSY_FREE;
     130        phone->state = IPC_PHONE_FREE;
    131131        atomic_set(&phone->active_calls, 0);
    132132}
     
    185185        call->data.phone = phone;
    186186        atomic_inc(&phone->active_calls);
    187         if (phone->busy == IPC_BUSY_CONNECTED)
    188                 IPC_SET_RETVAL(call->data, EHANGUP);
    189         else
    190                 IPC_SET_RETVAL(call->data, ENOENT);
    191 
     187        IPC_SET_RETVAL(call->data, err);
    192188        _ipc_answer_free_call(call);
    193189}
     
    217213
    218214        spinlock_lock(&phone->lock);
    219 
    220         box = phone->callee;
    221         if (!box) {
    222                 /* Trying to send over disconnected phone */
     215        if (phone->state != IPC_PHONE_CONNECTED) {
    223216                spinlock_unlock(&phone->lock);
    224217                if (call->flags & IPC_CALL_FORWARDED) {
    225218                        IPC_SET_RETVAL(call->data, EFORWARD);
    226219                        _ipc_answer_free_call(call);
    227                 } else { /* Simulate sending back a message */
    228                         if (phone->busy == IPC_BUSY_CONNECTED)
     220                } else {
     221                        if (phone->state == IPC_PHONE_HUNGUP)
    229222                                ipc_backsend_err(phone, call, EHANGUP);
    230223                        else
    231224                                ipc_backsend_err(phone, call, ENOENT);
    232225                }
    233 
    234226                return ENOENT;
    235227        }
     228        box = phone->callee;
    236229        _ipc_call(phone, box, call);
    237230       
     
    242235/** Disconnect phone from answerbox
    243236 *
    244  * It is allowed to call disconnect on already disconnected phone
    245  *
     237 * This call leaves the phone in HUNGUP state. The change to 'free' is done
     238 * lazily later.
     239 *
     240 * @param phone Phone to be hung up
     241 * @param aggressive If false, the phone is only marked hungup, and all
     242 *              messages are allowed to complete.
     243 *              If true, all messages in all queues are discarded. There
     244 *              may still be some messages that will be 'in-transit' on
     245 *              other CPU.
     246 *             
    246247 * @return 0 - phone disconnected, -1 - the phone was already disconnected
    247248 */
    248 int ipc_phone_hangup(phone_t *phone)
     249int ipc_phone_hangup(phone_t *phone, int aggressive)
    249250{
    250251        answerbox_t *box;
     
    252253       
    253254        spinlock_lock(&phone->lock);
     255        if (phone->state == IPC_PHONE_FREE || phone->state ==IPC_PHONE_HUNGUP \
     256            || phone->state == IPC_PHONE_CONNECTING) {
     257                spinlock_unlock(&phone->lock);
     258                return -1;
     259        }
    254260        box = phone->callee;
    255         if (!box) {
    256                 if (phone->busy == IPC_BUSY_CONNECTING) {
    257                         spinlock_unlock(&phone->lock);
    258                         return -1;
     261        if (phone->state != IPC_PHONE_SLAMMED) {
     262                /* Remove myself from answerbox */
     263                spinlock_lock(&box->lock);
     264                list_remove(&phone->list);
     265                spinlock_unlock(&box->lock);
     266
     267                if (phone->state != IPC_PHONE_SLAMMED) {
     268                        call = ipc_call_alloc(0);
     269                        IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
     270                        call->flags |= IPC_CALL_DISCARD_ANSWER;
     271                        _ipc_call(phone, box, call);
    259272                }
    260                 /* Already disconnected phone */
    261                 phone->busy = IPC_BUSY_FREE;
    262                 spinlock_unlock(&phone->lock);
    263                 return 0;
    264         }
    265 
    266         spinlock_lock(&box->lock);
    267         list_remove(&phone->list);
    268         phone->callee = NULL;
    269         spinlock_unlock(&box->lock);
    270 
    271         call = ipc_call_alloc(0);
    272         IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
    273         call->flags |= IPC_CALL_DISCARD_ANSWER;
    274         _ipc_call(phone, box, call);
    275 
    276         phone->busy = IPC_BUSY_FREE;
    277 
     273        }
     274
     275        if (aggressive && atomic_get(&phone->active_calls) > 0) {
     276                /* TODO: Do some stuff be VERY aggressive */
     277        }
     278
     279        phone->callee = 0;
     280       
     281        phone->state = IPC_PHONE_HUNGUP;
    278282        spinlock_unlock(&phone->lock);
    279283
     
    381385        /* Disconnect all our phones ('ipc_phone_hangup') */
    382386        for (i=0;i < IPC_MAX_PHONES; i++)
    383                 ipc_phone_hangup(&task->phones[i]);
     387                ipc_phone_hangup(&task->phones[i], 1);
    384388
    385389        /* Disconnect all connected irqs */
     
    399403               
    400404                /* Disconnect phone */
    401                 phone->callee = NULL;
     405                ASSERT(phone->state == IPC_PHONE_CONNECTED);
     406                phone->state = IPC_PHONE_SLAMMED;
    402407                list_remove(&phone->list);
    403408
     
    412417       
    413418        /* Wait for all async answers to arrive */
    414         while (atomic_get(&task->active_calls)) {
     419        while (1) {
     420                /* Go through all phones, until all are FREE... */
     421                /* Locking not needed, no one else should modify
     422                 * it, when we are in cleanup */
     423                for (i=0;i < IPC_MAX_PHONES; i++) {
     424                        if (task->phones[i].state == IPC_PHONE_HUNGUP && \
     425                            atomic_get(&task->phones[i].active_calls) == 0)
     426                                task->phones[i].state = IPC_PHONE_FREE;
     427                        if (task->phones[i].state != IPC_PHONE_FREE)
     428                                break;
     429                }
     430                /* Voila, got into cleanup */
     431                if (i == IPC_MAX_PHONES)
     432                        break;
     433               
    415434                call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
    416435                ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF));
  • generic/src/ipc/ipcrsc.c

    r7669bcf reb3d379  
    159159       
    160160        for (i=0; i < IPC_MAX_PHONES; i++) {
    161                 if (TASK->phones[i].busy==IPC_BUSY_FREE && !atomic_get(&TASK->phones[i].active_calls)) {
    162                         TASK->phones[i].busy = IPC_BUSY_CONNECTING;
     161                if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \
     162                    atomic_get(&TASK->phones[i].active_calls) == 0)
     163                        TASK->phones[i].state = IPC_PHONE_FREE;
     164
     165                if (TASK->phones[i].state == IPC_PHONE_FREE) {
     166                        TASK->phones[i].state = IPC_PHONE_CONNECTING;
    163167                        break;
    164168                }
     
    173177static void phone_deallocp(phone_t *phone)
    174178{
    175         ASSERT(phone->busy == IPC_BUSY_CONNECTING);
     179        ASSERT(phone->state == IPC_PHONE_CONNECTING);
    176180        ASSERT(! phone->callee);
    177181       
    178182        /* atomic operation */
    179         phone->busy = IPC_BUSY_FREE;
     183        phone->state = IPC_PHONE_FREE;
    180184}
    181185
     
    201205        phone_t *phone = &TASK->phones[phoneid];
    202206       
    203         ASSERT(phone->busy == IPC_BUSY_CONNECTING);
     207        ASSERT(phone->state == IPC_PHONE_CONNECTING);
    204208        ipc_phone_connect(phone, box);
    205209}
  • generic/src/ipc/sysipc.c

    r7669bcf reb3d379  
    106106                spinlock_lock(&answer->data.phone->lock);
    107107                spinlock_lock(&TASK->answerbox.lock);
    108                 if (answer->data.phone->callee) {
     108                if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
    109109                        list_remove(&answer->data.phone->list);
    110                         answer->data.phone->callee = 0;
     110                        answer->data.phone->state = IPC_PHONE_SLAMMED;
    111111                }
    112112                spinlock_unlock(&TASK->answerbox.lock);
     
    493493        GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    494494
    495         if (ipc_phone_hangup(phone))
     495        if (ipc_phone_hangup(phone, 0))
    496496                return -1;
    497497
  • generic/src/mm/frame.c

    r7669bcf reb3d379  
    135135 * Insert-sort zone into zones list
    136136 *
     137 * @param newzone New zone to be inserted into zone list
    137138 * @return zone number on success, -1 on error
    138139 */
     
    173174 * Try to find a zone where can we find the frame
    174175 *
    175  * @param hint Start searching in zone 'hint'
    176  * @param lock Lock zone if true
     176 * @param frame Frame number contained in zone
     177 * @param pzone If not null, it is used as zone hint. Zone index
     178 *              is filled into the variable on success.
     179 * @return Pointer to LOCKED zone containing frame
    177180 *
    178181 * Assume interrupts disable
     
    221224 * Assume interrupts are disabled!!
    222225 *
     226 * @param order Size (2^order) of free space we are trying to find
    223227 * @param pzone Pointer to preferred zone or NULL, on return contains zone number
    224228 */
     
    469473 *
    470474 * Assume zone is locked
     475 *
     476 * @param zone Pointer to zone from which the frame is to be freed
     477 * @param frame_idx Frame index relative to zone
    471478 */
    472479static void zone_frame_free(zone_t *zone, index_t frame_idx)
     
    519526 *
    520527 * Assume z1 & z2 are locked
     528 *
     529 * @param z Target zone structure pointer
     530 * @param z1 Zone to merge
     531 * @param z2 Zone to merge
    521532 */
    522533
     
    628639 *
    629640 * The allocated block need 2^order frames of space. Reduce all frames
    630  * in block to order 0 and free the unneded frames. This means, that
    631  * when freeing the block, you have to free every frame from block.
     641 * in block to order 0 and free the unneeded frames. This means, that
     642 * when freeing the previously allocated block starting with frame_idx,
     643 * you have to free every frame.
    632644 *
    633645 * @param zone
     
    752764 *
    753765 * @param start Physical address of the first frame within the zone.
    754  * @param size Size of the zone. Must be a multiple of FRAME_SIZE.
    755  * @param conffram Address of configuration frame
     766 * @param count Count of frames in zone
     767 * @param z Address of configuration information of zone
    756768 * @param flags Zone flags.
    757769 *
     
    794806}
    795807
    796 /** Compute configuration data size for zone */
     808/** Compute configuration data size for zone
     809 *
     810 * @param count Size of zone in frames
     811 * @return Size of zone configuration info (in bytes)
     812 */
    797813__address zone_conf_size(count_t count)
    798814{
     
    807823/** Create and add zone to system
    808824 *
    809  * @param confframe Where configuration frame is supposed to be.
    810  *                  Always check, that we will not disturb the kernel and possibly init.
     825 * @param start First frame number (absolute)
     826 * @param count Size of zone in frames
     827 * @param confframe Where configuration frames are supposed to be.
     828 *                  Automatically checks, that we will not disturb the
     829 *                  kernel and possibly init.
    811830 *                  If confframe is given _outside_ this zone, it is expected,
    812831 *                  that the area is already marked BUSY and big enough
    813  *                  to contain zone_conf_size() amount of data
     832 *                  to contain zone_conf_size() amount of data.
     833 *                  If the confframe is inside the area, the zone free frame
     834 *                  information is modified not to include it.
    814835 *
    815836 * @return Zone number or -1 on error
Note: See TracChangeset for help on using the changeset viewer.