1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #include "k_api.h"
6
7 #if (RHINO_CONFIG_QUEUE > 0)
task_msg_recv(ktask_t * task,void * msg)8 RHINO_INLINE void task_msg_recv(ktask_t *task, void *msg)
9 {
10 task->msg = msg;
11 pend_task_wakeup(task);
12 }
13
queue_create(kqueue_t * queue,const name_t * name,void ** start,size_t msg_num,uint8_t mm_alloc_flag)14 static kstat_t queue_create(kqueue_t *queue, const name_t *name, void **start,
15 size_t msg_num, uint8_t mm_alloc_flag)
16 {
17 #if (RHINO_CONFIG_KOBJ_LIST > 0)
18 CPSR_ALLOC();
19 #endif
20
21 NULL_PARA_CHK(queue);
22 NULL_PARA_CHK(start);
23 NULL_PARA_CHK(name);
24
25 if (msg_num == 0u) {
26 return RHINO_INV_PARAM;
27 }
28
29 memset(queue, 0, sizeof(kqueue_t));
30
31 /* init the queue blocked list */
32 klist_init(&queue->blk_obj.blk_list);
33
34 queue->blk_obj.name = name;
35 queue->blk_obj.blk_policy = BLK_POLICY_PRI;
36 queue->msg_q.queue_start = start;
37
38 ringbuf_init(&queue->ringbuf, (void *)start, msg_num * sizeof(void *),
39 RINGBUF_TYPE_FIX, sizeof(void *));
40
41 queue->msg_q.size = msg_num;
42 queue->msg_q.cur_num = 0u;
43 queue->msg_q.peak_num = 0u;
44 queue->mm_alloc_flag = mm_alloc_flag;
45 #if (RHINO_CONFIG_TASK_DEL > 0)
46 queue->blk_obj.cancel = 1u;
47 #endif
48
49 #if (RHINO_CONFIG_KOBJ_LIST > 0)
50 RHINO_CRITICAL_ENTER();
51 klist_insert(&(g_kobj_list.queue_head), &queue->queue_item);
52 RHINO_CRITICAL_EXIT();
53 #endif
54
55 queue->blk_obj.obj_type = RHINO_QUEUE_OBJ_TYPE;
56
57 return RHINO_SUCCESS;
58 }
59
krhino_queue_create(kqueue_t * queue,const name_t * name,void ** start,size_t msg_num)60 kstat_t krhino_queue_create(kqueue_t *queue, const name_t *name, void **start,
61 size_t msg_num)
62 {
63 return queue_create(queue, name, start, msg_num, K_OBJ_STATIC_ALLOC);
64 }
65
krhino_queue_del(kqueue_t * queue)66 kstat_t krhino_queue_del(kqueue_t *queue)
67 {
68 CPSR_ALLOC();
69 klist_t *blk_list_head;
70
71 NULL_PARA_CHK(queue);
72
73 RHINO_CRITICAL_ENTER();
74
75 INTRPT_NESTED_LEVEL_CHK();
76
77 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
78 RHINO_CRITICAL_EXIT();
79 return RHINO_KOBJ_TYPE_ERR;
80 }
81
82 if (queue->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
83 RHINO_CRITICAL_EXIT();
84 return RHINO_KOBJ_DEL_ERR;
85 }
86
87 blk_list_head = &queue->blk_obj.blk_list;
88
89 queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
90
91 /* all task blocked on this queue is waken up */
92 while (!is_klist_empty(blk_list_head)) {
93 pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
94 }
95
96 #if (RHINO_CONFIG_KOBJ_LIST > 0)
97 klist_rm(&queue->queue_item);
98 #endif
99
100 ringbuf_reset(&queue->ringbuf);
101
102 RHINO_CRITICAL_EXIT_SCHED();
103
104 return RHINO_SUCCESS;
105 }
106
107 #if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
krhino_queue_dyn_create(kqueue_t ** queue,const name_t * name,size_t msg_num)108 kstat_t krhino_queue_dyn_create(kqueue_t **queue, const name_t *name,
109 size_t msg_num)
110 {
111 kstat_t stat;
112 kqueue_t *queue_obj;
113 void **msg_start;
114
115 NULL_PARA_CHK(queue);
116
117 queue_obj = krhino_mm_alloc(sizeof(kqueue_t));
118 if (queue_obj == NULL) {
119 return RHINO_NO_MEM;
120 }
121
122 msg_start = krhino_mm_alloc(msg_num * sizeof(void *));
123 if (msg_start == NULL) {
124 krhino_mm_free(queue_obj);
125 return RHINO_NO_MEM;
126 }
127
128 stat = queue_create(queue_obj, name, (void **)msg_start, msg_num,
129 K_OBJ_DYN_ALLOC);
130 if (stat != RHINO_SUCCESS) {
131 krhino_mm_free(msg_start);
132 krhino_mm_free(queue_obj);
133 return stat;
134 }
135
136 *queue = queue_obj;
137
138 return stat;
139 }
140
krhino_queue_dyn_del(kqueue_t * queue)141 kstat_t krhino_queue_dyn_del(kqueue_t *queue)
142 {
143 CPSR_ALLOC();
144 klist_t *blk_list_head;
145
146 NULL_PARA_CHK(queue);
147
148 RHINO_CRITICAL_ENTER();
149
150 INTRPT_NESTED_LEVEL_CHK();
151
152 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
153 RHINO_CRITICAL_EXIT();
154 return RHINO_KOBJ_TYPE_ERR;
155 }
156
157 if (queue->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
158 RHINO_CRITICAL_EXIT();
159 return RHINO_KOBJ_DEL_ERR;
160 }
161
162 blk_list_head = &queue->blk_obj.blk_list;
163
164 queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
165
166 /* all task blocked on this queue is waken up */
167 while (!is_klist_empty(blk_list_head)) {
168 pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
169 }
170
171 #if (RHINO_CONFIG_KOBJ_LIST > 0)
172 klist_rm(&queue->queue_item);
173 #endif
174
175 ringbuf_reset(&queue->ringbuf);
176
177 RHINO_CRITICAL_EXIT_SCHED();
178
179 krhino_mm_free(queue->msg_q.queue_start);
180 krhino_mm_free(queue);
181
182 return RHINO_SUCCESS;
183 }
184 #endif
185
msg_send(kqueue_t * p_q,void * p_void,uint8_t opt_wake_all)186 static kstat_t msg_send(kqueue_t *p_q, void *p_void, uint8_t opt_wake_all)
187 {
188 CPSR_ALLOC();
189 klist_t *blk_list_head;
190
191 NULL_PARA_CHK(p_q);
192
193 RHINO_CRITICAL_ENTER();
194
195 if (p_q->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
196 RHINO_CRITICAL_EXIT();
197 return RHINO_KOBJ_TYPE_ERR;
198 }
199
200 if (p_q->msg_q.cur_num >= p_q->msg_q.size) {
201 RHINO_CRITICAL_EXIT();
202 return RHINO_QUEUE_FULL;
203 }
204
205 blk_list_head = &p_q->blk_obj.blk_list;
206
207 /* queue is not full here, if there is no blocked receive task */
208 if (is_klist_empty(blk_list_head)) {
209 p_q->msg_q.cur_num++;
210
211 /* update peak_num for debug */
212 if (p_q->msg_q.cur_num > p_q->msg_q.peak_num) {
213 p_q->msg_q.peak_num = p_q->msg_q.cur_num;
214 }
215
216 ringbuf_queue_push(&p_q->ringbuf, &p_void, sizeof(void *));
217
218 RHINO_CRITICAL_EXIT();
219 return RHINO_SUCCESS;
220 }
221
222 /* wake all the task blocked on this queue */
223 if (opt_wake_all) {
224 while (!is_klist_empty(blk_list_head)) {
225 task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
226 p_void);
227 }
228 } else {
229 task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
230 p_void);
231 }
232
233 RHINO_CRITICAL_EXIT_SCHED();
234
235 return RHINO_SUCCESS;
236 }
237
krhino_queue_back_send(kqueue_t * queue,void * msg)238 kstat_t krhino_queue_back_send(kqueue_t *queue, void *msg)
239 {
240 return msg_send(queue, msg, WAKE_ONE_TASK);
241 }
242
krhino_queue_all_send(kqueue_t * queue,void * msg)243 kstat_t krhino_queue_all_send(kqueue_t *queue, void *msg)
244 {
245 return msg_send(queue, msg, WAKE_ALL_TASK);
246 }
247
krhino_queue_recv(kqueue_t * queue,tick_t ticks,void ** msg)248 kstat_t krhino_queue_recv(kqueue_t *queue, tick_t ticks, void **msg)
249 {
250 CPSR_ALLOC();
251 kstat_t ret;
252 uint8_t cur_cpu_num;
253
254 NULL_PARA_CHK(queue);
255 NULL_PARA_CHK(msg);
256
257 RHINO_CRITICAL_ENTER();
258
259 cur_cpu_num = cpu_cur_get();
260 TASK_CANCEL_CHK(queue);
261
262 if ((g_intrpt_nested_level[cur_cpu_num] > 0u) && (ticks != RHINO_NO_WAIT)) {
263 RHINO_CRITICAL_EXIT();
264 return RHINO_NOT_CALLED_BY_INTRPT;
265 }
266
267 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
268 RHINO_CRITICAL_EXIT();
269 return RHINO_KOBJ_TYPE_ERR;
270 }
271
272 /* if queue has msgs, just receive it */
273 if (queue->msg_q.cur_num > 0u) {
274
275 ringbuf_queue_pop(&queue->ringbuf, msg, NULL);
276
277 queue->msg_q.cur_num--;
278
279 RHINO_CRITICAL_EXIT();
280
281 return RHINO_SUCCESS;
282 }
283
284 if (ticks == RHINO_NO_WAIT) {
285 *msg = NULL;
286 RHINO_CRITICAL_EXIT();
287
288 return RHINO_NO_PEND_WAIT;
289 }
290
291 /* if system is locked, block operation is not allowed */
292 if (g_sched_lock[cur_cpu_num] > 0u) {
293 *msg = NULL;
294 RHINO_CRITICAL_EXIT();
295 return RHINO_SCHED_DISABLE;
296 }
297
298 pend_to_blk_obj(&queue->blk_obj, g_active_task[cur_cpu_num], ticks);
299
300 RHINO_CRITICAL_EXIT_SCHED();
301
302 RHINO_CPU_INTRPT_DISABLE();
303
304 cur_cpu_num = cpu_cur_get();
305
306 ret = pend_state_end_proc(g_active_task[cur_cpu_num], &queue->blk_obj);
307
308 switch (ret) {
309 case RHINO_SUCCESS:
310 *msg = g_active_task[cur_cpu_num]->msg;
311 break;
312 default:
313 *msg = NULL;
314 break;
315 }
316
317 RHINO_CPU_INTRPT_ENABLE();
318
319 return ret;
320 }
321
krhino_queue_is_full(kqueue_t * queue)322 kstat_t krhino_queue_is_full(kqueue_t *queue)
323 {
324 CPSR_ALLOC();
325 kstat_t ret;
326
327 NULL_PARA_CHK(queue);
328
329 RHINO_CRITICAL_ENTER();
330
331 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
332 RHINO_CRITICAL_EXIT();
333 return RHINO_KOBJ_TYPE_ERR;
334 }
335
336 if (queue->msg_q.cur_num >= queue->msg_q.size) {
337 ret = RHINO_QUEUE_FULL;
338 } else {
339 ret = RHINO_QUEUE_NOT_FULL;
340 }
341
342 RHINO_CRITICAL_EXIT();
343
344 return ret;
345 }
346
krhino_queue_flush(kqueue_t * queue)347 kstat_t krhino_queue_flush(kqueue_t *queue)
348 {
349 CPSR_ALLOC();
350
351 NULL_PARA_CHK(queue);
352
353 RHINO_CRITICAL_ENTER();
354
355 INTRPT_NESTED_LEVEL_CHK();
356
357 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
358 RHINO_CRITICAL_EXIT();
359 return RHINO_KOBJ_TYPE_ERR;
360 }
361
362 queue->msg_q.cur_num = 0u;
363 ringbuf_reset(&queue->ringbuf);
364
365 RHINO_CRITICAL_EXIT();
366
367 return RHINO_SUCCESS;
368 }
369
krhino_queue_info_get(kqueue_t * queue,msg_info_t * info)370 kstat_t krhino_queue_info_get(kqueue_t *queue, msg_info_t *info)
371 {
372 CPSR_ALLOC();
373 klist_t *blk_list_head;
374
375 if (queue == NULL) {
376 return RHINO_NULL_PTR;
377 }
378
379 if (info == NULL) {
380 return RHINO_NULL_PTR;
381 }
382
383 NULL_PARA_CHK(queue);
384 NULL_PARA_CHK(info);
385
386 RHINO_CPU_INTRPT_DISABLE();
387
388 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
389 RHINO_CPU_INTRPT_ENABLE();
390 return RHINO_KOBJ_TYPE_ERR;
391 }
392
393 blk_list_head = &queue->blk_obj.blk_list;
394
395 info->msg_q.peak_num = queue->msg_q.peak_num;
396 info->msg_q.cur_num = queue->msg_q.cur_num;
397 info->msg_q.queue_start = queue->msg_q.queue_start;
398 info->msg_q.size = queue->msg_q.size;
399 info->pend_entry = blk_list_head->next;
400
401 RHINO_CPU_INTRPT_ENABLE();
402
403 return RHINO_SUCCESS;
404 }
405 #endif
406
407