AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
waitq.c
Go to the documentation of this file.
1
11
12#include <core/system.h>
13#include <core/panic.h>
14#include <core/arch.h>
15#include <sys/proc.h>
16#include <sys/sched.h>
17#include <sys/signal.h>
18#include <sys/waitq.h>
19
24static void sleep_on(struct waitq *waitq, state_t state)
25{
26 if (!waitq)
27 panic("sleeping in a blackhole?");
28
29 curthread->waitq = waitq;
30 list_append(&waitq->threads, &curthread->run_link);
31 curthread->state = state;
32 arch_sleep();
33 curthread->state = RUNNABLE;
34}
35
51{
53 return -ERESTARTSYS;
54
56
58}
59
68{
70}
71
72/*
73 * select() and poll() wait for any of several files. For each file, the
74 * thread registers the wait queue that the file's readers (or writers)
75 * sleep on (poll_register()), then sleeps on its own queue,
76 * `thread->poll_wait`. A wakeup of any registered queue also wakes that
77 * thread, which then looks at its files again. A file that can't say
78 * which queue it uses registers NULL, which every wakeup matches.
79 *
80 * Registrations are kept in a small hash table, keyed by the queue, so
81 * that a wakeup finds its pollers without looking at every thread.
82 */
83MALLOC_DEFINE(M_POLL_REG, "poll-reg", "a queue a thread polls");
84
86struct poll_reg {
87 struct waitq *queue;
88 struct thread *thread;
89 struct poll_reg *next; /* the next one in its hash chain */
90 struct poll_reg *thread_next; /* the thread's next registration */
91};
92
93#define POLL_HASH 64
94
96static int poll_regs;
97
99static struct poll_reg **poll_chain(struct waitq *queue)
100{
101 return &poll_hash[((uintptr_t) queue >> 4) % POLL_HASH];
102}
103
113{
114 struct thread *thread = curthread;
115
116 for (struct poll_reg *r = thread->poll_regs; r; r = r->thread_next)
117 if (r->queue == queue)
118 return 0;
119
120 struct poll_reg *r = kmalloc(sizeof(*r), &M_POLL_REG, 0);
121
122 if (!r)
123 return -ENOMEM;
124
125 struct poll_reg **chain = poll_chain(queue);
126
127 r->queue = queue;
128 r->thread = thread;
129 r->next = *chain;
130 *chain = r;
132 thread->poll_regs = r;
133 poll_regs++;
134
135 return 0;
136}
137
145{
146 while (thread->poll_regs) {
147 struct poll_reg *r = thread->poll_regs;
148 struct poll_reg **p = poll_chain(r->queue);
149
150 while (*p != r)
151 p = &(*p)->next;
152
153 *p = r->next;
155 poll_regs--;
156 kfree(r);
157 }
158}
159
161static void poll_wake(struct waitq *waitq)
162{
163 for (struct poll_reg *r = *poll_chain(waitq); r; r = r->next)
164 if (r->queue == waitq)
165 waitq_wakeup_nopoll(&r->thread->poll_wait);
166
167 for (struct poll_reg *r = *poll_chain(NULL); r; r = r->next)
168 if (!r->queue)
169 waitq_wakeup_nopoll(&r->thread->poll_wait);
170}
171
179{
180 if (!waitq)
181 return;
182
183 if (poll_regs)
185
187}
188
197{
198 struct list_node *node;
199
200 if (!waitq)
201 return;
202
203 while ((node = list_pop(&waitq->threads))) {
204 struct thread *thread = list_entry(node, struct thread, run_link);
205 thread->waitq = NULL;
207 }
208}
209
217{
218 if (!thread->waitq)
219 return;
220
221 list_remove(&thread->run_link);
222 thread->waitq = NULL;
224}
void arch_sleep(void)
Puts the current thread to sleep.
Definition sched.c:101
#define panic(s)
Definition panic.h:15
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
#define list_entry(node, type, member)
Definition list.h:43
#define curthread
Definition sched.h:12
void sched_thread_wake(struct thread *thread)
Makes a thread that was sleeping ready to run.
Definition sched.c:315
int signal_interrupts(struct thread *thread)
Says whether a thread has a signal to take, which ends a sleep that a signal may end.
Definition signal.c:215
#define ERESTARTSYS
Definition signal.h:81
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
A link in a list, inside the structure that is listed.
Definition list.h:31
One wait queue that one polling thread waits for.
Definition waitq.c:86
struct thread * thread
Definition waitq.c:88
struct poll_reg * next
Definition waitq.c:89
struct poll_reg * thread_next
Definition waitq.c:90
struct waitq * queue
Definition waitq.c:87
A queue.
Definition queue.h:29
A thread.
Definition thread.h:23
struct list_node run_link
it's on the ready list (sched.c) while it's ready to run, or on the wait queue it sleeps on (waitq); ...
Definition thread.h:45
state_t state
its state
Definition thread.h:28
struct waitq * waitq
Definition thread.h:46
struct poll_reg * poll_regs
in select() or poll(): what it waits for (poll_register()), and where it sleeps meanwhile
Definition thread.h:95
Definition waitq.h:19
struct list threads
Definition waitq.h:20
state_t
Definition thread.h:15
@ RUNNABLE
Definition thread.h:16
@ USLEEP
Definition thread.h:18
@ ISLEEP
Definition thread.h:17
static void sleep_on(struct waitq *waitq, state_t state)
Puts the current thread to sleep on waitq in state (ISLEEP or USLEEP), and returns once it has been w...
Definition waitq.c:24
static int poll_regs
Definition waitq.c:96
static struct poll_reg ** poll_chain(struct waitq *queue)
Returns the hash chain that registrations of queue are on.
Definition waitq.c:99
static struct poll_reg * poll_hash[POLL_HASH]
Definition waitq.c:95
#define POLL_HASH
Definition waitq.c:93
static void poll_wake(struct waitq *waitq)
Wakes up the threads polling waitq, and those polling any queue.
Definition waitq.c:161
void thread_wakeup(struct thread *thread)
Wakes up one thread, if it is sleeping on a wait queue.
Definition waitq.c:216
void waitq_wakeup_nopoll(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, but not the threads polling it.
Definition waitq.c:196
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
Definition waitq.c:178
void poll_unregister(struct thread *thread)
Removes every registration of a thread, when it stops waiting (it was woken up, or it is going away).
Definition waitq.c:144
void waitq_sleep_unint(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up, whatever signals come meanwhil...
Definition waitq.c:67
int waitq_sleep(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up.
Definition waitq.c:50
int poll_register(struct waitq *waitq)
Registers a wait queue that the current thread, in select() or poll(), waits for: a wakeup of that qu...
Definition waitq.c:112