Changeset 20282ef3 in mainline


Ignore:
Timestamp:
2012-08-26T13:36:41Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
53af6e8c
Parents:
b1e6269
Message:

When answer_preprocess() wins the race for a call, let it also dequeue
the call from the sender's active list so that we have a real atomic
either-answered-or-forgotten behavior.

This change avoids the possibility that the race is won in
answer_preprocess(), but lost later in _ipc_answer_free_call(), which
would have the effect of skipping some of the necessary call_t cleanup.

Location:
kernel/generic
Files:
3 edited

Legend:

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

    rb1e6269 r20282ef3  
    131131         */
    132132        bool forget;
     133
     134        /** True if the call is in the active list. */
     135        bool active;
    133136       
    134137        /**
  • kernel/generic/src/ipc/ipc.c

    rb1e6269 r20282ef3  
    7373        memsetb(call, sizeof(*call), 0);
    7474        spinlock_initialize(&call->forget_lock, "forget_lock");
     75        call->active = false;
    7576        call->forget = false;
    7677        call->sender = TASK;
     
    201202
    202203                /*
    203                  * Remove the call from the sender's active call list.
    204                  * We enforce this locking order so that any potential
    205                  * concurrently executing forget operation is forced to
    206                  * release its active_calls_lock and lose the race to
    207                  * forget this soon to be answered call.
     204                 * If the call is still active, i.e. it was answered
     205                 * in a non-standard way, remove the call from the
     206                 * sender's active call list.
    208207                 */
    209                 spinlock_lock(&call->sender->active_calls_lock);
    210                 list_remove(&call->ta_link);
    211                 spinlock_unlock(&call->sender->active_calls_lock);
     208                if (call->active) {
     209                        spinlock_lock(&call->sender->active_calls_lock);
     210                        list_remove(&call->ta_link);
     211                        spinlock_unlock(&call->sender->active_calls_lock);
     212                }
    212213        }
    213214        spinlock_unlock(&call->forget_lock);
     
    291292        if (!(call->flags & IPC_CALL_FORWARDED)) {
    292293                atomic_inc(&phone->active_calls);
     294
     295                call->active = true;
    293296
    294297                spinlock_lock(&TASK->active_calls_lock);
     
    594597        if (!spinlock_trylock(&call->forget_lock)) {
    595598                /*
    596                  * Avoid deadlock and let _ipc_answer_free_call() win the race
    597                  * to answer the first call on the list.
     599                 * Avoid deadlock and let async_answer() or
     600                 *  _ipc_answer_free_call() win the race to dequeue the first
     601                 * call on the list.
    598602                 */
    599603                spinlock_unlock(&TASK->active_calls_lock);     
  • kernel/generic/src/ipc/sysipc.c

    rb1e6269 r20282ef3  
    175175                return rc;
    176176        } else {
     177                ASSERT(answer->active);
     178
     179                /*
     180                 * Mark the call as inactive to prevent _ipc_answer_free_call()
     181                 * from attempting to remove the call from the active list
     182                 * itself.
     183                 */
     184                answer->active = false;
     185
     186                /*
     187                 * Remove the call from the sender's active call list.
     188                 * We enforce this locking order so that any potential
     189                 * concurrently executing forget operation is forced to
     190                 * release its active_calls_lock and lose the race to
     191                 * forget this soon to be answered call.
     192                 */
     193                spinlock_lock(&answer->sender->active_calls_lock);
     194                list_remove(&answer->ta_link);
     195                spinlock_unlock(&answer->sender->active_calls_lock);
     196
    177197                /*
    178198                 * Hold the sender task so that it cannot suddenly disappear
Note: See TracChangeset for help on using the changeset viewer.