AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
queue.h
Go to the documentation of this file.
1#ifndef _DS_QUEUE_H
2#define _DS_QUEUE_H
3
4#include <core/system.h>
5
6struct qnode;
7struct queue;
8
9#include <core/string.h>
10
11/*
12 * Queues: doubly linked lists of pointers, each entry in a node allocated
13 * for it. Adding an entry allocates, so it can fail; the kernel's lists
14 * that mustn't fail (the scheduler's, the wait queues) are in ds/list.h
15 * instead, linked through their entries.
16 */
17
19struct qnode {
20 void *value;
21 struct qnode *prev;
22 struct qnode *next;
23};
24
25/* A queue flag: print what is added to it, for debugging. */
26#define QUEUE_TRACE 1
27
29struct queue {
30 size_t count;
31 struct qnode *head;
32 struct qnode *tail;
33 int flags;
34};
35
36/* Loops over each node `n` of queue `q`. */
37#define queue_for(n, q) for (struct qnode *(n) = (q)->head; (n); (n) = (n)->next)
38
39/* A new, empty, static queue. */
40#define QUEUE_NEW() &(struct queue){0}
41
44static inline struct queue *queue_new(void)
45{
46 struct queue *queue;
47
48 queue = kmalloc(sizeof(struct queue), &M_QUEUE, 0);
49 if (!queue) return NULL;
50
51 memset(queue, 0, sizeof(struct queue));
52 return queue;
53}
54
57static inline struct qnode *enqueue(struct queue *queue, void *value)
58{
59 if (!queue)
60 return NULL;
61
62 int trace = queue->flags & QUEUE_TRACE;
63
64 if (trace) printk("qtrace: enqueue(%p, %p)\n", queue, value);
65
66 struct qnode *node;
67
68 node = kmalloc(sizeof(struct qnode), &M_QNODE, 0);
69 if (!node) return NULL;
70
71 memset(node, 0, sizeof(struct qnode));
72
73 if (trace) printk("qtrace: allocated node %p\n", node);
74
75 node->value = value;
76
77 if (!queue->count) {
78 /* the queue is empty */
79 queue->head = queue->tail = node;
80 } else {
81 node->prev = queue->tail;
82 queue->tail->next = node;
83 queue->tail = node;
84 }
85
86 ++queue->count;
87 return node;
88}
89
92static inline struct qnode *enqueue_head(struct queue *queue, void *value)
93{
94 if (!queue)
95 return NULL;
96
97 struct qnode *node = kmalloc(sizeof(struct qnode), &M_QNODE, 0);
98 if (!node) return NULL;
99
100 memset(node, 0, sizeof(struct qnode));
101 node->value = value;
102
103 if (!queue->count) {
104 queue->head = queue->tail = node;
105 } else {
106 node->next = queue->head;
107 queue->head->prev = node;
108 queue->head = node;
109 }
110
111 ++queue->count;
112 return node;
113}
114
117static inline void *dequeue(struct queue *queue)
118{
119 if (!queue || !queue->count)
120 return NULL;
121
122 --queue->count;
123 struct qnode *head = queue->head;
124
125 queue->head = head->next;
126
127 if (queue->head)
128 queue->head->prev = NULL;
129
130 if (head == queue->tail)
131 queue->tail = NULL;
132
133 void *value = head->value;
134 kfree(head);
135
136 return value;
137}
138
140static inline void queue_remove(struct queue *queue, void *value)
141{
142 if (!queue || !queue->count)
143 return;
144
145 queue_for (node, queue) {
146 if (node->value == value) {
147 if (!node->prev) { /* the head */
148 dequeue(queue);
149 } else if (!node->next) { /* the tail */
150 --queue->count;
151 queue->tail = queue->tail->prev;
152 queue->tail->next = NULL;
153 kfree(node);
154 } else {
155 --queue->count;
156 node->prev->next = node->next;
157 node->next->prev = node->prev;
158 kfree(node);
159 }
160
161 break;
162 }
163 }
164}
165
167static inline void queue_node_remove(struct queue *queue, struct qnode *node)
168{
169 if (!queue || !queue->count || !node)
170 return;
171
172 if (node->prev)
173 node->prev->next = node->next;
174 if (node->next)
175 node->next->prev = node->prev;
176 if (queue->head == node)
177 queue->head = node->next;
178 if (queue->tail == node)
179 queue->tail = node->prev;
180
181 --queue->count;
182 kfree(node);
183 return;
184}
185
186#endif /* ! _DS_QUEUE_H */
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
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
Definition libc.c:23
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
static void * dequeue(struct queue *queue)
Takes the first entry off a queue, frees its node, and returns the entry, or NULL if the queue is emp...
Definition queue.h:117
#define QUEUE_TRACE
Definition queue.h:26
static struct qnode * enqueue_head(struct queue *queue, void *value)
Adds an entry at the head of a queue, so that dequeue() returns it next.
Definition queue.h:92
#define queue_for(n, q)
Definition queue.h:37
static void queue_remove(struct queue *queue, void *value)
Removes the first node whose entry is value, if there's one.
Definition queue.h:140
static struct qnode * enqueue(struct queue *queue, void *value)
Adds an entry at the end of a queue.
Definition queue.h:57
static struct queue * queue_new(void)
Returns a new, empty queue from kmalloc(), or NULL if there was no memory for it.
Definition queue.h:44
static void queue_node_remove(struct queue *queue, struct qnode *node)
Removes a node from a queue, and frees it.
Definition queue.h:167
#define NULL
Definition stddef.h:27
A queue's node, holding one entry.
Definition queue.h:19
void * value
Definition queue.h:20
struct qnode * next
Definition queue.h:22
struct qnode * prev
Definition queue.h:21
A queue.
Definition queue.h:29
struct qnode * tail
Definition queue.h:32
size_t count
Definition queue.h:30
struct qnode * head
Definition queue.h:31
int flags
Definition queue.h:33