kernel: POSIX: Compatibility layer for pthread APIs.
This patch provides pthread APIs for POSIX 1003.1 PSE52 standard. Signed-off-by: Youvedeep Singh <youvedeep.singh@intel.com>
This commit is contained in:
parent
abc94b8597
commit
c8aa6570c1
8 changed files with 731 additions and 6 deletions
|
@ -30,7 +30,9 @@
|
||||||
#define pthread_condattr_t zap_pthread_condattr_t
|
#define pthread_condattr_t zap_pthread_condattr_t
|
||||||
#define pthread_barrier_t zap_pthread_barrier_t
|
#define pthread_barrier_t zap_pthread_barrier_t
|
||||||
#define pthread_barrierattr_t zap_pthread_barrierattr_t
|
#define pthread_barrierattr_t zap_pthread_barrierattr_t
|
||||||
|
#define pthread_attr_t zap_pthread_attr_t
|
||||||
|
|
||||||
|
/* Condition variables */
|
||||||
#define pthread_cond_init(...) zap_pthread_cond_init(__VA_ARGS__)
|
#define pthread_cond_init(...) zap_pthread_cond_init(__VA_ARGS__)
|
||||||
#define pthread_cond_destroy(...) zap_pthread_cond_destroy(__VA_ARGS__)
|
#define pthread_cond_destroy(...) zap_pthread_cond_destroy(__VA_ARGS__)
|
||||||
#define pthread_cond_signal(...) zap_pthread_cond_signal(__VA_ARGS__)
|
#define pthread_cond_signal(...) zap_pthread_cond_signal(__VA_ARGS__)
|
||||||
|
@ -39,6 +41,7 @@
|
||||||
#define pthread_cond_timedwait(...) zap_pthread_cond_timedwait(__VA_ARGS__)
|
#define pthread_cond_timedwait(...) zap_pthread_cond_timedwait(__VA_ARGS__)
|
||||||
#define pthread_condattr_init(...) zap_pthread_condattr_init(__VA_ARGS__)
|
#define pthread_condattr_init(...) zap_pthread_condattr_init(__VA_ARGS__)
|
||||||
#define pthread_condattr_destroy(...) zap_pthread_condattr_destroy(__VA_ARGS__)
|
#define pthread_condattr_destroy(...) zap_pthread_condattr_destroy(__VA_ARGS__)
|
||||||
|
/* Mutex */
|
||||||
#define pthread_mutex_init(...) zap_pthread_mutex_init(__VA_ARGS__)
|
#define pthread_mutex_init(...) zap_pthread_mutex_init(__VA_ARGS__)
|
||||||
#define pthread_mutex_destroy(...) zap_pthread_mutex_destroy(__VA_ARGS__)
|
#define pthread_mutex_destroy(...) zap_pthread_mutex_destroy(__VA_ARGS__)
|
||||||
#define pthread_mutex_lock(...) zap_pthread_mutex_lock(__VA_ARGS__)
|
#define pthread_mutex_lock(...) zap_pthread_mutex_lock(__VA_ARGS__)
|
||||||
|
@ -48,6 +51,7 @@
|
||||||
#define pthread_mutexattr_init(...) zap_pthread_mutexattr_init(__VA_ARGS__)
|
#define pthread_mutexattr_init(...) zap_pthread_mutexattr_init(__VA_ARGS__)
|
||||||
#define pthread_mutexattr_destroy(...) \
|
#define pthread_mutexattr_destroy(...) \
|
||||||
zap_pthread_mutexattr_destroy(__VA_ARGS__)
|
zap_pthread_mutexattr_destroy(__VA_ARGS__)
|
||||||
|
/* Barrier */
|
||||||
#define pthread_barrier_wait(...) zap_pthread_barrier_wait(__VA_ARGS__)
|
#define pthread_barrier_wait(...) zap_pthread_barrier_wait(__VA_ARGS__)
|
||||||
#define pthread_barrier_init(...) zap_pthread_barrier_init(__VA_ARGS__)
|
#define pthread_barrier_init(...) zap_pthread_barrier_init(__VA_ARGS__)
|
||||||
#define pthread_barrier_destroy(...) zap_pthread_barrier_destroy(__VA_ARGS__)
|
#define pthread_barrier_destroy(...) zap_pthread_barrier_destroy(__VA_ARGS__)
|
||||||
|
@ -55,6 +59,37 @@
|
||||||
#define pthread_barrierattr_destroy(...) \
|
#define pthread_barrierattr_destroy(...) \
|
||||||
zap_pthread_barrierattr_destroy(__VA_ARGS__)
|
zap_pthread_barrierattr_destroy(__VA_ARGS__)
|
||||||
|
|
||||||
|
/* pthread */
|
||||||
|
#define pthread_attr_init(...) zap_pthread_attr_init(__VA_ARGS__)
|
||||||
|
#define pthread_attr_destroy(...) zap_pthread_attr_destroy(__VA_ARGS__)
|
||||||
|
#define pthread_attr_getschedparam(...) \
|
||||||
|
zap_pthread_attr_getschedparam(__VA_ARGS__)
|
||||||
|
#define pthread_attr_getstack(...) zap_pthread_attr_getstack(__VA_ARGS__)
|
||||||
|
#define pthread_attr_getstacksize(...) \
|
||||||
|
zap_pthread_attr_getstacksize(__VA_ARGS__)
|
||||||
|
#define pthread_equal(...) zap_pthread_equal(__VA_ARGS__)
|
||||||
|
#define pthread_self(...) zap_pthread_self(__VA_ARGS__)
|
||||||
|
#define pthread_getschedparam(...) zap_pthread_getschedparam(__VA_ARGS__)
|
||||||
|
#define pthread_exit(...) zap_pthread_exit(__VA_ARGS__)
|
||||||
|
#define pthread_join(...) zap_pthread_join(__VA_ARGS__)
|
||||||
|
#define pthread_detach(...) zap_pthread_detach(__VA_ARGS__)
|
||||||
|
#define pthread_cancel(...) zap_pthread_cancel(__VA_ARGS__)
|
||||||
|
#define pthread_attr_getdetachstate(...) \
|
||||||
|
zap_pthread_attr_getdetachstate(__VA_ARGS__)
|
||||||
|
#define pthread_attr_setdetachstate(...) \
|
||||||
|
zap_pthread_attr_setdetachstate(__VA_ARGS__)
|
||||||
|
#define pthread_attr_setschedparam(...) \
|
||||||
|
zap_pthread_attr_setschedparam(__VA_ARGS__)
|
||||||
|
#define pthread_attr_setschedpolicy(...)\
|
||||||
|
zap_pthread_attr_setschedpolicy(__VA_ARGS__)
|
||||||
|
#define pthread_attr_getschedpolicy(...)\
|
||||||
|
zap_pthread_attr_getschedpolicy(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define pthread_attr_setstack(...) zap_pthread_attr_setstack(__VA_ARGS__)
|
||||||
|
#define pthread_create(...) zap_pthread_create(__VA_ARGS__)
|
||||||
|
#define pthread_setcancelstate(...) zap_pthread_setcancelstate(__VA_ARGS__)
|
||||||
|
#define pthread_setschedparam(...) zap_pthread_setschedparam(__VA_ARGS__)
|
||||||
|
|
||||||
#endif /* CONFIG_ARCH_POSIX */
|
#endif /* CONFIG_ARCH_POSIX */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef __PTHREAD_H__
|
#ifndef __PTHREAD_H__
|
||||||
#define __PTHREAD_H__
|
#define __PTHREAD_H__
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
#ifdef CONFIG_NEWLIB_LIBC
|
#ifdef CONFIG_NEWLIB_LIBC
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#else
|
#else
|
||||||
|
@ -20,6 +21,46 @@ struct timespec {
|
||||||
#endif /* CONFIG_NEWLIB_LIBC */
|
#endif /* CONFIG_NEWLIB_LIBC */
|
||||||
|
|
||||||
#include "sys/types.h"
|
#include "sys/types.h"
|
||||||
|
#include "sched.h"
|
||||||
|
|
||||||
|
enum pthread_state {
|
||||||
|
/* The thread is running and joinable. */
|
||||||
|
PTHREAD_JOINABLE = 0,
|
||||||
|
/* The thread is running and detached. */
|
||||||
|
PTHREAD_DETACHED,
|
||||||
|
/* A joinable thread exited and its return code is available. */
|
||||||
|
PTHREAD_EXITED,
|
||||||
|
/* The thread structure is unallocated and available for reuse. */
|
||||||
|
PTHREAD_TERMINATED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct posix_thread {
|
||||||
|
struct k_thread thread;
|
||||||
|
|
||||||
|
/* Exit status */
|
||||||
|
void *retval;
|
||||||
|
|
||||||
|
/* Pthread cancellation */
|
||||||
|
int cancel_state;
|
||||||
|
int cancel_pending;
|
||||||
|
struct k_sem cancel_lock_sem;
|
||||||
|
pthread_mutex_t cancel_lock;
|
||||||
|
|
||||||
|
/* Pthread State */
|
||||||
|
enum pthread_state state;
|
||||||
|
pthread_mutex_t state_lock;
|
||||||
|
struct k_sem state_lock_sem;
|
||||||
|
pthread_cond_t state_cond;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Pthread detach/joinable */
|
||||||
|
#define PTHREAD_CREATE_JOINABLE 0
|
||||||
|
#define PTHREAD_CREATE_DETACHED 1
|
||||||
|
|
||||||
|
/* Pthread cancellation */
|
||||||
|
#define _PTHREAD_CANCEL_POS 0
|
||||||
|
#define PTHREAD_CANCEL_ENABLE (0 << _PTHREAD_CANCEL_POS)
|
||||||
|
#define PTHREAD_CANCEL_DISABLE (1 << _PTHREAD_CANCEL_POS)
|
||||||
|
|
||||||
static inline s32_t _ts_to_ms(const struct timespec *to)
|
static inline s32_t _ts_to_ms(const struct timespec *to)
|
||||||
{
|
{
|
||||||
|
@ -359,4 +400,57 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *);
|
||||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
|
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Base Pthread related APIs */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Obtain ID of the calling thread.
|
||||||
|
*
|
||||||
|
* The results of calling this API from threads not created with
|
||||||
|
* pthread_create() are undefined.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
static inline pthread_t pthread_self(void)
|
||||||
|
{
|
||||||
|
return (pthread_t)k_current_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare thread IDs.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
static inline int pthread_equal(pthread_t pt1, pthread_t pt2)
|
||||||
|
{
|
||||||
|
return (pt1 == pt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
|
||||||
|
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
|
||||||
|
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
|
||||||
|
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
|
||||||
|
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
|
||||||
|
int pthread_attr_init(pthread_attr_t *attr);
|
||||||
|
int pthread_attr_destroy(pthread_attr_t *attr);
|
||||||
|
int pthread_attr_getschedparam(const pthread_attr_t *attr,
|
||||||
|
struct sched_param *schedparam);
|
||||||
|
int pthread_getschedparam(pthread_t pthread, int *policy,
|
||||||
|
struct sched_param *param);
|
||||||
|
int pthread_attr_getstack(const pthread_attr_t *attr,
|
||||||
|
void **stackaddr, size_t *stacksize);
|
||||||
|
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
|
||||||
|
size_t stacksize);
|
||||||
|
void pthread_exit(void *retval);
|
||||||
|
int pthread_join(pthread_t thread, void **status);
|
||||||
|
int pthread_cancel(pthread_t pthread);
|
||||||
|
int pthread_detach(pthread_t thread);
|
||||||
|
int pthread_create(pthread_t *newthread, const pthread_attr_t *attr,
|
||||||
|
void *(*threadroutine)(void *), void *arg);
|
||||||
|
int pthread_setcancelstate(int state, int *oldstate);
|
||||||
|
int pthread_attr_setschedparam(pthread_attr_t *attr,
|
||||||
|
const struct sched_param *schedparam);
|
||||||
|
int pthread_setschedparam(pthread_t pthread, int policy,
|
||||||
|
const struct sched_param *param);
|
||||||
|
|
||||||
#endif /* __PTHREAD_H__ */
|
#endif /* __PTHREAD_H__ */
|
||||||
|
|
33
include/posix/sched.h
Normal file
33
include/posix/sched.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef __POSIX_SCHED_H__
|
||||||
|
#define __POSIX_SCHED_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include_next <sched.h>
|
||||||
|
|
||||||
|
/* Cooperative scheduling policy */
|
||||||
|
#ifndef SCHED_FIFO
|
||||||
|
#define SCHED_FIFO 0
|
||||||
|
#endif /* SCHED_FIFO */
|
||||||
|
|
||||||
|
/* Priority based prempetive scheduling policy */
|
||||||
|
#ifndef SCHED_RR
|
||||||
|
#define SCHED_RR 1
|
||||||
|
#endif /* SCHED_RR */
|
||||||
|
|
||||||
|
struct sched_param {
|
||||||
|
int priority; /* Thread execution priority */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __POSIX_SCHED_H__ */
|
|
@ -12,11 +12,24 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NEWLIB_LIBC
|
|
||||||
#include_next <sys/types.h>
|
#include_next <sys/types.h>
|
||||||
#endif /* CONFIG_NEWLIB_LIBC */
|
|
||||||
|
|
||||||
#ifdef CONFIG_PTHREAD_IPC
|
#ifdef CONFIG_PTHREAD_IPC
|
||||||
|
|
||||||
|
/* Thread attributes */
|
||||||
|
typedef struct pthread_attr_t {
|
||||||
|
int priority;
|
||||||
|
void *stack;
|
||||||
|
size_t stacksize;
|
||||||
|
u32_t flags;
|
||||||
|
u32_t delayedstart;
|
||||||
|
u32_t schedpolicy;
|
||||||
|
s32_t detachstate;
|
||||||
|
u32_t initialized;
|
||||||
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
typedef void *pthread_t;
|
||||||
|
|
||||||
/* Mutex */
|
/* Mutex */
|
||||||
typedef struct pthread_mutex {
|
typedef struct pthread_mutex {
|
||||||
struct k_sem *sem;
|
struct k_sem *sem;
|
||||||
|
@ -26,7 +39,7 @@ typedef struct pthread_mutexattr {
|
||||||
int unused;
|
int unused;
|
||||||
} pthread_mutexattr_t;
|
} pthread_mutexattr_t;
|
||||||
|
|
||||||
/* Confition Variables */
|
/* Condition variables */
|
||||||
typedef struct pthread_cond {
|
typedef struct pthread_cond {
|
||||||
_wait_q_t wait_q;
|
_wait_q_t wait_q;
|
||||||
} pthread_cond_t;
|
} pthread_cond_t;
|
||||||
|
|
|
@ -25,7 +25,9 @@ add_library(kernel
|
||||||
smp.c
|
smp.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (CONFIG_PTHREAD_IPC)
|
||||||
target_include_directories(kernel PRIVATE ${PROJECT_SOURCE_DIR}/include/posix)
|
target_include_directories(kernel PRIVATE ${PROJECT_SOURCE_DIR}/include/posix)
|
||||||
|
endif (CONFIG_PTHREAD_IPC)
|
||||||
target_sources_ifdef(CONFIG_INT_LATENCY_BENCHMARK kernel PRIVATE int_latency_bench.c)
|
target_sources_ifdef(CONFIG_INT_LATENCY_BENCHMARK kernel PRIVATE int_latency_bench.c)
|
||||||
target_sources_ifdef(CONFIG_STACK_CANARIES kernel PRIVATE compiler_stack_protect.c)
|
target_sources_ifdef(CONFIG_STACK_CANARIES kernel PRIVATE compiler_stack_protect.c)
|
||||||
target_sources_ifdef(CONFIG_SYS_CLOCK_EXISTS kernel PRIVATE timer.c)
|
target_sources_ifdef(CONFIG_SYS_CLOCK_EXISTS kernel PRIVATE timer.c)
|
||||||
|
|
|
@ -500,9 +500,19 @@ config PTHREAD_IPC
|
||||||
prompt "POSIX pthread IPC API"
|
prompt "POSIX pthread IPC API"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
This enables a mostly-standards-compliant implementation of
|
This enables a mostly-standards-compliant implementation of
|
||||||
the pthread mutex, condition variable and barrier IPC
|
the pthread mutex, condition variable and barrier IPC
|
||||||
mechanisms.
|
mechanisms.
|
||||||
|
|
||||||
|
if PTHREAD_IPC
|
||||||
|
config MAX_PTHREAD_COUNT
|
||||||
|
int
|
||||||
|
prompt "Maximum pthread count in POSIX application"
|
||||||
|
default 5
|
||||||
|
range 0 255
|
||||||
|
help
|
||||||
|
Mention maximum number of threads in POSIX compliant application.
|
||||||
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "Security Options"
|
menu "Security Options"
|
||||||
|
|
|
@ -2,3 +2,4 @@ target_sources(kernel PRIVATE posix/pthread_common.c)
|
||||||
target_sources(kernel PRIVATE posix/pthread_cond.c)
|
target_sources(kernel PRIVATE posix/pthread_cond.c)
|
||||||
target_sources(kernel PRIVATE posix/pthread_mutex.c)
|
target_sources(kernel PRIVATE posix/pthread_mutex.c)
|
||||||
target_sources(kernel PRIVATE posix/pthread_barrier.c)
|
target_sources(kernel PRIVATE posix/pthread_barrier.c)
|
||||||
|
target_sources(kernel PRIVATE posix/pthread.c)
|
||||||
|
|
537
kernel/posix/pthread.c
Normal file
537
kernel/posix/pthread.c
Normal file
|
@ -0,0 +1,537 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#include "ksched.h"
|
||||||
|
#include "wait_q.h"
|
||||||
|
|
||||||
|
#define PTHREAD_INIT_FLAGS PTHREAD_CANCEL_ENABLE
|
||||||
|
#define PTHREAD_CANCELED ((void *) -1)
|
||||||
|
|
||||||
|
static const pthread_attr_t init_pthread_attrs = {
|
||||||
|
.priority = K_LOWEST_APPLICATION_THREAD_PRIO,
|
||||||
|
.stack = NULL,
|
||||||
|
.stacksize = 0,
|
||||||
|
.flags = PTHREAD_INIT_FLAGS,
|
||||||
|
.delayedstart = K_NO_WAIT,
|
||||||
|
.schedpolicy = SCHED_RR,
|
||||||
|
.detachstate = PTHREAD_CREATE_JOINABLE,
|
||||||
|
.initialized = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Memory pool for pthread space */
|
||||||
|
K_MEM_POOL_DEFINE(posix_thread_pool, sizeof(struct posix_thread),
|
||||||
|
sizeof(struct posix_thread), CONFIG_MAX_PTHREAD_COUNT, 4);
|
||||||
|
static bool is_posix_prio_valid(u32_t priority, int policy)
|
||||||
|
{
|
||||||
|
if ((policy == SCHED_RR &&
|
||||||
|
priority <= CONFIG_NUM_PREEMPT_PRIORITIES) ||
|
||||||
|
(policy == SCHED_FIFO &&
|
||||||
|
priority < CONFIG_NUM_COOP_PRIORITIES)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32_t zephyr_to_posix_priority(s32_t z_prio, int *policy)
|
||||||
|
{
|
||||||
|
u32_t prio;
|
||||||
|
|
||||||
|
if (z_prio < 0) {
|
||||||
|
*policy = SCHED_FIFO;
|
||||||
|
prio = -1 * (z_prio + 1);
|
||||||
|
} else {
|
||||||
|
*policy = SCHED_RR;
|
||||||
|
prio = (CONFIG_NUM_PREEMPT_PRIORITIES - z_prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32_t posix_to_zephyr_priority(u32_t priority, int policy)
|
||||||
|
{
|
||||||
|
s32_t prio;
|
||||||
|
|
||||||
|
if (policy == SCHED_FIFO) {
|
||||||
|
/* Zephyr COOP priority starts from -1 */
|
||||||
|
prio = -1 * (priority + 1);
|
||||||
|
} else {
|
||||||
|
prio = (CONFIG_NUM_PREEMPT_PRIORITIES - priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
return prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set scheduling parameter attributes in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_setschedparam(pthread_attr_t *attr,
|
||||||
|
const struct sched_param *schedparam)
|
||||||
|
{
|
||||||
|
int priority = schedparam->priority;
|
||||||
|
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_posix_prio_valid(priority, attr->schedpolicy) == false) {
|
||||||
|
return ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->priority = priority;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set stack attributes in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
|
||||||
|
size_t stacksize)
|
||||||
|
{
|
||||||
|
if (stackaddr == NULL) {
|
||||||
|
return EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->stack = stackaddr;
|
||||||
|
attr->stacksize = stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
|
||||||
|
{
|
||||||
|
void * (*fun_ptr)(void *) = arg3;
|
||||||
|
|
||||||
|
fun_ptr(arg1);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new thread.
|
||||||
|
*
|
||||||
|
* Pthread attribute should not be NULL. API will return Error on NULL
|
||||||
|
* attribute value.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_create(pthread_t *newthread, const pthread_attr_t *attr,
|
||||||
|
void *(*threadroutine)(void *), void *arg)
|
||||||
|
{
|
||||||
|
s32_t prio;
|
||||||
|
pthread_mutexattr_t att;
|
||||||
|
pthread_condattr_t cond_attr;
|
||||||
|
struct posix_thread *thread;
|
||||||
|
struct k_mem_block block;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Pthread attribute must be non-null and it provides stack
|
||||||
|
* pointer and stack size. So even though POSIX 1003.1 spec accepts
|
||||||
|
* attrib as NULL but zephyr needs it initialized with valid stack.
|
||||||
|
*/
|
||||||
|
if (!attr || !attr->initialized || !attr->stack || !attr->stacksize) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
prio = posix_to_zephyr_priority(attr->priority, attr->schedpolicy);
|
||||||
|
|
||||||
|
if (k_mem_pool_alloc(&posix_thread_pool, &block,
|
||||||
|
sizeof(struct posix_thread), 100) == 0) {
|
||||||
|
memset(block.data, 0, sizeof(struct posix_thread));
|
||||||
|
thread = block.data;
|
||||||
|
} else {
|
||||||
|
/* Insuffecient resource to create thread*/
|
||||||
|
return EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->cancel_state = (1 << _PTHREAD_CANCEL_POS) & attr->flags;
|
||||||
|
thread->state = attr->detachstate;
|
||||||
|
thread->cancel_pending = 0;
|
||||||
|
thread->state_lock.sem = &thread->state_lock_sem;
|
||||||
|
pthread_mutex_init(&thread->state_lock, &att);
|
||||||
|
thread->cancel_lock.sem = &thread->cancel_lock_sem;
|
||||||
|
pthread_mutex_init(&thread->cancel_lock, &att);
|
||||||
|
pthread_cond_init(&thread->state_cond, &cond_attr);
|
||||||
|
|
||||||
|
*newthread = (pthread_t) k_thread_create(&thread->thread, attr->stack,
|
||||||
|
attr->stacksize,
|
||||||
|
(k_thread_entry_t)
|
||||||
|
zephyr_thread_wrapper,
|
||||||
|
(void *)arg, NULL,
|
||||||
|
threadroutine, prio,
|
||||||
|
(~K_ESSENTIAL & attr->flags),
|
||||||
|
attr->delayedstart);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set cancelability State.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_setcancelstate(int state, int *oldstate)
|
||||||
|
{
|
||||||
|
struct posix_thread *pthread = (struct posix_thread *) pthread_self();
|
||||||
|
|
||||||
|
if (state != PTHREAD_CANCEL_ENABLE &&
|
||||||
|
state != PTHREAD_CANCEL_DISABLE) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*oldstate = pthread->cancel_state;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&pthread->cancel_lock);
|
||||||
|
pthread->cancel_state = state;
|
||||||
|
pthread_mutex_unlock(&pthread->cancel_lock);
|
||||||
|
|
||||||
|
if (state == PTHREAD_CANCEL_ENABLE && pthread->cancel_pending) {
|
||||||
|
pthread_exit((void *)PTHREAD_CANCELED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cancel execution of a thread.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_cancel(pthread_t pthread)
|
||||||
|
{
|
||||||
|
struct posix_thread *thread = (struct posix_thread *) pthread;
|
||||||
|
|
||||||
|
if (thread == NULL || thread->state == PTHREAD_TERMINATED) {
|
||||||
|
return ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&thread->cancel_lock);
|
||||||
|
thread->cancel_pending = 1;
|
||||||
|
|
||||||
|
if (thread->cancel_state == PTHREAD_CANCEL_ENABLE) {
|
||||||
|
if (thread->state == PTHREAD_DETACHED) {
|
||||||
|
thread->state = PTHREAD_TERMINATED;
|
||||||
|
pthread_mutex_unlock(&thread->cancel_lock);
|
||||||
|
} else {
|
||||||
|
thread->retval = PTHREAD_CANCELED;
|
||||||
|
pthread_mutex_unlock(&thread->cancel_lock);
|
||||||
|
pthread_mutex_lock(&thread->state_lock);
|
||||||
|
thread->state = PTHREAD_EXITED;
|
||||||
|
pthread_cond_broadcast(&thread->state_cond);
|
||||||
|
pthread_mutex_unlock(&thread->state_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_thread_abort((k_tid_t) thread);
|
||||||
|
} else {
|
||||||
|
pthread_mutex_unlock(&thread->cancel_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set thread scheduling policy and parameters.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_setschedparam(pthread_t pthread, int policy,
|
||||||
|
const struct sched_param *param)
|
||||||
|
{
|
||||||
|
k_tid_t *thread = (k_tid_t *)pthread;
|
||||||
|
int new_prio;
|
||||||
|
|
||||||
|
if (thread == NULL) {
|
||||||
|
return ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (policy != SCHED_RR && policy != SCHED_FIFO) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_prio = posix_to_zephyr_priority(param->priority, policy);
|
||||||
|
|
||||||
|
if (is_posix_prio_valid(new_prio, policy) == false) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_thread_priority_set(*thread, new_prio);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise threads attribute object
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_init(pthread_attr_t *attr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (attr->initialized == true) {
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
*attr = init_pthread_attrs;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get thread scheduling policy and parameters
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_getschedparam(pthread_t pthread, int *policy,
|
||||||
|
struct sched_param *param)
|
||||||
|
{
|
||||||
|
k_tid_t thread = (k_tid_t)pthread;
|
||||||
|
u32_t priority = k_thread_priority_get(thread);
|
||||||
|
|
||||||
|
param->priority = zephyr_to_posix_priority(priority, policy);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Terminate calling thread.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
void pthread_exit(void *retval)
|
||||||
|
{
|
||||||
|
struct posix_thread *self = (struct posix_thread *)pthread_self();
|
||||||
|
|
||||||
|
/* Make a thread as cancelable before exiting */
|
||||||
|
pthread_mutex_lock(&self->cancel_lock);
|
||||||
|
if (self->cancel_state == PTHREAD_CANCEL_DISABLE) {
|
||||||
|
self->cancel_state = PTHREAD_CANCEL_ENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&self->cancel_lock);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&self->state_lock);
|
||||||
|
if (self->state == PTHREAD_JOINABLE) {
|
||||||
|
self->retval = retval;
|
||||||
|
self->state = PTHREAD_EXITED;
|
||||||
|
self->retval = retval;
|
||||||
|
pthread_cond_broadcast(&self->state_cond);
|
||||||
|
} else {
|
||||||
|
self->state = PTHREAD_TERMINATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&self->state_lock);
|
||||||
|
k_thread_abort((k_tid_t)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wait for a thread termination.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_join(pthread_t thread, void **status)
|
||||||
|
{
|
||||||
|
struct posix_thread *pthread = (struct posix_thread *) thread;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (pthread == NULL) {
|
||||||
|
return ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&pthread->state_lock);
|
||||||
|
|
||||||
|
if (pthread->state == PTHREAD_JOINABLE) {
|
||||||
|
pthread_cond_wait(&pthread->state_cond, &pthread->state_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread->state == PTHREAD_EXITED) {
|
||||||
|
if (status) {
|
||||||
|
*status = pthread->retval;
|
||||||
|
}
|
||||||
|
} else if (pthread->state == PTHREAD_DETACHED) {
|
||||||
|
ret = EINVAL;
|
||||||
|
} else {
|
||||||
|
ret = ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&pthread->state_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Detach a thread.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_detach(pthread_t thread)
|
||||||
|
{
|
||||||
|
struct posix_thread *pthread = (struct posix_thread *) thread;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (pthread == NULL) {
|
||||||
|
return ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&pthread->state_lock);
|
||||||
|
|
||||||
|
switch (pthread->state) {
|
||||||
|
case PTHREAD_JOINABLE:
|
||||||
|
pthread->state = PTHREAD_DETACHED;
|
||||||
|
/* Broadcast the condition.
|
||||||
|
* This will make threads waiting to join this thread continue.
|
||||||
|
*/
|
||||||
|
pthread_cond_broadcast(&pthread->state_cond);
|
||||||
|
break;
|
||||||
|
case PTHREAD_EXITED:
|
||||||
|
pthread->state = PTHREAD_TERMINATED;
|
||||||
|
/* THREAD has already exited.
|
||||||
|
* Pthread remained to provide exit status.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case PTHREAD_TERMINATED:
|
||||||
|
ret = ESRCH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&pthread->state_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get detach state attribute in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*detachstate = attr->detachstate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set detach state attribute in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized ||
|
||||||
|
(detachstate != PTHREAD_CREATE_DETACHED &&
|
||||||
|
detachstate != PTHREAD_CREATE_JOINABLE)) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->detachstate = detachstate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get scheduling policy attribute in Thread attributes.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*policy = attr->schedpolicy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set scheduling policy attribute in Thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized ||
|
||||||
|
(policy != SCHED_RR && policy != SCHED_FIFO)) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->schedpolicy = policy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get stack size attribute in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stacksize = attr->stacksize;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get stack attributes in thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_getstack(const pthread_attr_t *attr,
|
||||||
|
void **stackaddr, size_t *stacksize)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stackaddr = attr->stack;
|
||||||
|
*stacksize = attr->stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get thread attributes object scheduling parameters.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_getschedparam(const pthread_attr_t *attr,
|
||||||
|
struct sched_param *schedparam)
|
||||||
|
{
|
||||||
|
if (!attr || !attr->initialized) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
schedparam->priority = attr->priority;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy thread attributes object.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_attr_destroy(pthread_attr_t *attr)
|
||||||
|
{
|
||||||
|
if (attr && attr->initialized) {
|
||||||
|
attr->initialized = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue