Subversion Repositories HelenOS-historic

Rev

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

Rev 1467 Rev 1502
Line 133... Line 133...
133
        goto out;
133
        goto out;
134
 
134
 
135
grab_locks:
135
grab_locks:
136
    spinlock_lock(&t->lock);
136
    spinlock_lock(&t->lock);
137
    if ((wq = t->sleep_queue)) {        /* assignment */
137
    if ((wq = t->sleep_queue)) {        /* assignment */
-
 
138
        if (!(t->sleep_interruptible)) {
-
 
139
            /*
-
 
140
             * The sleep cannot be interrupted.
-
 
141
             */
-
 
142
            spinlock_unlock(&t->lock);
-
 
143
            goto out;
-
 
144
        }
-
 
145
           
138
        if (!spinlock_trylock(&wq->lock)) {
146
        if (!spinlock_trylock(&wq->lock)) {
139
            spinlock_unlock(&t->lock);
147
            spinlock_unlock(&t->lock);
140
            goto grab_locks;    /* avoid deadlock */
148
            goto grab_locks;    /* avoid deadlock */
141
        }
149
        }
142
 
150
 
Line 157... Line 165...
157
    interrupts_restore(ipl);
165
    interrupts_restore(ipl);
158
}
166
}
159
 
167
 
160
/** Sleep until either wakeup, timeout or interruption occurs
168
/** Sleep until either wakeup, timeout or interruption occurs
161
 *
169
 *
162
 * This is a sleep implementation which allows itself to be
170
 * This is a sleep implementation which allows itself to time out or to be
163
 * interrupted from the sleep, restoring a failover context.
171
 * interrupted from the sleep, restoring a failover context.
164
 *
172
 *
165
 * Sleepers are organised in a FIFO fashion in a structure called wait queue.
173
 * Sleepers are organised in a FIFO fashion in a structure called wait queue.
166
 *
174
 *
167
 * This function is really basic in that other functions as waitq_sleep()
175
 * This function is really basic in that other functions as waitq_sleep()
168
 * and all the *_timeout() functions use it.
176
 * and all the *_timeout() functions use it.
169
 *
177
 *
170
 * @param wq Pointer to wait queue.
178
 * @param wq Pointer to wait queue.
171
 * @param usec Timeout in microseconds.
179
 * @param usec Timeout in microseconds.
172
 * @param nonblocking Blocking vs. non-blocking operation mode switch.
180
 * @param flags Specify mode of the sleep.
173
 *
181
 *
-
 
182
 * The sleep can be interrupted only if the
-
 
183
 * SYNCH_FLAGS_INTERRUPTIBLE bit is specified in flags.
-
 
184
 
174
 * If usec is greater than zero, regardless of the value of nonblocking,
185
 * If usec is greater than zero, regardless of the value of the
175
 * the call will not return until either timeout or wakeup comes.
186
 * SYNCH_FLAGS_NON_BLOCKING bit in flags, the call will not return until either timeout,
-
 
187
 * interruption or wakeup comes.
176
 *
188
 *
177
 * If usec is zero and @nonblocking is zero (false), the call
189
 * If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is not set in flags, the call
178
 * will not return until wakeup comes.
190
 * will not return until wakeup or interruption comes.
179
 *
191
 *
180
 * If usec is zero and nonblocking is non-zero (true), the call will
192
 * If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is set in flags, the call will
181
 * immediately return, reporting either success or failure.
193
 * immediately return, reporting either success or failure.
182
 *
194
 *
183
 * @return  Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT,
195
 * @return  Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, ESYNCH_INTERRUPTED,
184
 *          ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED.
196
 *          ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED.
185
 *
197
 *
186
 * @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
198
 * @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
187
 * of the call there was no pending wakeup.
199
 * of the call there was no pending wakeup.
188
 *
200
 *
Line 195... Line 207...
195
 * asleep at all.
207
 * asleep at all.
196
 *
208
 *
197
 * @li ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was
209
 * @li ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was
198
 * attempted.
210
 * attempted.
199
 */
211
 */
200
int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking)
212
int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int flags)
201
{
213
{
202
    ipl_t ipl;
214
    ipl_t ipl;
203
    int rc;
215
    int rc;
204
   
216
   
205
    ipl = waitq_sleep_prepare(wq);
217
    ipl = waitq_sleep_prepare(wq);
206
    rc = waitq_sleep_timeout_unsafe(wq, usec, nonblocking);
218
    rc = waitq_sleep_timeout_unsafe(wq, usec, flags);
207
    waitq_sleep_finish(wq, rc, ipl);
219
    waitq_sleep_finish(wq, rc, ipl);
208
    return rc;
220
    return rc;
209
}
221
}
210
 
222
 
211
/** Prepare to sleep in a waitq.
223
/** Prepare to sleep in a waitq.
Line 274... Line 286...
274
 * This call must be preceeded by a call to waitq_sleep_prepare()
286
 * This call must be preceeded by a call to waitq_sleep_prepare()
275
 * and followed by a call to waitq_slee_finish().
287
 * and followed by a call to waitq_slee_finish().
276
 *
288
 *
277
 * @param wq See waitq_sleep_timeout().
289
 * @param wq See waitq_sleep_timeout().
278
 * @param usec See waitq_sleep_timeout().
290
 * @param usec See waitq_sleep_timeout().
279
 * @param nonblocking See waitq_sleep_timeout().
291
 * @param flags See waitq_sleep_timeout().
280
 *
292
 *
281
 * @return See waitq_sleep_timeout().
293
 * @return See waitq_sleep_timeout().
282
 */
294
 */
283
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int nonblocking)
295
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int flags)
284
{
296
{
285
    /* checks whether to go to sleep at all */
297
    /* checks whether to go to sleep at all */
286
    if (wq->missed_wakeups) {
298
    if (wq->missed_wakeups) {
287
        wq->missed_wakeups--;
299
        wq->missed_wakeups--;
288
        return ESYNCH_OK_ATOMIC;
300
        return ESYNCH_OK_ATOMIC;
289
    }
301
    }
290
    else {
302
    else {
291
        if (nonblocking && (usec == 0)) {
303
        if ((flags & SYNCH_FLAGS_NON_BLOCKING) && (usec == 0)) {
292
            /* return immediatelly instead of going to sleep */
304
            /* return immediatelly instead of going to sleep */
293
            return ESYNCH_WOULD_BLOCK;
305
            return ESYNCH_WOULD_BLOCK;
294
        }
306
        }
295
    }
307
    }
296
   
308
   
297
    /*
309
    /*
298
     * Now we are firmly decided to go to sleep.
310
     * Now we are firmly decided to go to sleep.
299
     */
311
     */
300
    spinlock_lock(&THREAD->lock);
312
    spinlock_lock(&THREAD->lock);
301
 
313
 
-
 
314
    if (flags & SYNCH_FLAGS_INTERRUPTIBLE) {
302
    /*
315
        /*
303
     * Set context that will be restored if the sleep
316
         * Set context that will be restored if the sleep
304
     * of this thread is ever interrupted.
317
         * of this thread is ever interrupted.
305
     */
318
         */
-
 
319
        THREAD->sleep_interruptible = true;
306
    if (!context_save(&THREAD->sleep_interruption_context)) {
320
        if (!context_save(&THREAD->sleep_interruption_context)) {
307
        /* Short emulation of scheduler() return code. */
321
            /* Short emulation of scheduler() return code. */
308
        spinlock_unlock(&THREAD->lock);
322
            spinlock_unlock(&THREAD->lock);
309
        return ESYNCH_INTERRUPTED;
323
            return ESYNCH_INTERRUPTED;
-
 
324
        }
-
 
325
    } else {
-
 
326
        THREAD->sleep_interruptible = false;
310
    }
327
    }
311
 
328
 
312
    if (usec) {
329
    if (usec) {
313
        /* We use the timeout variant. */
330
        /* We use the timeout variant. */
314
        if (!context_save(&THREAD->sleep_timeout_context)) {
331
        if (!context_save(&THREAD->sleep_timeout_context)) {