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