kernel: Add posix API for semaphore

Add semaphore posix APIs.

Signed-off-by: Punit Vara <punit.vara@intel.com>
This commit is contained in:
Punit Vara 2018-02-06 09:27:44 +05:30 committed by Anas Nashif
commit a74725f1d3
7 changed files with 210 additions and 1 deletions

View file

@ -42,6 +42,7 @@
#define pthread_rwlock_obj zap_pthread_rwlock_obj #define pthread_rwlock_obj zap_pthread_rwlock_obj
#define pthread_rwlockattr_t zap_pthread_rwlockattr_t #define pthread_rwlockattr_t zap_pthread_rwlockattr_t
/* Condition variables */ /* 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__)
@ -50,6 +51,16 @@
#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__)
/* 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 */ /* 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__)

View file

@ -157,7 +157,6 @@ static inline int pthread_condattr_destroy(pthread_condattr_t *att)
.sem = &name##_psem, \ .sem = &name##_psem, \
} }
/** /**
* @brief POSIX threading compatibility API * @brief POSIX threading compatibility API
* *

28
include/posix/semaphore.h Normal file
View file

@ -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 <time.h>
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 */

View file

@ -30,6 +30,9 @@ typedef struct pthread_attr_t {
typedef void *pthread_t; typedef void *pthread_t;
/* Semaphore */
typedef struct k_sem sem_t;
/* Mutex */ /* Mutex */
typedef struct pthread_mutex { typedef struct pthread_mutex {
struct k_sem *sem; struct k_sem *sem;

View file

@ -513,6 +513,14 @@ config MAX_PTHREAD_COUNT
help help
Mention maximum number of threads in POSIX compliant application. 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 config MAX_TIMER_COUNT
int int
prompt "Maximum timer count in POSIX application" prompt "Maximum timer count in POSIX application"

View file

@ -7,3 +7,4 @@ target_sources(kernel PRIVATE posix/pthread_sched.c)
target_sources(kernel PRIVATE posix/clock.c) target_sources(kernel PRIVATE posix/clock.c)
target_sources(kernel PRIVATE posix/timer.c) target_sources(kernel PRIVATE posix/timer.c)
target_sources(kernel PRIVATE posix/pthread_rwlock.c) target_sources(kernel PRIVATE posix/pthread_rwlock.c)
target_sources(kernel PRIVATE posix/semaphore.c)

159
kernel/posix/semaphore.c Normal file
View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <pthread.h>
#include <errno.h>
/**
* @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;
}
}