Skip to content

Posix implementation layer #5667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Feb 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions arch/posix/include/posix_cheats.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,23 @@
* some prefix, and we ensure this header is included
*/

#ifdef CONFIG_PTHREAD_IPC

#define timespec zap_timespec
#define pthread_mutex_t zap_pthread_mutex_t
#define pthread_mutexattr_t zap_pthread_mutexattr_t
#define pthread_cond_t zap_pthread_cond_t
#define pthread_condattr_t zap_pthread_condattr_t
#define pthread_barrier_t zap_pthread_barrier_t
#define pthread_barrierattr_t zap_pthread_barrierattr_t

#define pthread_attr_t zap_pthread_attr_t
#define clockid_t zap_clockid_t
#define sched_param zap_sched_param
#define itimerspe zap_sched_param
#define timer_t zap_timer_t
#define sigval zap_sigval
#define sigevent zap_sigevent
/* 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__)
Expand All @@ -39,6 +48,7 @@
#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__)
/* Mutex */
#define pthread_mutex_init(...) zap_pthread_mutex_init(__VA_ARGS__)
#define pthread_mutex_destroy(...) zap_pthread_mutex_destroy(__VA_ARGS__)
#define pthread_mutex_lock(...) zap_pthread_mutex_lock(__VA_ARGS__)
Expand All @@ -48,13 +58,66 @@
#define pthread_mutexattr_init(...) zap_pthread_mutexattr_init(__VA_ARGS__)
#define pthread_mutexattr_destroy(...) \
zap_pthread_mutexattr_destroy(__VA_ARGS__)
/* Barrier */
#define pthread_barrier_wait(...) zap_pthread_barrier_wait(__VA_ARGS__)
#define pthread_barrier_init(...) zap_pthread_barrier_init(__VA_ARGS__)
#define pthread_barrier_destroy(...) zap_pthread_barrier_destroy(__VA_ARGS__)
#define pthread_barrierattr_init(...) zap_pthread_barrierattr_init(__VA_ARGS__)
#define pthread_barrierattr_destroy(...) \
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__)

/* Scheduler */
#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__)

/* Sleep */
#define sleep(...) zap_sleep(__VA_ARGS__)
#define usleep(...) zap_usleep(__VA_ARGS__)

/* Clock */
#define clock_gettime(...) zap_clock_gettime(__VA_ARGS__)
#define clock_settime(...) zap_clock_settime(__VA_ARGS__)

/* Timer */
#define timer_create(...) zap_timer_create(__VA_ARGS__)
#define timer_delete(...) zap_timer_delete(__VA_ARGS__)
#define timer_gettime(...) zap_timer_gettime(__VA_ARGS__)
#define timer_settime(...) zap_timer_settime(__VA_ARGS__)

#endif /* CONFIG_PTHREAD_IPC */

#endif /* CONFIG_ARCH_POSIX */

#endif
#endif /* _POSIX_CHEATS_H */
45 changes: 45 additions & 0 deletions include/posix/posix_sched.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __POSIX_SCHED_H__
#define __POSIX_SCHED_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Cooperative scheduling policy */
#ifndef SCHED_FIFO
#define SCHED_FIFO 0
#endif /* SCHED_FIFO */

/* Priority based preemptive scheduling policy */
#ifndef SCHED_RR
#define SCHED_RR 1
#endif /* SCHED_RR */

struct sched_param {
int priority;
};

/**
* @brief Yield the processor
*
* See IEEE 1003.1
*/
static inline int sched_yield(void)
{
k_yield();
return 0;
}

int sched_get_priority_min(int policy);
int sched_get_priority_max(int policy);

#ifdef __cplusplus
}
#endif

#endif /* __POSIX_SCHED_H__ */
127 changes: 91 additions & 36 deletions include/posix/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,50 @@
#ifndef __PTHREAD_H__
#define __PTHREAD_H__

#ifdef CONFIG_NEWLIB_LIBC
#include <kernel.h>
#include <time.h>
#else
/* This should probably live somewhere else but Zephyr doesn't
* currently have a stdc layer to provide it
*/
struct timespec {
s32_t tv_sec;
s32_t tv_nsec;
#include "sys/types.h"
#include "posix_sched.h"
#include "unistd.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
};
#endif

static inline s32_t _ts_to_ms(const struct timespec *to)
{
return (to->tv_sec * 1000) + (to->tv_nsec / 1000000);
}
struct posix_thread {
struct k_thread thread;

typedef struct pthread_mutex {
struct k_sem *sem;
} pthread_mutex_t;
/* Exit status */
void *retval;

typedef struct pthread_mutexattr {
int unused;
} pthread_mutexattr_t;
/* Pthread cancellation */
int cancel_state;
int cancel_pending;
struct k_sem cancel_lock_sem;
pthread_mutex_t cancel_lock;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have a semaphore and a pthread_mutex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pthread_mutex_t just contains a pointer to a semphore.
So we need a semaphore to for this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A user using these APIs will have to define a k_sem as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pthread mutex was implemented by @andyross in last zephyr release.

As per my understanding, there are 2 ways to achieve this :-

  1. Application need to define it statically something like : "PTHREAD_MUTEX_DEFINE(lock);" (something shown in same application tests/kernel/pthread)
  2. Application need to define a "k_sem" and then use ptherad_mutex_init to initialize it. (approach I have taken for my implementation for achieving cancel_lock and state_lock).

I think we need to modify this later, as it does not seem intuitive to a app developer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make it work for both cases (by statically initializing it with that macro or calling pthread_init()) if pthread_mutex_t were embedding a k_sem rather than pointing to it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to modify this later

I think we need to fix this now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes @andrewboie we need to fix this now. But it will need changes in almost all mutex related APIs. At this stage I am avoiding this because merge window is approaching and this will gate all POSIX patches. I will put a FIXME: Comment here and will take this up after 1.11.


typedef struct pthread_cond {
_wait_q_t wait_q;
} pthread_cond_t;
/* Pthread State */
enum pthread_state state;
pthread_mutex_t state_lock;
struct k_sem state_lock_sem;
pthread_cond_t state_cond;
};

typedef struct pthread_condattr {
int unused;
} pthread_condattr_t;
/* 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)

/**
* @brief Declare a pthread condition variable
Expand Down Expand Up @@ -193,7 +205,7 @@ static inline int pthread_mutex_timedlock(pthread_mutex_t *m,
{
int ret = k_sem_take(m->sem, _ts_to_ms(to));

return ret == -EAGAIN ? -ETIMEDOUT : ret;
return ret == 0 ? ret : ETIMEDOUT;
}

/**
Expand Down Expand Up @@ -260,16 +272,6 @@ static inline int pthread_mutexattr_destroy(pthread_mutexattr_t *m)
/* #define PTHREAD_MUTEX_INITIALIZER */
/* #define PTHREAD_COND_INITIALIZER */

typedef struct pthread_barrier {
_wait_q_t wait_q;
int max;
int count;
} pthread_barrier_t;

typedef struct pthread_barrierattr {
int unused;
} pthread_barrierattr_t;

/**
* @brief Declare a pthread barrier
*
Expand Down Expand Up @@ -383,4 +385,57 @@ int pthread_barrierattr_getpshared(const 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__ */
44 changes: 44 additions & 0 deletions include/posix/signal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __POSIX_SIGNAL_H__
#define __POSIX_SIGNAL_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "sys/types.h"

#ifndef SIGEV_NONE
#define SIGEV_NONE 1
#endif

#ifndef SIGEV_SIGNAL
#define SIGEV_SIGNAL 2
#endif

#ifndef SIGEV_THREAD
#define SIGEV_THREAD 3
#endif

typedef union sigval {
int sival_int;
void *sival_ptr;
} sigval;

typedef struct sigevent {
int sigev_notify;
int sigev_signo;
sigval sigev_value;
void (*sigev_notify_function)(sigval val);
pthread_attr_t *sigev_notify_attributes;
} sigevent;

#ifdef __cplusplus
}
#endif

#endif /* __POSIX_TIME_H__ */
Loading