Engineer's Asylum

Problem with taskYIELD() and xQueueReceive()

I have two tasks in my program, manager task and employee task. The manager task has the highest priority and the employee has the lowest priority. But the manager task blocks when taskYIELD() and execution jumps to employee task. The taskYIELD() should place the manager task itself in the ready list if there is no equal or higher priority task? Right? But it blocks instead. Why?

In the employee task, as the control reaches the xQueueReceive() API, the manager task unblocks and the execution jumps to the manager task.

void manager_task(void *params) {
 
  while(1) {
 
	int ticket_id = rand();
 
	if(xQueueSendToFront(ticket_queue_handle, &ticket_id, portMAX_DELAY) == pdTRUE) { 
 
        sprintf(user_msg, "\r\nIssued Ticket ID: %d  ", ticket_id);
	    print_msg(user_msg);
 
	 }
 
        taskYIELD(); --->Blocks even though manager task has high priority.
   }
}
 
void employee_task(void *params) {
 
	int ticket_id;
 
while(1) {
 
	if(xQueueReceive(ticket_queue_handle, &ticket_id, 0) == pdTRUE) {
            |
            |--------> Manager task Ready and execution jumps to manager.
 
        sprintf(user_msg, "Working on ticket ID: %d", ticket_id);
	    print_msg(user_msg);
	    vTaskDelay(5);
 
	 }
   }
}

taskYIELD() does not block any task. It only does a manual context switch, and switching happens if an equal or higher priority task is ready. If not, the control will come back to the same task. It is the kernel APIs that block a task (e.g. xQueueReceive).

2 Likes

Agreed. xQueueSend will unblock any tasking waiting for the queue to receive and xQueueReceive will unblock any tasking waiting for the queue to send. Is that correct? If yes, one cannot use these two API with two task having unequal priorities. Correct?

BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

The xQueueReceive() API will block the task until xTicksToWait number of ticks, waiting for the data to be received to a void pointer variable. Setting xTicksToWait to 0 will cause the function to return immediately. Specifying the block time as portMAX_DELAY will cause the task to block indefinitely.

BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

The xQueueSend() API sends data to the queue. The API will block the task for xTicksToWait number of ticks for space to become available on the queue. If there is already data in the queue, the API will block the task. The call will return immediately if the queue is full and xTicksToWait is set to 0. Specifying the block time as portMAX_DELAY will cause the task to block indefinitely.

In both the APIs the blocking time depends on the parameter xTicksToWait.

1 Like

Thank you. You have well explained the concept. I have forgot to consider the xTicksToWait parameter.

1 Like