diff --git a/arch/posix/include/posix_cheats.h b/arch/posix/include/posix_cheats.h index be87dd1944a..229042c29a7 100644 --- a/arch/posix/include/posix_cheats.h +++ b/arch/posix/include/posix_cheats.h @@ -42,6 +42,7 @@ #define pthread_rwlock_obj zap_pthread_rwlock_obj #define pthread_rwlockattr_t zap_pthread_rwlockattr_t /* Condition variables */ + #define pthread_cond_init(...) zap_pthread_cond_init(__VA_ARGS__) #define pthread_cond_destroy(...) zap_pthread_cond_destroy(__VA_ARGS__) #define pthread_cond_signal(...) zap_pthread_cond_signal(__VA_ARGS__) @@ -50,6 +51,16 @@ #define pthread_cond_timedwait(...) zap_pthread_cond_timedwait(__VA_ARGS__) #define pthread_condattr_init(...) zap_pthread_condattr_init(__VA_ARGS__) #define pthread_condattr_destroy(...) zap_pthread_condattr_destroy(__VA_ARGS__) + +/* Semaphore */ +#define sem_destroy(...) zap_sem_destroy(__VA_ARGS__) +#define sem_getvalue(...) zap_sem_getvalue(__VA_ARGS__) +#define sem_init(...) zap_sem_init(__VA_ARGS__) +#define sem_post(...) zap_sem_post(__VA_ARGS__) +#define sem_timedwait(...) zap_sem_timedwait(__VA_ARGS__) +#define sem_trywait(...) zap_sem_trywait(__VA_ARGS__) +#define sem_wait(...) zap_sem_wait(__VA_ARGS__) + /* Mutex */ #define pthread_mutex_init(...) zap_pthread_mutex_init(__VA_ARGS__) #define pthread_mutex_destroy(...) zap_pthread_mutex_destroy(__VA_ARGS__) diff --git a/include/posix/pthread.h b/include/posix/pthread.h index 8633f8c8223..7c7bb736f84 100644 --- a/include/posix/pthread.h +++ b/include/posix/pthread.h @@ -157,7 +157,6 @@ static inline int pthread_condattr_destroy(pthread_condattr_t *att) .sem = &name##_psem, \ } - /** * @brief POSIX threading compatibility API * diff --git a/include/posix/semaphore.h b/include/posix/semaphore.h new file mode 100644 index 00000000000..167795ce0fa --- /dev/null +++ b/include/posix/semaphore.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _POSIX_SEMAPHORE_H +#define _POSIX_SEMAPHORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" +#include + +int sem_destroy(sem_t *semaphore); +int sem_getvalue(sem_t *semaphore, int *value); +int sem_init(sem_t *semaphore, int pshared, unsigned int value); +int sem_post(sem_t *semaphore); +int sem_timedwait(sem_t *semaphore, struct timespec *abstime); +int sem_trywait(sem_t *semaphore); +int sem_wait(sem_t *semaphore); + +#ifdef __cplusplus +} +#endif + +#endif /* POSIX_SEMAPHORE_H */ diff --git a/include/posix/sys/types.h b/include/posix/sys/types.h index 7a597e75e3f..a6afb41b34a 100644 --- a/include/posix/sys/types.h +++ b/include/posix/sys/types.h @@ -30,6 +30,9 @@ typedef struct pthread_attr_t { typedef void *pthread_t; +/* Semaphore */ +typedef struct k_sem sem_t; + /* Mutex */ typedef struct pthread_mutex { struct k_sem *sem; diff --git a/kernel/Kconfig b/kernel/Kconfig index 69be217d1da..4e4796b7ee9 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -513,6 +513,14 @@ config MAX_PTHREAD_COUNT help Mention maximum number of threads in POSIX compliant application. +config SEM_VALUE_MAX + int + prompt "Maximum semaphore limit" + default 32767 + range 1 32767 + help + Maximum semaphore count in POSIX compliant Application. + config MAX_TIMER_COUNT int prompt "Maximum timer count in POSIX application" diff --git a/kernel/posix/CMakeLists.txt b/kernel/posix/CMakeLists.txt index 0e7b4782980..ccfb59c0aad 100644 --- a/kernel/posix/CMakeLists.txt +++ b/kernel/posix/CMakeLists.txt @@ -7,3 +7,4 @@ target_sources(kernel PRIVATE posix/pthread_sched.c) target_sources(kernel PRIVATE posix/clock.c) target_sources(kernel PRIVATE posix/timer.c) target_sources(kernel PRIVATE posix/pthread_rwlock.c) +target_sources(kernel PRIVATE posix/semaphore.c) diff --git a/kernel/posix/semaphore.c b/kernel/posix/semaphore.c new file mode 100644 index 00000000000..7f7fa432a98 --- /dev/null +++ b/kernel/posix/semaphore.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** + * @brief Destroy semaphore. + * + * FIXME: EBUSY is not taken care as of now + * + * see IEEE 1003.1 + */ +int sem_destroy(sem_t *semaphore) +{ + if (semaphore == NULL) { + errno = EINVAL; + return -1; + } + + k_sem_reset(semaphore); + + return 0; +} + +/** + * @brief Get value of semaphore. + * + * See IEEE 1003.1 + */ +int sem_getvalue(sem_t *semaphore, int *value) +{ + *value = (int) k_sem_count_get(semaphore); + return 0; +} +/** + * @brief Initialize semaphore. + * + * API only accepts 0 to share share semaphore among threads. Values + * greater than 0 are invalid as zephyr does not support processes. + * + * See IEEE 1003.1 + */ +int sem_init(sem_t *semaphore, int pshared, unsigned int value) +{ + if (value == 0 || value > CONFIG_SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + + if (pshared != 0) { + errno = ENOSYS; + return -1; + } + + k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX); + + return 0; +} + +/** + * @brief Unlock a semaphore. + * + * See IEEE 1003.1 + */ +int sem_post(sem_t *semaphore) +{ + if (semaphore == NULL) { + errno = EINVAL; + return -1; + } + + k_sem_give(semaphore); + return 0; +} + +static int take_and_convert(sem_t *semaphore, s32_t timeout) +{ + int temp, ret; + + temp = k_sem_take(semaphore, timeout); + + if (temp == -EBUSY) { + errno = EAGAIN; + ret = -1; + } else if (temp != 0) { + errno = ETIMEDOUT; + ret = -1; + } else { + ret = 0; + } + + return ret; +} + +/** + * @brief Lock a sempahore. + * + * See IEEE 1003.1 + */ +int sem_timedwait(sem_t *semaphore, struct timespec *abstime) +{ + u32_t timeout; + long msecs = 0; + s64_t current_ms; + s32_t abstime_ms; + + __ASSERT(abstime, "abstime pointer NULL"); + + if ((abstime->tv_sec < 0) || (abstime->tv_nsec >= NSEC_PER_SEC)) { + errno = EINVAL; + return -1; + } + + current_ms = k_uptime_get(); + abstime_ms = _ts_to_ms(abstime); + msecs = abstime_ms - current_ms; + + if (abstime_ms <= current_ms) { + timeout = 0; + } else { + timeout = _ms_to_ticks(msecs); + } + + return take_and_convert(semaphore, timeout); +} + +/** + * @brief Lock a sempahore. + * + * See IEEE 1003.1 + */ +int sem_trywait(sem_t *semaphore) +{ + if (k_sem_take(semaphore, K_NO_WAIT) == -EBUSY) { + errno = EAGAIN; + return -1; + } else { + return 0; + } +} + +/** + * @brief Lock a sempahore. + * + * See IEEE 1003.1 + */ +int sem_wait(sem_t *semaphore) +{ + if (k_sem_take(semaphore, K_FOREVER) == -EBUSY) { + errno = EAGAIN; + return -1; + } else { + return 0; + } +}