Project

General

Profile

Statistics
| Revision:

root / lab4 / .minix-src / include / sys / sleepq.h @ 14

History | View | Annotate | Download (5.22 KB)

1 13 up20180614
/*        $NetBSD: sleepq.h,v 1.24 2015/02/08 19:39:09 christos Exp $        */
2
3
/*-
4
 * Copyright (c) 2002, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
5
 * All rights reserved.
6
 *
7
 * This code is derived from software contributed to The NetBSD Foundation
8
 * by Jason R. Thorpe and Andrew Doran.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#ifndef        _SYS_SLEEPQ_H_
33
#define        _SYS_SLEEPQ_H_
34
35
#include <sys/lwp.h>
36
#include <sys/mutex.h>
37
#include <sys/pool.h>
38
#include <sys/queue.h>
39
#include <sys/sched.h>
40
#include <sys/syncobj.h>
41
42
/*
43
 * Generic sleep queues.
44
 */
45
46
#define        SLEEPTAB_HASH_SHIFT        7
47
#define        SLEEPTAB_HASH_SIZE        (1 << SLEEPTAB_HASH_SHIFT)
48
#define        SLEEPTAB_HASH_MASK        (SLEEPTAB_HASH_SIZE - 1)
49
#define        SLEEPTAB_HASH(wchan)        (((uintptr_t)(wchan) >> 8) & SLEEPTAB_HASH_MASK)
50
51
TAILQ_HEAD(sleepq, lwp);
52
53
typedef struct sleepq sleepq_t;
54
55
typedef struct sleeptab {
56
        struct {
57
                kmutex_t        *st_mutex;
58
                sleepq_t        st_queue;
59
        } st_queues[SLEEPTAB_HASH_SIZE];
60
} sleeptab_t;
61
62
void        sleepq_init(sleepq_t *);
63
void        sleepq_remove(sleepq_t *, lwp_t *);
64
void        sleepq_enqueue(sleepq_t *, wchan_t, const char *, struct syncobj *);
65
void        sleepq_unsleep(lwp_t *, bool);
66
void        sleepq_timeout(void *);
67
void        sleepq_wake(sleepq_t *, wchan_t, u_int, kmutex_t *);
68
int        sleepq_abort(kmutex_t *, int);
69
void        sleepq_changepri(lwp_t *, pri_t);
70
void        sleepq_lendpri(lwp_t *, pri_t);
71
int        sleepq_block(int, bool);
72
73
void        sleeptab_init(sleeptab_t *);
74
75
extern sleeptab_t        sleeptab;
76
77
#ifdef _KERNEL
78
/*
79
 * Return non-zero if it is unsafe to sleep.
80
 *
81
 * XXX This only exists because panic() is broken.
82
 */
83
static inline bool
84
sleepq_dontsleep(lwp_t *l)
85
{
86
        extern int cold;
87
88
        return cold || (doing_shutdown && (panicstr || CURCPU_IDLE_P()));
89
}
90
91
/*
92
 * Find the correct sleep queue for the specified wait channel.  This
93
 * acquires and holds the per-queue interlock.
94
 */
95
static inline sleepq_t *
96
sleeptab_lookup(sleeptab_t *st, wchan_t wchan, kmutex_t **mp)
97
{
98
        sleepq_t *sq;
99
100
        sq = &st->st_queues[SLEEPTAB_HASH(wchan)].st_queue;
101
        *mp = st->st_queues[SLEEPTAB_HASH(wchan)].st_mutex;
102
        mutex_spin_enter(*mp);
103
        return sq;
104
}
105
106
static inline kmutex_t *
107
sleepq_hashlock(wchan_t wchan)
108
{
109
        kmutex_t *mp;
110
111
        mp = sleeptab.st_queues[SLEEPTAB_HASH(wchan)].st_mutex;
112
        mutex_spin_enter(mp);
113
        return mp;
114
}
115
116
/*
117
 * Prepare to block on a sleep queue, after which any interlock can be
118
 * safely released.
119
 */
120
static inline void
121
sleepq_enter(sleepq_t *sq, lwp_t *l, kmutex_t *mp)
122
{
123
124
        /*
125
         * Acquire the per-LWP mutex and lend it ours sleep queue lock.
126
         * Once interlocked, we can release the kernel lock.
127
         */
128
        lwp_lock(l);
129
        lwp_unlock_to(l, mp);
130
        KERNEL_UNLOCK_ALL(NULL, &l->l_biglocks);
131
}
132
#endif
133
134
/*
135
 * Turnstiles, specialized sleep queues for use by kernel locks.
136
 */
137
138
typedef struct turnstile {
139
        LIST_ENTRY(turnstile)        ts_chain;        /* link on hash chain */
140
        struct turnstile        *ts_free;        /* turnstile free list */
141
        wchan_t                        ts_obj;                /* lock object */
142
        sleepq_t                ts_sleepq[2];        /* sleep queues */
143
        u_int                        ts_waiters[2];        /* count of waiters */
144
145
        /* priority inheritance */
146
        pri_t                        ts_eprio;
147
        lwp_t                        *ts_inheritor;
148
        SLIST_ENTRY(turnstile)        ts_pichain;
149
} turnstile_t;
150
151
typedef struct tschain {
152
        kmutex_t                *tc_mutex;        /* mutex on structs & queues */
153
        LIST_HEAD(, turnstile)        tc_chain;        /* turnstile chain */
154
} tschain_t;
155
156
#define        TS_READER_Q        0                /* reader sleep queue */
157
#define        TS_WRITER_Q        1                /* writer sleep queue */
158
159
#define        TS_WAITERS(ts, q)                                                \
160
        (ts)->ts_waiters[(q)]
161
162
#define        TS_ALL_WAITERS(ts)                                                \
163
        ((ts)->ts_waiters[TS_READER_Q] +                                \
164
         (ts)->ts_waiters[TS_WRITER_Q])
165
166
#define        TS_FIRST(ts, q)        (TAILQ_FIRST(&(ts)->ts_sleepq[(q)]))
167
168
#ifdef        _KERNEL
169
170
void        turnstile_init(void);
171
turnstile_t        *turnstile_lookup(wchan_t);
172
void        turnstile_exit(wchan_t);
173
void        turnstile_block(turnstile_t *, int, wchan_t, syncobj_t *);
174
void        turnstile_wakeup(turnstile_t *, int, int, lwp_t *);
175
void        turnstile_print(volatile void *, void (*)(const char *, ...)
176
    __printflike(1, 2));
177
void        turnstile_unsleep(lwp_t *, bool);
178
void        turnstile_changepri(lwp_t *, pri_t);
179
180
extern pool_cache_t turnstile_cache;
181
extern turnstile_t turnstile0;
182
183
#endif        /* _KERNEL */
184
185
#endif        /* _SYS_SLEEPQ_H_ */