diff --git a/arch/posix/include/posix_cheats.h b/arch/posix/include/posix_cheats.h index 88a68b9fd490c1d..770dab9aac605a3 100644 --- a/arch/posix/include/posix_cheats.h +++ b/arch/posix/include/posix_cheats.h @@ -151,6 +151,8 @@ extern "C" int _posix_zephyr_main(void); #define sched_yield(...) zap_sched_yield(__VA_ARGS__) #define sched_get_priority_min(...) zap_sched_get_priority_min(__VA_ARGS__) #define sched_get_priority_max(...) zap_sched_get_priority_max(__VA_ARGS__) +#define sched_getparam(...) zap_sched_getparam(__VA_ARGS__) +#define sched_getscheduler(...) zap_sched_getscheduler(__VA_ARGS__) /* Sleep */ #define sleep(...) zap_sleep(__VA_ARGS__) diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 893754f647d1381..41db3d66e6dace8 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -446,8 +446,8 @@ _POSIX_PRIORITY_SCHEDULING sched_get_priority_max(),yes sched_get_priority_min(),yes - sched_getparam(), - sched_getscheduler(), + sched_getparam(),yes + sched_getscheduler(),yes sched_rr_get_interval(), sched_setparam(), sched_setscheduler(), diff --git a/include/zephyr/posix/sched.h b/include/zephyr/posix/sched.h index 10cfc666c66d206..b7431fc3342247e 100644 --- a/include/zephyr/posix/sched.h +++ b/include/zephyr/posix/sched.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2018-2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,8 @@ #include +#include "posix_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -46,6 +48,9 @@ static inline int sched_yield(void) int sched_get_priority_min(int policy); int sched_get_priority_max(int policy); +int sched_getparam(pid_t pid, struct sched_param *param); +int sched_getscheduler(pid_t pid); + #ifdef __cplusplus } #endif diff --git a/lib/posix/sched.c b/lib/posix/sched.c index 4f71badded980e6..7389c8fcec30873 100644 --- a/lib/posix/sched.c +++ b/lib/posix/sched.c @@ -1,12 +1,14 @@ /* - * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2018-2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_internal.h" #include "pthread_sched.h" #include +#include #include /** @@ -41,3 +43,57 @@ int sched_get_priority_max(int policy) errno = EINVAL; return -1; } + +/** + * @brief Get scheduling parameters + * + * See IEEE 1003.1 + */ +int sched_getparam(pid_t pid, struct sched_param *param) +{ + /* TODO: Ensure the Zephyr POSIX process id (PID) value is assigned + * with its first thread's id (TID). + */ + struct sched_param dummy_param = {0}; + pthread_t tid = (pthread_t)pid; + int t_policy = -1; + int ret = -1; + + if (param == NULL) { + param = &dummy_param; + } + + if (tid == 0) { + tid = pthread_self(); + } + + ret = pthread_getschedparam(tid, &t_policy, param); + errno = ret; + + return ((ret) ? -1 : 0); +} + +/** + * @brief Get scheduling policy + * + * See IEEE 1003.1 + */ +int sched_getscheduler(pid_t pid) +{ + /* TODO: Ensure the Zephyr POSIX process id (PID) value is assigned + * with its first thread's id (TID). + */ + struct sched_param dummy_param = {0}; + pthread_t tid = z_get_tid(pid); + int t_policy = -1; + int ret = -1; + + if (tid == 0) { + tid = pthread_self(); + } + + ret = pthread_getschedparam(tid, &t_policy, &dummy_param); + errno = ret; + + return (ret == 0) ? t_policy : -1; +} diff --git a/tests/posix/common/src/pthread.c b/tests/posix/common/src/pthread.c index 16c4af2e3602c59..b0fe709659ead3e 100644 --- a/tests/posix/common/src/pthread.c +++ b/tests/posix/common/src/pthread.c @@ -28,6 +28,7 @@ K_THREAD_STACK_ARRAY_DEFINE(stack_e, N_THR_E, STACKS); K_THREAD_STACK_ARRAY_DEFINE(stack_t, N_THR_T, STACKS); +K_THREAD_STACK_ARRAY_DEFINE(stack_s, 1, STACKS); K_THREAD_STACK_ARRAY_DEFINE(stack_1, 1, 32); void *thread_top_exec(void *p1); @@ -644,6 +645,87 @@ ZTEST(posix_apis, test_pthread_descriptor_leak) } } +static void *create_thread_sched(void *p1) +{ + struct sched_param param = { .sched_priority = -1 }; + int err = 0; + int rc = 0; + + /* Get scheduling params of the current process. */ + rc = sched_getparam(0, ¶m); + err = errno; + zassert_ok(rc, "unable to get scheduling parameters: rc=%d, errno=%d", + rc, err); + + rc = sched_getscheduler(0); + err = errno; + zassert_not_equal(rc, -1, "unable to get scheduling policy: errno=%d", + err); + zassert_equal(rc, SCHED_RR, "unexpected scheduling policy: %d", rc); + + if (p1) { + zassert_equal(param.sched_priority, + ((struct sched_param *)p1)->sched_priority, + "unexpected sched_priority=%d expects=%d", + param.sched_priority, + ((struct sched_param *)p1)->sched_priority); + } + + return NULL; +} + +ZTEST(posix_apis, test_sched_getparam) +{ + struct sched_param param = { .sched_priority = -1 }; + int err = 0; + int rc = 0; + + /* TODO: Assuming non-existent PID is -1 */ + rc = sched_getparam(-1, ¶m); + err = errno; + zassert_true((rc == -1 && err == ESRCH), + "failed parameter check: rc=%d, errno=%d", rc, err); + + rc = sched_getscheduler(-1); + err = errno; + zassert_true((rc == -1 && err == ESRCH), + "failed parameter check: rc=%d, errno=%d", rc, err); + + /* .. and it is safe to call with NULL as praram. */ + rc = sched_getparam(-1, NULL); + err = errno; + zassert_true((rc == -1 && err == ESRCH), + "failed parameter check: rc=%d, errno=%d", rc, err); + + /* Try with the current PID as ztest execution thread - it fails. */ + rc = sched_getparam(0, ¶m); + err = errno; + zassert_true((rc == -1 && err == ESRCH), + "Unexpected result : rc=%d, errno=%d", rc, err); + + rc = sched_getscheduler(0); + err = errno; + zassert_true((rc == -1 && err == ESRCH), + "Unexpected result : rc=%d, errno=%d", rc, err); + + /* Check with a test thread. */ + pthread_t pthread1; + pthread_attr_t attr1 = (pthread_attr_t){0}; + + param.sched_priority = sched_get_priority_min(SCHED_RR); + err = errno; + zassert_not_equal(-1, param.sched_priority, + "sched_get_priority_min(SCHED_RR) failed: errno=%d", err); + zassert_ok(pthread_attr_init(&attr1)); + zassert_ok(pthread_attr_setschedparam(&attr1, ¶m), + "pthread_attr_setschedparam() failed"); + zassert_ok(pthread_attr_setstack(&attr1, &stack_s[0][0], STACKS)); + zassert_ok(pthread_create(&pthread1, &attr1, create_thread_sched, (void *)¶m), + "unable to create a test thread"); + k_msleep(100); + zassert_ok(pthread_join(pthread1, NULL), "unable to join the test thread"); +} + ZTEST(posix_apis, test_sched_policy) { /* diff --git a/tests/posix/headers/src/sched_h.c b/tests/posix/headers/src/sched_h.c index fb4f2de26883052..fba7d17704c729c 100644 --- a/tests/posix/headers/src/sched_h.c +++ b/tests/posix/headers/src/sched_h.c @@ -30,8 +30,8 @@ ZTEST(posix_headers, test_sched_h) zassert_not_null(sched_get_priority_max); zassert_not_null(sched_get_priority_min); - /* zassert_not_null(sched_getparam); */ /* not implemented */ - /* zassert_not_null(sched_getscheduler); */ /* not implemented */ + zassert_not_null(sched_getparam); + zassert_not_null(sched_getscheduler); /* zassert_not_null(sched_rr_get_interval); */ /* not implemented */