Changeset 203f4c3 in mainline


Ignore:
Timestamp:
2006-04-09T14:14:49Z (19 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
016acbe
Parents:
fe04594
Message:

Sleeping in a wait queue can be now interrupted with
waitq_interrupt_sleep().

Location:
generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • generic/include/proc/thread.h

    rfe04594 r203f4c3  
    8181        void *thread_arg;                       /**< Argument passed to thread_code() function. */
    8282
    83         context_t saved_context;                /**< From here, the stored context is restored when the thread is scheduled. */
    84         context_t sleep_timeout_context;        /**< From here, the stored failover context is restored when sleep times out. */
     83        /** From here, the stored context is restored when the thread is scheduled. */
     84        context_t saved_context;
     85        /** From here, the stored timeout context is restored when sleep times out. */
     86        context_t sleep_timeout_context;
     87        /** From here, the stored interruption context is restored when sleep is interrupted. */
     88        context_t sleep_interruption_context;
    8589
    8690        waitq_t *sleep_queue;                   /**< Wait queue in which this thread sleeps. */
  • generic/include/synch/synch.h

    rfe04594 r203f4c3  
    3636#define ESYNCH_WOULD_BLOCK      1       /**< Could not satisfy the request without going to sleep. */
    3737#define ESYNCH_TIMEOUT          2       /**< Timeout occurred. */
    38 #define ESYNCH_OK_ATOMIC        4       /**< Operation succeeded without sleeping. */
    39 #define ESYNCH_OK_BLOCKED       8       /**< Operation succeeded and did sleep. */
     38#define ESYNCH_INTERRUPTED      4       /**< Sleep was interrupted. */
     39#define ESYNCH_OK_ATOMIC        8       /**< Operation succeeded without sleeping. */
     40#define ESYNCH_OK_BLOCKED       16      /**< Operation succeeded and did sleep. */
    4041
    41 #define SYNCH_FAILED(rc)        ((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT))
     42#define SYNCH_FAILED(rc)        ((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT | ESYNCH_INTERRUPTED))
    4243#define SYNCH_OK(rc)            ((rc) & (ESYNCH_OK_ATOMIC | ESYNCH_OK_BLOCKED))
    4344
  • generic/include/synch/waitq.h

    rfe04594 r203f4c3  
    5555        waitq_sleep_timeout((wq),SYNCH_NO_TIMEOUT,SYNCH_BLOCKING)
    5656
    57 extern void waitq_interrupted_sleep(void *data);
    58 
    5957extern void waitq_initialize(waitq_t *wq);
    6058extern int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking);
    6159extern void waitq_wakeup(waitq_t *wq, bool all);
    6260extern void _waitq_wakeup_unsafe(waitq_t *wq, bool all);
     61extern void waitq_interrupt_sleep(thread_t *t);
    6362
    6463#endif
  • generic/src/synch/waitq.c

    rfe04594 r203f4c3  
    4040#include <adt/list.h>
    4141
     42static void waitq_timeouted_sleep(void *data);
     43
    4244/** Initialize wait queue
    4345 *
     
    6567 * @param data Pointer to the thread that called waitq_sleep_timeout().
    6668 */
    67 void waitq_interrupted_sleep(void *data)
     69void waitq_timeouted_sleep(void *data)
    6870{
    6971        thread_t *t = (thread_t *) data;
     
    101103}
    102104
    103 /** Sleep until either wakeup or timeout occurs
     105/** Interrupt sleeping thread.
     106 *
     107 * This routine attempts to interrupt a thread from its sleep in a waitqueue.
     108 * If the thread is not found sleeping, no action is taken.
     109 *
     110 * @param t Thread to be interrupted.
     111 */
     112void waitq_interrupt_sleep(thread_t *t)
     113{
     114        waitq_t *wq;
     115        bool do_wakeup = false;
     116        ipl_t ipl;
     117
     118        ipl = interrupts_disable();
     119        spinlock_lock(&threads_lock);
     120        if (!list_member(&t->threads_link, &threads_head))
     121                goto out;
     122
     123grab_locks:
     124        spinlock_lock(&t->lock);
     125        if ((wq = t->sleep_queue)) {            /* assignment */
     126                if (!spinlock_trylock(&wq->lock)) {
     127                        spinlock_unlock(&t->lock);
     128                        goto grab_locks;        /* avoid deadlock */
     129                }
     130
     131                list_remove(&t->wq_link);
     132                t->saved_context = t->sleep_interruption_context;
     133                do_wakeup = true;
     134               
     135                spinlock_unlock(&wq->lock);
     136                t->sleep_queue = NULL;
     137        }
     138        spinlock_unlock(&t->lock);
     139
     140        if (do_wakeup)
     141                thread_ready(t);
     142
     143out:
     144        spinlock_unlock(&threads_lock);
     145        interrupts_restore(ipl);
     146}
     147
     148
     149/** Sleep until either wakeup, timeout or interruption occurs
    104150 *
    105151 * This is a sleep implementation which allows itself to be
     
    131177 *
    132178 * ESYNCH_TIMEOUT means that the sleep timed out.
     179 *
     180 * ESYNCH_INTERRUPTED means that somebody interrupted the sleeping thread.
    133181 *
    134182 * ESYNCH_OK_ATOMIC means that the sleep succeeded and that there was
     
    179227                }
    180228        }
    181 
    182229       
    183230        /*
     
    185232         */
    186233        spinlock_lock(&THREAD->lock);
     234
     235        /*
     236         * Set context that will be restored if the sleep
     237         * of this thread is ever interrupted.
     238         */
     239        if (!context_save(&THREAD->sleep_interruption_context)) {
     240                /* Short emulation of scheduler() return code. */
     241                spinlock_unlock(&THREAD->lock);
     242                interrupts_restore(ipl);
     243                return ESYNCH_INTERRUPTED;
     244        }
     245
    187246        if (usec) {
    188247                /* We use the timeout variant. */
    189248                if (!context_save(&THREAD->sleep_timeout_context)) {
    190                         /*
    191                          * Short emulation of scheduler() return code.
    192                          */
     249                        /* Short emulation of scheduler() return code. */
    193250                        spinlock_unlock(&THREAD->lock);
    194251                        interrupts_restore(ipl);
     
    196253                }
    197254                THREAD->timeout_pending = true;
    198                 timeout_register(&THREAD->sleep_timeout, (__u64) usec, waitq_interrupted_sleep, THREAD);
     255                timeout_register(&THREAD->sleep_timeout, (__u64) usec, waitq_timeouted_sleep, THREAD);
    199256        }
    200257
Note: See TracChangeset for help on using the changeset viewer.