初级会员
- 积分
- 85
- 金钱
- 85
- 注册时间
- 2017-3-14
- 在线时间
- 18 小时
|
发表于 2017-3-14 20:10:50
|
显示全部楼层
本帖最后由 yuer19900712 于 2017-3-14 20:13 编辑
这个代码已经找到了,举一个简单例子。比如释放信号量的过程
[mw_shl_code=c,true]#definexSemaphoreGive( xSemaphore ) \
xQueueGenericSend( \
( QueueHandle_t ) ( xSemaphore ), \
NULL, \
semGIVE_BLOCK_TIME, \
queueSEND_TO_BACK ) [/mw_shl_code]
对应的是使用了消息队列的函数
源码如下
[mw_shl_code=c,true]BaseType_t xQueueGenericSend(
QueueHandle_t xQueue,
const voidvoid * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
{
BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
TimeOut_t xTimeOut;
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
for( ;; )
{
taskENTER_CRITICAL();
{
/* 队列还有空闲?正在运行的任务一定要比等待访问队列的任务优先级高.如果使用覆盖式入队,则不需要关注队列是否满*/
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{
/*完成数据拷贝工作,分为从队列尾入队,从队列首入队和覆盖式入队*/
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* 如果有任务在此等待队列数据到来,则将该任务解除阻塞*/
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{
/*有任务因等待出队而阻塞,则将任务从队列等待接收列表中删除,然后加入到就绪列表*/
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* 解除阻塞的任务有更高的优先级,则当前任务要让出CPU,因此触发一个上下文切换.又因为现在还在临界区,要等退出临界区后,才会执行上下文切换.*/
queueYIELD_IF_USING_PREEMPTION();
}
}
else if( xYieldRequired != pdFALSE )
{
/* 这个分支处理特殊情况*/
queueYIELD_IF_USING_PREEMPTION();
}
taskEXIT_CRITICAL();
return pdPASS;
}
else
{
if( xTicksToWait == ( TickType_t ) 0 )
{
/* 如果队列满并且没有设置超时,则直接退出 */
taskEXIT_CRITICAL();
/* 返回队列满错误码 */
return errQUEUE_FULL;
}
else if( xEntryTimeSet == pdFALSE )
{
/* 队列满并且规定了阻塞时间,因此需要配置超时结构体对象 */
vTaskSetTimeOutState( &xTimeOut );
xEntryTimeSet = pdTRUE;
}
}
}
taskEXIT_CRITICAL();
/* 退出临界区,至此,中断和其它任务可以向这个队列执行入队(投递)或出队(读取)操作.因为队列满,任务无法入队,下面的代码将当前任务将阻塞在这个队列上,在这段代码执行过程中我们需要挂起调度器,防止其它任务操作队列事件列表;挂起调度器虽然可以禁止其它任务操作这个队列,但并不能阻止中断服务程序操作这个队列,因此还需要将队列上锁,防止中断程序读取队列后,使阻塞在出队操作其它任务解除阻塞,执行上下文切换(因为调度器挂起后,不允许执行上下文切换) */
vTaskSuspendAll();
prvLockQueue( pxQueue );
/* 查看任务的超时时间是否到期 */
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{
if( prvIsQueueFull( pxQueue ) != pdFALSE )
{
/*超时时间未到期,并且队列仍然满*/
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
/* 解除队列锁,如果有任务要解除阻塞,则将任务移到挂起就绪列表中(因为当前调度器挂起,所以不能移到就绪列表)*/
prvUnlockQueue( pxQueue );
/* 恢复调度器,将任务从挂起就绪列表移到就绪列表中*/
if( xTaskResumeAll() == pdFALSE )
{
portYIELD_WITHIN_API();
}
}
else
{
/* 队列有空闲,重试 */
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
}
}
else
{
/* 超时时间到期,返回队列满错误码*/
prvUnlockQueue( pxQueue );
( void ) xTaskResumeAll();
traceQUEUE_SEND_FAILED( pxQueue );
return errQUEUE_FULL;
}
}
}[/mw_shl_code]
在26行的函数是个关键,一直goto,找到最终的代码,会看见就绪最高优先级任务被修改了。回家再贴上详细的。下班 |
|