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 f1318fe7cb
commit 957505136b
2 changed files with 24 additions and 8 deletions

View File

@@ -95,13 +95,13 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
*/
result = core_id;
#if defined(CONFIG_ESP32_SPIRAM_SUPPORT)
#if (CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S3_SPIRAM_SUPPORT)
if (esp_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 defined(CONFIG_ESP32_SPIRAM_SUPPORT)
#if (CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S3_SPIRAM_SUPPORT)
}
#endif
if(result != other_core_id) {

View File

@@ -73,15 +73,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 xSemaphoreHandle 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);
@@ -89,8 +89,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();
@@ -106,15 +107,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();
@@ -136,8 +139,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