1 /*
2 * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "osi/pkt_queue.h"
8 #include "osi/allocator.h"
9 #include "osi/mutex.h"
10
11
12 STAILQ_HEAD(pkt_queue_header, pkt_linked_item);
13
14 struct pkt_queue {
15 osi_mutex_t lock;
16 size_t length;
17 struct pkt_queue_header header;
18 } pkt_queue_t;
19
pkt_queue_create(void)20 struct pkt_queue *pkt_queue_create(void)
21 {
22 struct pkt_queue *queue = calloc(1, sizeof(struct pkt_queue));
23 if (queue == NULL) {
24 return NULL;
25 }
26 if (osi_mutex_new(&queue->lock) != 0) {
27 osi_free(queue);
28 }
29 struct pkt_queue_header *p = &queue->header;
30 STAILQ_INIT(p);
31
32 return queue;
33 }
34
pkt_queue_cleanup(struct pkt_queue * queue,pkt_queue_free_cb free_cb)35 static void pkt_queue_cleanup(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
36 {
37 if (queue == NULL) {
38 return;
39 }
40
41 struct pkt_queue_header *header = &queue->header;
42 pkt_linked_item_t *item = STAILQ_FIRST(header);
43 pkt_linked_item_t *tmp;
44
45 pkt_queue_free_cb free_func = (free_cb != NULL) ? free_cb : (pkt_queue_free_cb)osi_free_func;
46
47 while (item != NULL) {
48 tmp = STAILQ_NEXT(item, next);
49 free_func(item);
50 item = tmp;
51 queue->length--;
52 }
53 STAILQ_INIT(header);
54 queue->length = 0;
55 }
56
pkt_queue_flush(struct pkt_queue * queue,pkt_queue_free_cb free_cb)57 void pkt_queue_flush(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
58 {
59 if (queue == NULL) {
60 return;
61 }
62 osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
63 pkt_queue_cleanup(queue, free_cb);
64 osi_mutex_unlock(&queue->lock);
65 }
66
pkt_queue_destroy(struct pkt_queue * queue,pkt_queue_free_cb free_cb)67 void pkt_queue_destroy(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
68 {
69 if (queue == NULL) {
70 return;
71 }
72 osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
73 pkt_queue_cleanup(queue, free_cb);
74 osi_mutex_unlock(&queue->lock);
75
76 osi_mutex_free(&queue->lock);
77 osi_free(queue);
78 }
79
pkt_queue_dequeue(struct pkt_queue * queue)80 pkt_linked_item_t *pkt_queue_dequeue(struct pkt_queue *queue)
81 {
82 if (queue == NULL || queue->length == 0) {
83 return NULL;
84 }
85
86 struct pkt_linked_item *item;
87 struct pkt_queue_header *header;
88 osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
89 header = &queue->header;
90 item = STAILQ_FIRST(header);
91 if (item != NULL) {
92 STAILQ_REMOVE_HEAD(header, next);
93 if (queue->length > 0) {
94 queue->length--;
95 }
96 }
97 osi_mutex_unlock(&queue->lock);
98
99 return item;
100 }
101
pkt_queue_enqueue(struct pkt_queue * queue,pkt_linked_item_t * item)102 bool pkt_queue_enqueue(struct pkt_queue *queue, pkt_linked_item_t *item)
103 {
104 if (queue == NULL || item == NULL) {
105 return false;
106 }
107
108 struct pkt_queue_header *header;
109 osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
110 header = &queue->header;
111 STAILQ_INSERT_TAIL(header, item, next);
112 queue->length++;
113 osi_mutex_unlock(&queue->lock);
114
115 return true;
116 }
117
pkt_queue_length(const struct pkt_queue * queue)118 size_t pkt_queue_length(const struct pkt_queue *queue)
119 {
120 if (queue == NULL) {
121 return 0;
122 }
123 return queue->length;
124 }
125
pkt_queue_is_empty(const struct pkt_queue * queue)126 bool pkt_queue_is_empty(const struct pkt_queue *queue)
127 {
128 return pkt_queue_length(queue) == 0;
129 }
130
pkt_queue_try_peek_first(struct pkt_queue * queue)131 pkt_linked_item_t *pkt_queue_try_peek_first(struct pkt_queue *queue)
132 {
133 if (queue == NULL) {
134 return NULL;
135 }
136
137 struct pkt_queue_header *header = &queue->header;
138 pkt_linked_item_t *item;
139 osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
140 item = STAILQ_FIRST(header);
141 osi_mutex_unlock(&queue->lock);
142
143 return item;
144 }
145