spinlock: fixed spinlocks not working on S3 if placed in PSRAM

The compare and set instruction (S32C1I) cannot be used when
lock is not in internal memory.

Closes https://github.com/espressif/esp-idf/issues/9120
This commit is contained in:
Marius Vikhammer 2022-06-08 14:18:03 +08:00
parent e6c5badfe2
commit 486316f222
2 changed files with 25 additions and 9 deletions

View File

@ -37,7 +37,7 @@ typedef struct {
NEED_VOLATILE_MUX uint32_t count;
}spinlock_t;
#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)
#if (CONFIG_SPIRAM)
/**
* @brief Check if the pointer is on external ram
* @param p pointer
@ -108,13 +108,13 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
*/
result = core_id;
#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)
#if (CONFIG_SPIRAM)
if (spinlock_ptr_external_ram(lock)) {
compare_and_set_extram(&lock->owner, SPINLOCK_FREE, &result);
} else {
#endif
compare_and_set_native(&lock->owner, SPINLOCK_FREE, &result);
#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32)
#if (CONFIG_SPIRAM)
}
#endif
if(result != other_core_id) {

View File

@ -78,15 +78,15 @@ TEST_CASE("portMUX recursive locks (no contention)", "[freertos]")
#if portNUM_PROCESSORS == 2
static volatile int shared_value;
static portMUX_TYPE shared_mux;
static portMUX_TYPE *shared_mux;
static SemaphoreHandle_t done_sem;
static void task_shared_value_increment(void *ignore)
{
for (int i = 0; i < REPEAT_OPS; i++) {
portENTER_CRITICAL(&shared_mux);
portENTER_CRITICAL(shared_mux);
shared_value++;
portEXIT_CRITICAL(&shared_mux);
portEXIT_CRITICAL(shared_mux);
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
@ -94,8 +94,9 @@ static void task_shared_value_increment(void *ignore)
TEST_CASE("portMUX cross-core locking", "[freertos]")
{
shared_mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
done_sem = xSemaphoreCreateCounting(2, 0);
portMUX_INITIALIZE(&shared_mux);
portMUX_INITIALIZE(shared_mux);
shared_value = 0;
BENCHMARK_START();
@ -111,15 +112,17 @@ TEST_CASE("portMUX cross-core locking", "[freertos]")
BENCHMARK_END("cross-core incrementing");
vSemaphoreDelete(done_sem);
free(shared_mux);
TEST_ASSERT_EQUAL_INT(REPEAT_OPS * 2, shared_value);
}
TEST_CASE("portMUX high contention", "[freertos]")
void portmux_high_contention_test(uint32_t lock_malloc_caps)
{
const int TOTAL_TASKS = 8; /* half on each core */
shared_mux = heap_caps_malloc(sizeof(portMUX_TYPE), lock_malloc_caps);
done_sem = xSemaphoreCreateCounting(TOTAL_TASKS, 0);
portMUX_INITIALIZE(&shared_mux);
portMUX_INITIALIZE(shared_mux);
shared_value = 0;
BENCHMARK_START();
@ -141,8 +144,21 @@ TEST_CASE("portMUX high contention", "[freertos]")
BENCHMARK_END("cross-core high contention");
vSemaphoreDelete(done_sem);
free(shared_mux);
TEST_ASSERT_EQUAL_INT(REPEAT_OPS * TOTAL_TASKS, shared_value);
}
TEST_CASE("portMUX high contention", "[freertos]")
{
portmux_high_contention_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
}
#if CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC
TEST_CASE("portMUX high contention, PSRAM", "[freertos]")
{
portmux_high_contention_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
}
#endif// CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC
#endif // portNUM_PROCESSORS == 2