Skip to content

Commit

Permalink
posix: sched: Implement get APIs for scheduling parameters
Browse files Browse the repository at this point in the history
Implement `sched_getparam()` and `sched_getscheduler()` POSIX APIs
as a part of PSE53 `_POSIX_PRIORITY_SCHEDULING` option group.

Signed-off-by: Dmitrii Golovanov <dmitrii.golovanov@intel.com>
  • Loading branch information
golowanow committed Jan 1, 2024
1 parent 43189cc commit ef03798
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 6 deletions.
2 changes: 2 additions & 0 deletions arch/posix/include/posix_cheats.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
4 changes: 2 additions & 2 deletions doc/services/portability/posix/option_groups/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
7 changes: 6 additions & 1 deletion include/zephyr/posix/sched.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Intel Corporation
* Copyright (c) 2018-2023 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -8,6 +8,8 @@

#include <zephyr/kernel.h>

#include "posix_types.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -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
Expand Down
58 changes: 57 additions & 1 deletion lib/posix/sched.c
Original file line number Diff line number Diff line change
@@ -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 <zephyr/kernel.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/posix/sched.h>

/**
Expand Down Expand Up @@ -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;
}
82 changes: 82 additions & 0 deletions tests/posix/common/src/pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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, &param);
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, &param);
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, &param);
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, &param),
"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 *)&param),
"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)
{
/*
Expand Down
4 changes: 2 additions & 2 deletions tests/posix/headers/src/sched_h.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down

0 comments on commit ef03798

Please sign in to comment.