1 /*
2 * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "osi/allocator.h"
8 #include "osi/pkt_queue.h"
9 #include "osi/fixed_pkt_queue.h"
10 #include "osi/osi.h"
11 #include "osi/semaphore.h"
12
13 typedef struct fixed_pkt_queue_t {
14 struct pkt_queue *pkt_list;
15 osi_sem_t enqueue_sem;
16 osi_sem_t dequeue_sem;
17 size_t capacity;
18 fixed_pkt_queue_cb dequeue_ready;
19 } fixed_pkt_queue_t;
20
fixed_pkt_queue_new(size_t capacity)21 fixed_pkt_queue_t *fixed_pkt_queue_new(size_t capacity)
22 {
23 fixed_pkt_queue_t *ret = osi_calloc(sizeof(fixed_pkt_queue_t));
24 if (!ret) {
25 goto error;
26 }
27
28 ret->capacity = capacity;
29 ret->pkt_list = pkt_queue_create();
30 if (!ret->pkt_list) {
31 goto error;
32 }
33
34 osi_sem_new(&ret->enqueue_sem, capacity, capacity);
35 if (!ret->enqueue_sem) {
36 goto error;
37 }
38
39 osi_sem_new(&ret->dequeue_sem, capacity, 0);
40 if (!ret->dequeue_sem) {
41 goto error;
42 }
43
44 return ret;
45
46 error:
47 fixed_pkt_queue_free(ret, NULL);
48 return NULL;
49 }
50
fixed_pkt_queue_free(fixed_pkt_queue_t * queue,fixed_pkt_queue_free_cb free_cb)51 void fixed_pkt_queue_free(fixed_pkt_queue_t *queue, fixed_pkt_queue_free_cb free_cb)
52 {
53 if (queue == NULL) {
54 return;
55 }
56
57 fixed_pkt_queue_unregister_dequeue(queue);
58
59 pkt_queue_destroy(queue->pkt_list, (pkt_queue_free_cb)free_cb);
60 queue->pkt_list = NULL;
61
62 if (queue->enqueue_sem) {
63 osi_sem_free(&queue->enqueue_sem);
64 }
65 if (queue->dequeue_sem) {
66 osi_sem_free(&queue->dequeue_sem);
67 }
68 osi_free(queue);
69 }
70
fixed_pkt_queue_is_empty(fixed_pkt_queue_t * queue)71 bool fixed_pkt_queue_is_empty(fixed_pkt_queue_t *queue)
72 {
73 if (queue == NULL) {
74 return true;
75 }
76
77 return pkt_queue_is_empty(queue->pkt_list);
78 }
79
fixed_pkt_queue_length(fixed_pkt_queue_t * queue)80 size_t fixed_pkt_queue_length(fixed_pkt_queue_t *queue)
81 {
82 if (queue == NULL) {
83 return 0;
84 }
85 return pkt_queue_length(queue->pkt_list);
86 }
87
fixed_pkt_queue_capacity(fixed_pkt_queue_t * queue)88 size_t fixed_pkt_queue_capacity(fixed_pkt_queue_t *queue)
89 {
90 assert(queue != NULL);
91
92 return queue->capacity;
93 }
94
fixed_pkt_queue_enqueue(fixed_pkt_queue_t * queue,pkt_linked_item_t * linked_pkt,uint32_t timeout)95 bool fixed_pkt_queue_enqueue(fixed_pkt_queue_t *queue, pkt_linked_item_t *linked_pkt, uint32_t timeout)
96 {
97 bool ret = false;
98
99 assert(queue != NULL);
100 assert(linked_pkt != NULL);
101
102 if (osi_sem_take(&queue->enqueue_sem, timeout) != 0) {
103 return false;
104 }
105
106 ret = pkt_queue_enqueue(queue->pkt_list, linked_pkt);
107
108 assert(ret == true);
109 osi_sem_give(&queue->dequeue_sem);
110
111 return ret;
112 }
113
fixed_pkt_queue_dequeue(fixed_pkt_queue_t * queue,uint32_t timeout)114 pkt_linked_item_t *fixed_pkt_queue_dequeue(fixed_pkt_queue_t *queue, uint32_t timeout)
115 {
116 pkt_linked_item_t *ret = NULL;
117
118 assert(queue != NULL);
119
120 if (osi_sem_take(&queue->dequeue_sem, timeout) != 0) {
121 return NULL;
122 }
123 ret = pkt_queue_dequeue(queue->pkt_list);
124
125 osi_sem_give(&queue->enqueue_sem);
126
127 return ret;
128 }
129
fixed_pkt_queue_try_peek_first(fixed_pkt_queue_t * queue)130 pkt_linked_item_t *fixed_pkt_queue_try_peek_first(fixed_pkt_queue_t *queue)
131 {
132 if (queue == NULL) {
133 return NULL;
134 }
135
136 return pkt_queue_try_peek_first(queue->pkt_list);
137 }
138
fixed_pkt_queue_register_dequeue(fixed_pkt_queue_t * queue,fixed_pkt_queue_cb ready_cb)139 void fixed_pkt_queue_register_dequeue(fixed_pkt_queue_t *queue, fixed_pkt_queue_cb ready_cb)
140 {
141 assert(queue != NULL);
142 assert(ready_cb != NULL);
143
144 queue->dequeue_ready = ready_cb;
145 }
146
fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t * queue)147 void fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t *queue)
148 {
149 assert(queue != NULL);
150
151 queue->dequeue_ready = NULL;
152 }
153
fixed_pkt_queue_process(fixed_pkt_queue_t * queue)154 void fixed_pkt_queue_process(fixed_pkt_queue_t *queue)
155 {
156 assert(queue != NULL);
157
158 if (queue->dequeue_ready) {
159 queue->dequeue_ready(queue);
160 }
161 }
162