1 Star 0 Fork 21

forest_555/raw-os

forked from jorya_txj/raw-os 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
raw_queue.c 20.74 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
/*
raw os - Copyright (C) Lingjun Chen(jorya_txj).
This file is part of raw os.
raw os is free software; you can redistribute it it under the terms of the
GNU General Public License as published by the Free Software Foundation;
either version 3 of the License, or (at your option) any later version.
raw os is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. if not, write email to jorya.txj@gmail.com
---
A special exception to the LGPL can be applied should you wish to distribute
a combined work that includes raw os, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/* 2012-4 Created by jorya_txj
* xxxxxx please added here
*/
#include <raw_api.h>
#if (CONFIG_RAW_QUEUE > 0)
/*
************************************************************************************************************************
* Create a queue
*
* Description: This function is called to create a queue.
*
* Arguments :p_q is the address of queue object want to be initialized
* -----
* name_ptr is the queue object name
* -----
* msg_start is the address of pointer array.
* ------
* number is the number of elements of the queue.
* Returns
* RAW_SUCCESS: raw os return success
* Note(s)
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_create(RAW_QUEUE *p_q, RAW_U8 *p_name, void **msg_start, MSG_SIZE_TYPE number)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (msg_start == 0) {
return RAW_NULL_POINTER;
}
if (number == 0u) {
return RAW_ZERO_NUMBER;
}
#endif
/*init the queue blocked list*/
list_init(&p_q->common_block_obj.block_list);
p_q->common_block_obj.name = p_name;
p_q->common_block_obj.block_way = RAW_BLOCKED_WAY_PRIO;
p_q->msg_q.queue_start = msg_start; /* Initialize the queue */
p_q->msg_q.queue_end = &msg_start[number];
p_q->msg_q.write = msg_start;
p_q->msg_q.read = msg_start;
p_q->msg_q.size = number;
p_q->msg_q.current_numbers = 0u;
p_q->msg_q.peak_numbers = 0u;
p_q->queue_send_notify = 0;
p_q->queue_full_callback = 0;
list_insert(&(raw_task_debug.queue_head), &p_q->queue_debug_list);
p_q->common_block_obj.object_type = RAW_QUEUE_OBJ_TYPE;
TRACE_QUEUE_CREATE(raw_task_active, p_q);
return RAW_SUCCESS;
}
#if (CONFIG_RAW_QUEUE_BLOCK_WAY_SET > 0)
RAW_OS_ERROR raw_queue_block_way_set(RAW_QUEUE *p_q, RAW_BLOCKED_WAY block_way)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
#endif
p_q->common_block_obj.block_way = block_way;
return RAW_SUCCESS;
}
#endif
RAW_OS_ERROR raw_queue_full_register(RAW_QUEUE *p_q, QUEUE_FULL_CALLBACK callback_full)
{
RAW_SR_ALLOC();
if (raw_int_nesting) {
return RAW_NOT_CALLED_BY_ISR;
}
RAW_CPU_DISABLE();
p_q->queue_full_callback = callback_full;
RAW_CPU_ENABLE();
return RAW_SUCCESS;
}
RAW_OS_ERROR msg_post(RAW_QUEUE *p_q, void *p_void, RAW_U8 opt_send_method, RAW_U8 opt_wake_all)
{
LIST *block_list_head;
RAW_SR_ALLOC();
/*This is only needed when system zero interrupt feature is enabled*/
#if (CONFIG_INTERRUPT_PRIORITY_CHECK > 0)
port_interrupt_priority_check();
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
block_list_head = &p_q->common_block_obj.block_list;
if (p_q->msg_q.current_numbers >= p_q->msg_q.size) {
RAW_CRITICAL_EXIT();
TRACE_QUEUE_MSG_MAX(raw_task_active, p_q, p_void, opt_send_method);
if (p_q->queue_full_callback) {
p_q->queue_full_callback(p_q, p_void);
}
return RAW_MSG_MAX;
}
/*Queue is not full here, if there is no blocked receive task*/
if (is_list_empty(block_list_head)) {
p_q->msg_q.current_numbers++;
/*update peak_numbers for debug*/
if (p_q->msg_q.current_numbers > p_q->msg_q.peak_numbers) {
p_q->msg_q.peak_numbers = p_q->msg_q.current_numbers;
}
if (opt_send_method == SEND_TO_END) {
*p_q->msg_q.write++ = p_void;
if (p_q->msg_q.write == p_q->msg_q.queue_end) {
p_q->msg_q.write = p_q->msg_q.queue_start;
}
}
else {
/* Wrap read pointer to end if we are at the 1st queue entry */
if (p_q->msg_q.read == p_q->msg_q.queue_start) {
p_q->msg_q.read = p_q->msg_q.queue_end;
}
p_q->msg_q.read--;
*p_q->msg_q.read = p_void; /* Insert message into queue */
}
RAW_CRITICAL_EXIT();
/*if queue is registered with notify function just call it*/
if (p_q->queue_send_notify) {
p_q->queue_send_notify(p_q);
}
TRACE_QUEUE_MSG_POST(raw_task_active, p_q, p_void, opt_send_method);
return RAW_SUCCESS;
}
/*wake all the task blocked on this queue*/
if (opt_wake_all) {
while (!is_list_empty(block_list_head)) {
wake_send_msg(raw_list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void);
TRACE_QUEUE_WAKE_TASK(raw_task_active, raw_list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void, opt_wake_all);
}
}
/*wake hignhest priority task blocked on this queue and send msg to it*/
else {
wake_send_msg(raw_list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void);
TRACE_QUEUE_WAKE_TASK(raw_task_active, raw_list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void, opt_wake_all);
}
RAW_CRITICAL_EXIT();
raw_sched();
return RAW_SUCCESS;
}
/*
************************************************************************************************************************
* Post a msg to the queue front
*
* Description: This function is called to post a msg to the queue front and implement LIFO.
*
* Arguments :p_q is the address of the queue object
* -----
* p_void is the address of the msg
* -----
*
*
* Returns
* RAW_SUCCESS: raw os return success
* RAW_MSG_MAX:queue is full
*
*
*
* Note(s)
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_front_post(RAW_QUEUE *p_q, void *p_void)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (p_void == 0) {
return RAW_NULL_POINTER;
}
#endif
TRACE_QUEUE_FP_TIME_RECORD(p_q, p_void);
return msg_post(p_q, p_void,SEND_TO_FRONT, WAKE_ONE_QUEUE);
}
/*
************************************************************************************************************************
* Post a msg to the queue end
*
* Description: This function is called to post a msg to the queue end and implement FIFO.
*
* Arguments :p_q is the address of the queue object
* -----
* p_void is the address of the msg
* -----
*
*
* Returns
* RAW_SUCCESS: raw os return success
* RAW_MSG_MAX:queue is full
*
*
*
* Note(s)
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_end_post(RAW_QUEUE *p_q, void *p_void)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (p_void == 0) {
return RAW_NULL_POINTER;
}
#endif
TRACE_QUEUE_EP_TIME_RECORD(p_q, p_void);
return msg_post(p_q, p_void, SEND_TO_END, WAKE_ONE_QUEUE);
}
/*
************************************************************************************************************************
* Notify function call back
*
* Description: This function is called to post a msg to the queue end and implement FIFO.
*
* Arguments :p_q is the address of the queue object
* -----
* p_void is the address of the msg
* -----
*
*
* Returns
* RAW_SUCCESS: raw os return success
* RAW_MSG_MAX:queue is full
*
*
*
* Note(s)
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_post_notify(RAW_QUEUE *p_q, void *p_void)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (p_void == 0) {
return RAW_NULL_POINTER;
}
#endif
return msg_post(p_q, p_void, SEND_TO_END, WAKE_ONE_QUEUE);
}
/*
************************************************************************************************************************
* Post a msg to the all the task waiting for on this queue
*
* Description: This function is called to post a msg to the queue end and implement FIFO or LIFO as opt specified.
*
* Arguments :p_q is the address of the queue object
* -----
* p_void is the address of the msg
* -----
* opt: the opt option is:
* SEND_TO_END implement FIFO
* SEND_TO_FRONTimplement LIFO
* -----
*
*
* Returns RAW_SUCCESS: raw os return success
* RAW_MSG_MAX:queue is full
*
* Note(s) THis function will wake all the task waiting for this queue other than one!
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_all_post(RAW_QUEUE *p_q, void *p_void, RAW_U8 opt)
{
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (p_void == 0) {
return RAW_NULL_POINTER;
}
#endif
TRACE_QUEUE_AP_TIME_RECORD(p_q, p_void, opt);
return msg_post(p_q, p_void, opt, WAKE_ALL_QUEUE);
}
/*
************************************************************************************************************************
* Register notify function to queue
*
* Description: This function is called to Register notify function to queue.
*
* Arguments :p_q is the address of the queue object
* -----
* notify_function is the function to be called whennever send queue data to it.
* -----
*
*
* Returns
* RAW_SUCCESS: raw os return success
*
* Note(s) This function is normally used to implement pending on multi object function.
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_send_notify(RAW_QUEUE *p_q, QUEUE_SEND_NOTIFY notify_function)
{
RAW_SR_ALLOC();
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (raw_int_nesting) {
return RAW_NOT_CALLED_BY_ISR;
}
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
p_q->queue_send_notify = notify_function;
RAW_CRITICAL_EXIT();
return RAW_SUCCESS;
}
/*
************************************************************************************************************************
* Receive a msg
*
* Description: This function is called to receive a msg
*
* Arguments :p_q is the address of the queue object
* -----
* msg is the address of a point, and this pointer contains address of the msg.
* -----
* wait_option: is how the service behaves if the msg queue is full.
* The wait options are
* defined as follows:
* RAW_NO_WAIT (0x00000000)
* RAW_WAIT_FOREVER (0xFFFFFFFF)
* timeout value (0x00000001
* through
* 0xFFFFFFFE)
*
* Returns
* RAW_SUCCESS: raw os return success
* RAW_BLOCK_DEL: if this queue is deleted.
* RAW_BLOCK_TIMEOUT: queue is still full during waiting time when sending msg.
* RAW_BLOCK_ABORT:queue is aborted during waiting time when sending msg.
* Note(s) if no msg received then msg will get null pointer(0). ISR can call this function if only wait_option equal RAW_NO_WAIT.
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_receive(RAW_QUEUE *p_q, RAW_TICK_TYPE wait_option, void **msg)
{
void *pmsg;
RAW_OS_ERROR block_result;
RAW_SR_ALLOC();
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (raw_int_nesting && (wait_option != RAW_NO_WAIT)) {
return RAW_NOT_CALLED_BY_ISR;
}
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (msg == 0) {
return RAW_NULL_POINTER;
}
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
/*if queue has msgs, just receive it*/
if (p_q->msg_q.current_numbers) {
pmsg = *p_q->msg_q.read++;
if (p_q->msg_q.read == p_q->msg_q.queue_end) {
/*wrap around to start*/
p_q->msg_q.read = p_q->msg_q.queue_start;
}
*msg = pmsg;
p_q->msg_q.current_numbers--;
RAW_CRITICAL_EXIT();
TRACE_QUEUE_GET_MSG(raw_task_active, p_q, wait_option, *msg);
return RAW_SUCCESS;
}
if (wait_option == RAW_NO_WAIT) {
*msg = (void *)0;
RAW_CRITICAL_EXIT();
return RAW_NO_PEND_WAIT;
}
/*if system is locked, block operation is not allowed*/
SYSTEM_LOCK_PROCESS_QUEUE();
raw_pend_object((RAW_COMMON_BLOCK_OBJECT *)p_q, raw_task_active, wait_option);
RAW_CRITICAL_EXIT();
TRACE_QUEUE_GET_BLOCK(raw_task_active, p_q, wait_option);
raw_sched();
USER_CPU_INT_DISABLE();
block_result = block_state_post_process(raw_task_active);
switch (block_result) {
case RAW_SUCCESS:
*msg = raw_task_active->msg;
break;
default:
*msg = (void *)0;
break;
}
USER_CPU_INT_ENABLE();
return block_result;
}
/*
************************************************************************************************************************
* Check whether queue obj is full or not
*
* Description: This function is called to Check whether queue obj is full or not.
*
* Arguments :p_q is the address of the queue object
* -----
*
*
* Returns
* RAW_QUEUE_CHECK_FULL: queue obj is full
* RAW_QUEUE_CHECK_NOT_FULL: queue obj is not full
*
*Note(s)
*
*
************************************************************************************************************************
*/
RAW_OS_ERROR raw_queue_full_check(RAW_QUEUE *p_q)
{
RAW_SR_ALLOC();
RAW_OS_ERROR full_check_ret;
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
if (p_q->msg_q.current_numbers >= p_q->msg_q.size) {
full_check_ret = RAW_QUEUE_CHECK_FULL;
}
else {
full_check_ret = RAW_QUEUE_CHECK_NOT_FULL;
}
RAW_CRITICAL_EXIT();
return full_check_ret;
}
/*
************************************************************************************************************************
* Flush a queue
*
* Description: This service deletes all messages stored in the specified message queue.
* If the queue is empty, this service does nothing.
*
* Arguments :p_q is the address of the queue object
* -----
*
*
*Returns RAW_SUCCESS: raw os return success
*
*
* Note(s) Be careful This api will probably cause memory leak.
*
*
************************************************************************************************************************
*/
#if (CONFIG_RAW_QUEUE_FLUSH > 0)
RAW_OS_ERROR raw_queue_flush(RAW_QUEUE *p_q)
{
RAW_SR_ALLOC();
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (raw_int_nesting) {
return RAW_NOT_CALLED_BY_ISR;
}
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
/*Reset read and write pointer to init position*/
p_q->msg_q.write = p_q->msg_q.queue_start;
p_q->msg_q.read = p_q->msg_q.queue_start;
p_q->msg_q.current_numbers = 0u;
RAW_CRITICAL_EXIT();
TRACE_QUEUE_FLUSH(raw_task_active, p_q);
return RAW_SUCCESS;
}
#endif
/*
************************************************************************************************************************
* Delete a queue
*
* Description: This function is called to delete a queue.
*
* Arguments :p_q is the address of this queue object
* -----
* All blocked task will be waken up and return RAW_BLOCK_DEL.
*
* Returns
* RAW_SUCCESS: raw os return success
* Note(s)
*
*
************************************************************************************************************************
*/
#if (CONFIG_RAW_QUEUE_DELETE > 0)
RAW_OS_ERROR raw_queue_delete(RAW_QUEUE *p_q)
{
LIST *block_list_head;
RAW_SR_ALLOC();
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (raw_int_nesting) {
return RAW_NOT_CALLED_BY_ISR;
}
#endif
RAW_CRITICAL_ENTER();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
RAW_CRITICAL_EXIT();
return RAW_ERROR_OBJECT_TYPE;
}
block_list_head = &p_q->common_block_obj.block_list;
p_q->common_block_obj.object_type = RAW_OBJ_TYPE_NONE;
/*All task blocked on this queue is waken up*/
while (!is_list_empty(block_list_head)) {
delete_pend_obj(raw_list_entry(block_list_head->next, RAW_TASK_OBJ, task_list));
}
list_delete(&p_q->queue_debug_list);
RAW_CRITICAL_EXIT();
TRACE_QUEUE_DELETE(raw_task_active, p_q);
raw_sched();
return RAW_SUCCESS;
}
#endif
/*
************************************************************************************************************************
* Get queue information
*
* Description: This function is called to get information form queue.
*
* Arguments :p_q is the address of this queue object
* -----
* msg_information is the address of RAW_MSG_INFO, which will be filled queue information
* -----
*
*
* Returns
* RAW_SUCCESS: raw os return success
*
* Note(s) Commonly for debug purpose
*
*
************************************************************************************************************************
*/
#if (CONFIG_RAW_QUEUE_GET_INFORMATION > 0)
RAW_OS_ERROR raw_queue_get_information(RAW_QUEUE *p_q, RAW_MSG_INFO *msg_information)
{
LIST *block_list_head;
RAW_SR_ALLOC();
#if (RAW_QUEUE_FUNCTION_CHECK > 0)
if (p_q == 0) {
return RAW_NULL_OBJECT;
}
if (msg_information == 0) {
return RAW_NULL_POINTER;
}
#endif
USER_CPU_INT_DISABLE();
if (p_q->common_block_obj.object_type != RAW_QUEUE_OBJ_TYPE) {
USER_CPU_INT_ENABLE();
return RAW_ERROR_OBJECT_TYPE;
}
block_list_head = &p_q->common_block_obj.block_list;
msg_information->msg_q.peak_numbers = p_q->msg_q.peak_numbers;
msg_information->msg_q.current_numbers = p_q->msg_q.current_numbers;
msg_information->msg_q.queue_start = p_q->msg_q.queue_start;
msg_information->msg_q.queue_end = p_q->msg_q.queue_end;
msg_information->msg_q.read = p_q->msg_q.read;
msg_information->msg_q.write = p_q->msg_q.write;
msg_information->msg_q.size = p_q->msg_q.size;
msg_information->suspend_entry = block_list_head->next;
USER_CPU_INT_ENABLE();
return RAW_SUCCESS;
}
#endif
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/forest555/raw-os.git
git@gitee.com:forest555/raw-os.git
forest555
raw-os
raw-os
master

搜索帮助