diff --git a/components/newlib/platform_include/pthread.h b/components/newlib/platform_include/pthread.h index d814db9859a..9b591202c61 100644 --- a/components/newlib/platform_include/pthread.h +++ b/components/newlib/platform_include/pthread.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,18 @@ int pthread_condattr_getclock(const pthread_condattr_t * attr, clockid_t * clock int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id); +/* Dynamic Thread Scheduling Parameters Access */ +int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param); + +int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param); + +/* Set Scheduling Priority of a Thread */ +int pthread_setschedprio(pthread_t thread, int prio); + +int sched_get_priority_min(int policy); + +int sched_get_priority_max(int policy); + #ifdef __cplusplus } #endif diff --git a/components/pthread/pthread.c b/components/pthread/pthread.c index 0e73fe86bf1..69f0c440f0d 100644 --- a/components/pthread/pthread.c +++ b/components/pthread/pthread.c @@ -916,6 +916,81 @@ int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) return EINVAL; } +int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) +{ + int ret; + if (!policy || !param) { + return EINVAL; + } + + _lock_acquire(&s_threads_lock); + TaskHandle_t handle = pthread_find_handle(thread); + if (!handle) { + ret = ESRCH; + } else { + *policy = SCHED_OTHER; + param->sched_priority = uxTaskPriorityGet(handle); + ret = 0; + } + _lock_release(&s_threads_lock); + + return ret; +} + +static int set_prio(pthread_t thread, int policy, int prio) +{ + int ret; + if (prio < sched_get_priority_min(policy) || sched_get_priority_max(policy) < prio) { + return EINVAL; + } + + _lock_acquire(&s_threads_lock); + TaskHandle_t handle = pthread_find_handle(thread); + if (!handle) { + ret = ESRCH; + } else { + vTaskPrioritySet(handle, prio); + ret = 0; + } + _lock_release(&s_threads_lock); + + return ret; +} + +int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) +{ + // the policy does not change anything for the FreeRTOS kernel, ignore it. + int ret; + if (!param) { + return EINVAL; + } + + ret = set_prio(thread, policy, param->sched_priority); + + return ret; +} + +int pthread_setschedprio(pthread_t thread, int prio) +{ + // the policy does not change anything for the FreeRTOS kernel, ignore it. + int policy = SCHED_OTHER; + return set_prio(thread, policy, prio); +} + +int sched_get_priority_min(int policy) +{ + // the policy does not change anything for the FreeRTOS kernel, ignore it. + (void) policy; + return tskIDLE_PRIORITY; +} + +int sched_get_priority_max(int policy) +{ + // the policy does not change anything for the FreeRTOS kernel, ignore it. + (void) policy; + return configMAX_PRIORITIES - 1; +} + /* Hook function to force linking this file */ void pthread_include_pthread_impl(void) { diff --git a/components/pthread/test_apps/pthread_unity_tests/main/test_pthread.c b/components/pthread/test_apps/pthread_unity_tests/main/test_pthread.c index 551158bda85..1f2232c3bad 100644 --- a/components/pthread/test_apps/pthread_unity_tests/main/test_pthread.c +++ b/components/pthread/test_apps/pthread_unity_tests/main/test_pthread.c @@ -298,3 +298,46 @@ TEST_CASE("pthread mutex trylock timedlock", "[pthread]") pthread_mutex_destroy(&mutex); } } + +static volatile bool finish_test; + +static void *test_thread(void * arg) +{ + while (!finish_test) { + vTaskDelay(1); + } + printf("Thread 0x%"PRIx32" exiting\n", pthread_self()); + return NULL; +} + +TEST_CASE("pthread set and get sched param", "[pthread]") +{ + finish_test = false; + pthread_t thread; + TEST_ASSERT_EQUAL_INT(0, pthread_create(&thread, NULL, test_thread, NULL)); + + int policy; + struct sched_param param; + TEST_ASSERT_EQUAL_INT(0, pthread_getschedparam(thread, &policy, ¶m)); + int orig_prio = param.sched_priority; + printf("Origin Priority: %d\n", param.sched_priority); + printf("Policy: %d (2=SCHED_RR)\n", policy); + + param.sched_priority += 1; + TEST_ASSERT_EQUAL_INT(0, pthread_setschedparam(thread, policy, ¶m)); + param.sched_priority += 1; + TEST_ASSERT_EQUAL_INT(0, pthread_setschedprio(thread, param.sched_priority)); + + TEST_ASSERT_EQUAL_INT(0, pthread_getschedparam(thread, &policy, ¶m)); + printf("Priority: %d + 2 = %d\n", orig_prio, param.sched_priority); + TEST_ASSERT_EQUAL_INT(orig_prio + 2, param.sched_priority); + + // return priority back + TEST_ASSERT_EQUAL_INT(0, pthread_setschedprio(thread, orig_prio)); + TEST_ASSERT_EQUAL_INT(0, pthread_getschedparam(thread, &policy, ¶m)); + TEST_ASSERT_EQUAL_INT(orig_prio, param.sched_priority); + printf("Return Priority back to %d, current is %d\n", orig_prio, param.sched_priority); + // Wait for the thread to finish 100ms sleep + finish_test = true; + TEST_ASSERT_EQUAL_INT(0, pthread_join(thread, NULL)); +}