Subversion Repositories HelenOS

Rev

Rev 1103 | Rev 1158 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1103 Rev 1156
Line 37... Line 37...
37
#include <time/timeout.h>
37
#include <time/timeout.h>
38
#include <arch.h>
38
#include <arch.h>
39
#include <context.h>
39
#include <context.h>
40
#include <adt/list.h>
40
#include <adt/list.h>
41
 
41
 
-
 
42
static void waitq_timeouted_sleep(void *data);
-
 
43
 
42
/** Initialize wait queue
44
/** Initialize wait queue
43
 *
45
 *
44
 * Initialize wait queue.
46
 * Initialize wait queue.
45
 *
47
 *
46
 * @param wq Pointer to wait queue to be initialized.
48
 * @param wq Pointer to wait queue to be initialized.
Line 62... Line 64...
62
 * overlap. In that case it behaves just as though there was no
64
 * overlap. In that case it behaves just as though there was no
63
 * timeout at all.
65
 * timeout at all.
64
 *
66
 *
65
 * @param data Pointer to the thread that called waitq_sleep_timeout().
67
 * @param data Pointer to the thread that called waitq_sleep_timeout().
66
 */
68
 */
67
void waitq_interrupted_sleep(void *data)
69
void waitq_timeouted_sleep(void *data)
68
{
70
{
69
    thread_t *t = (thread_t *) data;
71
    thread_t *t = (thread_t *) data;
70
    waitq_t *wq;
72
    waitq_t *wq;
71
    bool do_wakeup = false;
73
    bool do_wakeup = false;
72
 
74
 
Line 98... Line 100...
98
 
100
 
99
out:
101
out:
100
    spinlock_unlock(&threads_lock);
102
    spinlock_unlock(&threads_lock);
101
}
103
}
102
 
104
 
-
 
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
 */
-
 
112
void 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
 
-
 
123
grab_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
 
-
 
143
out:
-
 
144
    spinlock_unlock(&threads_lock);
-
 
145
    interrupts_restore(ipl);
-
 
146
}
-
 
147
 
-
 
148
 
103
/** Sleep until either wakeup or timeout occurs
149
/** Sleep until either wakeup, timeout or interruption occurs
104
 *
150
 *
105
 * This is a sleep implementation which allows itself to be
151
 * This is a sleep implementation which allows itself to be
106
 * interrupted from the sleep, restoring a failover context.
152
 * interrupted from the sleep, restoring a failover context.
107
 *
153
 *
108
 * Sleepers are organised in FIFO fashion in a structure called wait queue.
154
 * Sleepers are organised in FIFO fashion in a structure called wait queue.
Line 129... Line 175...
129
 * ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
175
 * ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
130
 * of the call there was no pending wakeup.
176
 * of the call there was no pending wakeup.
131
 *
177
 *
132
 * ESYNCH_TIMEOUT means that the sleep timed out.
178
 * ESYNCH_TIMEOUT means that the sleep timed out.
133
 *
179
 *
-
 
180
 * ESYNCH_INTERRUPTED means that somebody interrupted the sleeping thread.
-
 
181
 *
134
 * ESYNCH_OK_ATOMIC means that the sleep succeeded and that there was
182
 * ESYNCH_OK_ATOMIC means that the sleep succeeded and that there was
135
 * a pending wakeup at the time of the call. The caller was not put
183
 * a pending wakeup at the time of the call. The caller was not put
136
 * asleep at all.
184
 * asleep at all.
137
 *
185
 *
138
 * ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was
186
 * ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was
Line 176... Line 224...
176
            spinlock_unlock(&wq->lock);
224
            spinlock_unlock(&wq->lock);
177
            interrupts_restore(ipl);
225
            interrupts_restore(ipl);
178
            return ESYNCH_WOULD_BLOCK;
226
            return ESYNCH_WOULD_BLOCK;
179
        }
227
        }
180
    }
228
    }
181
 
-
 
182
   
229
   
183
    /*
230
    /*
184
     * Now we are firmly decided to go to sleep.
231
     * Now we are firmly decided to go to sleep.
185
     */
232
     */
186
    spinlock_lock(&THREAD->lock);
233
    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
 
187
    if (usec) {
246
    if (usec) {
188
        /* We use the timeout variant. */
247
        /* We use the timeout variant. */
189
        if (!context_save(&THREAD->sleep_timeout_context)) {
248
        if (!context_save(&THREAD->sleep_timeout_context)) {
190
            /*
-
 
191
             * Short emulation of scheduler() return code.
249
            /* Short emulation of scheduler() return code. */
192
             */
-
 
193
            spinlock_unlock(&THREAD->lock);
250
            spinlock_unlock(&THREAD->lock);
194
            interrupts_restore(ipl);
251
            interrupts_restore(ipl);
195
            return ESYNCH_TIMEOUT;
252
            return ESYNCH_TIMEOUT;
196
        }
253
        }
197
        THREAD->timeout_pending = true;
254
        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);
199
    }
256
    }
200
 
257
 
201
    list_append(&THREAD->wq_link, &wq->head);
258
    list_append(&THREAD->wq_link, &wq->head);
202
 
259
 
203
    /*
260
    /*