-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqueue.c
61 lines (59 loc) · 1.47 KB
/
queue.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
* Copyright (c) 2020-2022 Jiansheng Qiu <[email protected]>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include "queue.h"
static inline struct nova_queue_block *
new_block(gfp_t gfp)
{
return (struct nova_queue_block *)
__get_free_pages(gfp, NOVA_QUEUE_BLOCK_ORDER);
}
static inline void
free_block(struct nova_queue_block *block)
{
free_pages((unsigned long)block, NOVA_QUEUE_BLOCK_ORDER);
}
int nova_queue_init(struct nova_queue *q, gfp_t gfp)
{
q->head = q->tail = new_block(gfp);
if (q->head == NULL)
return -ENOMEM;
q->front = q->back = 0;
return 0;
}
void nova_queue_destroy(struct nova_queue *q)
{
struct nova_queue_block *cur, *next = q->head;
do {
cur = next;
next = cur->next;
free_block(cur);
} while (cur != q->tail);
}
int nova_queue_push_ul(struct nova_queue *q, unsigned long data, gfp_t gfp)
{
if (unlikely(q->back == NOVA_QUEUE_BLOCK_CAP)) {
q->tail->next = new_block(gfp);
if (q->tail->next == NULL)
return -ENOMEM;
q->tail = q->tail->next;
q->back = 0;
}
q->tail->buf[q->back++] = data;
return 0;
}
// A push after a pop has to succeed.
unsigned long nova_queue_pop_ul(struct nova_queue *q)
{
if (unlikely(q->front == NOVA_QUEUE_BLOCK_CAP)) {
struct nova_queue_block *next = q->head->next;
free_block(q->head);
q->head = next;
q->front = 0;
}
return q->head->buf[q->front++];
}