Page 1 of 1

vTaskSuspendAll on Core0 halt tasks on Core1 too

Posted: Fri Aug 18, 2017 9:06 am
by andreykorol
As i understood (and see at sources) calling vTaskSuspendAll must suspend tasks just on current core, but it also stops tasks on Core1.
Is this right behavior?

Test example on ESP32 Core Board V2 (ESP-wroom-32) - just keep pressed button and task on core1 stops print.

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_task_wdt.h"

#define BTN_GPIO				0

void Task0(void * data) {
	printf("Task0: start on CORE%u\n", xPortGetCoreID());
	while(1){
		printf("Task0\n");
		fflush(stdout);
		if (!gpio_get_level(BTN_GPIO)) {
			printf("Task0 - call \"vTaskSuspendAll\" on Core%u\n", xPortGetCoreID());
			fflush(stdout);
			vTaskSuspendAll();
			while (!gpio_get_level(BTN_GPIO)) {
				esp_task_wdt_feed();
			}
			xTaskResumeAll();
			printf("Task0 - call \"xTaskResumeAll\" on Core%u\n", xPortGetCoreID());
			fflush(stdout);
		}
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

void Task1(void * data) {
	printf("Task1: start on CORE%u\n", xPortGetCoreID());
	while(1){
		printf("Task1\n");
		fflush(stdout);
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

void app_main()
{
    printf("Hello world!\n");
    fflush(stdout);

	gpio_config_t io_conf;
	io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.mode = GPIO_MODE_INPUT;
	io_conf.pin_bit_mask = (1 << BTN_GPIO);
	io_conf.pull_down_en = 0;
	io_conf.pull_up_en = 0;
	gpio_config(&io_conf);
	
	xTaskCreatePinnedToCore(Task0, "Task0", 2048, NULL, (configMAX_PRIORITIES - 1), NULL, 0);
	xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, (configMAX_PRIORITIES - 1), NULL, 1);
}
But if we will call vTaskSuspendAll on core1 all works as suspected - tasks on core0 keep works

Re: vTaskSuspendAll on Core0 halt tasks on Core1 too

Posted: Fri Aug 18, 2017 11:23 am
by ESP_igrr
I think the story here is that the tick interrupt on Core0 updates the global tick count. vTaskSuspendAll disables tick count updates, and as such, tasks sitting in vTaskDelay on Core1 never start running, because tick count remains constant.

Thanks for pointing out this problem. Maybe we need to improve the logic used for updating the tick count so that the behaviour is at least symmetrical.

At the same time, please note that in real applications it is not advisable to suspend tasks on core 0 for any significant amount of time, as this may affect operation of wifi and tcp/ip stacks.

Re: vTaskSuspendAll on Core0 halt tasks on Core1 too

Posted: Sun Sep 03, 2017 11:58 pm
by meowsqueak
I'm not sure if it's related, but I'm calling vTaskSuspendAll() to ensure no task switch while in the middle of a timing-sensitive GPIO bit-bash routine (followed by xTaskResumeAll()), and the LWIP stack continues to run (so is presumably running on the other CPU) but then asserts:

Code: Select all

    components/freertos/./queue.c:1442 (xQueueGenericReceive)- assert failed!

    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
In my case the GPIO function actually doesn't mind if the other CPU continues to run as long as its own CPU is not task switched. However it seems that the LWIP stack isn't so happy with this arrangement.