虽然相比较之前的互斥函数,消息队列的初始化内容好像多一些。但是大家如果对循环队列的知识比较了解的话,其实也不是很复杂的。我们看到,函数除了对通用阻塞结构进行初始化之外,就是对这些循环队列进行初始化。接着,我们就可以看看消息发送函数是怎么样的,
static RAW_U16 internal_msg_post(RAW_QUEUE *p_q, RAW_VOID *p_void, RAW_U8 opt_send_method, RAW_U8 opt_wake_all, RAW_U32 wait_option) { RAW_U16 error_status; LIST *block_list_head; RAW_U8 block_way; RAW_SR_ALLOC(); #if (RAW_QUEUE_FUNCTION_CHECK > 0) if (raw_int_nesting) { if (wait_option != RAW_NO_WAIT) { return RAW_NOT_CALLED_BY_ISR; } } if (p_q == 0) { return RAW_NULL_OBJECT; } if (p_void == 0) { return RAW_NULL_POINTER; } #endif block_list_head = &p_q->common_block_obj.block_list; RAW_CRITICAL_ENTER(); /*queue is full condition, there should be no received task blocked on queue object!*/ if (p_q->msg_q.current_numbers >= p_q->msg_q.size) { if (wait_option == RAW_NO_WAIT) { RAW_CRITICAL_EXIT(); return RAW_MSG_MAX; } else { /*system is locked so task can not be blocked just return immediately*/ if (raw_sched_lock) { RAW_CRITICAL_EXIT(); return RAW_SCHED_DISABLE; } /*queue is full and SEND_TO_FRONT method is not allowd*/ if (opt_send_method == SEND_TO_FRONT) { RAW_CRITICAL_EXIT(); return RAW_QUEUE_FULL_OPT_ERROR; } p_q->msg_q.blocked_send_task_numbers++; raw_task_active->msg = p_void; block_way = p_q->common_block_obj.block_way; p_q->common_block_obj.block_way = RAW_BLOCKED_WAY_FIFO; /*there should be no blocked received task beacuse msg exits*/ raw_pend_object(&p_q->common_block_obj, raw_task_active, wait_option); p_q->common_block_obj.block_way = block_way; RAW_CRITICAL_EXIT(); raw_sched(); error_status = block_state_post_process(raw_task_active, 0); return error_status; } } /*Queue is not full here, there should be no blocked send task*/ /*If there is no blocked receive task*/ if (is_list_empty(block_list_head)) { p_q->msg_q.current_numbers++; /* Update the nbr of entries in the queue */ 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 { 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(); 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(list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void); } p_q->msg_q.blocked_receive_task_numbers = 0; } /*wake hignhest priority task blocked on this queue and send msg to it*/ else { wake_send_msg(list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void); p_q->msg_q.blocked_receive_task_numbers--; } RAW_CRITICAL_EXIT(); raw_sched(); return RAW_SUCCESS; } |
这里消息发送函数稍显冗长,这主要是因为消息发送的情况比较复杂,方方面面考虑的情况比较多。但是整个函数处理的逻辑还是比较清晰的,只要有耐心,慢慢读下去还是没有什么问题。这里不妨和大家一起看一下消息发送函数是怎么实现的,
(1)检验参数合法性,注意在中断下调用这个函数时,必须是RAW_NO_WAIT的选项,中断毕竟是不好调度的;
(2) 处理消息已满的情况,
a)如果线程不想等待,函数返回;
b)如果禁止调度,函数返回;
c)消息存储到线程的msg里面,线程把自己pend到等待队列中;
d)调用系统调度函数,等待再次被调度的机会,函数返回。