diff --git a/sys/posix/pthread/include/pthread.h b/sys/posix/pthread/include/pthread.h index 69488c926bcb6dbfd3209aee2bddc1e3e60d0d13..acd5e8e3060497fb418ceca8d490b5ed0e8e4dd5 100644 --- a/sys/posix/pthread/include/pthread.h +++ b/sys/posix/pthread/include/pthread.h @@ -1,101 +1,26 @@ #ifndef RIOT_PTHREAD_H #define RIOT_PTHREAD_H 1 +/** + * @ingroup pthread + */ + #include <time.h> #include "kernel.h" #include "mutex.h" #include "sched.h" -#include "pthreadtypes.h" - -/* Create a new thread, starting with execution of START-ROUTINE - getting passed ARG. Creation attributed come from ATTR. The new - handle is stored in *NEWTHREAD. */ -int pthread_create(pthread_t *newthread, const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg); - -/* Terminate calling thread. - - The registered cleanup handlers are called via exception handling .*/ -void pthread_exit(void *retval); - -/* Make calling thread wait for termination of the thread TH. The - exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN - is not NULL. - - This function is a cancellation point and therefore not marked with - . */ -int pthread_join(pthread_t th, void **thread_return); - -/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. - The resources of TH will therefore be freed immediately when it - terminates, instead of waiting for another thread to perform PTHREAD_JOIN - on it. */ -int pthread_detach(pthread_t th); - -/* Obtain the identifier of the current thread. */ -pthread_t pthread_self(void); - -/* Compare two thread identifiers. */ -int pthread_equal(pthread_t thread1, pthread_t thread2); - -#include "pthread_attr.h" - -/* Functions for scheduling control. */ - -/* Set the scheduling parameters for TARGET_THREAD according to POLICY - and *PARAM. */ -int pthread_setschedparam(pthread_t target_thread, int policy, - const struct sched_param *param); - -/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ -int pthread_getschedparam(pthread_t target_thread, int *policy, - struct sched_param *param); - -/* Set the scheduling priority for TARGET_THREAD. */ -int pthread_setschedprio(pthread_t target_thread, int prio); - -/* Functions for handling initialization. */ - -/* Guarantee that the initialization function INIT_ROUTINE will be called - only once, even if pthread_once is executed several times with the - same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or - variable initialized to PTHREAD_ONCE_INIT. - - The initialization functions might throw exception */ -int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); - -/* Functions for handling cancellation. - - Note that these functions are explicitly not marked to not throw an - exception in C++ code. If cancellation is implemented by unwinding - this is necessary to have the compiler generate the unwind information. */ - -/* Set cancelability state of current thread to STATE, returning old - state in *OLDSTATE if OLDSTATE is not NULL. */ -int pthread_setcancelstate(int state, int *oldstate); - -/* Set cancellation state of current thread to TYPE, returning the old - type in *OLDTYPE if OLDTYPE is not NULL. */ -int pthread_setcanceltype(int type, int *oldtype); - -/* Cancel THREAD immediately or at the next possibility. */ -int pthread_cancel(pthread_t th); - -/* Test for pending cancellation for the current thread and terminate - the thread as per pthread_exit(PTHREAD_CANCELED) if it has been - cancelled. */ -void pthread_testcancel(void); - +#include "pthread_threading_attr.h" +#include "pthread_threading.h" +#include "pthread_mutex_attr.h" #include "pthread_mutex.h" - #include "pthread_rwlock.h" - #include "pthread_spin.h" - #include "pthread_barrier.h" - #include "pthread_cleanup.h" +#include "pthread_once.h" +#include "pthread_scheduling.h" +#include "pthread_cancellation.h" #endif /* pthread.h */ diff --git a/sys/posix/pthread/include/pthread_attr.h b/sys/posix/pthread/include/pthread_attr.h deleted file mode 100644 index 85b897e26ee48c478ed184ed759d73bb8a512d0c..0000000000000000000000000000000000000000 --- a/sys/posix/pthread/include/pthread_attr.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Thread attribute handling. */ - -#define PTHREAD_CREATE_DETACHED (1) -#define PTHREAD_CREATE_JOINABLE (0) - -/* Initialize thread attribute *ATTR with default attributes - (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, - no user-provided stack). */ -int pthread_attr_init(pthread_attr_t *attr); - -/* Destroy thread attribute *ATTR. */ -int pthread_attr_destroy(pthread_attr_t *attr); - -/* Get detach state attribute. */ -int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); - -/* Set detach state attribute. */ -int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); - -/* Get the size of the guard area created for stack overflow protection. */ -int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize); - -/* Set the size of the guard area created for stack overflow protection. */ -int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); - -/* Return in *PARAM the scheduling parameters of *ATTR. */ -int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct sched_param *param); - -/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ -int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct sched_param *param); - -/* Return in *POLICY the scheduling policy of *ATTR. */ -int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy); - -/* Set scheduling policy in *ATTR according to POLICY. */ -int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); - -/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ -int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit); - -/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ -int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit); - -/* Return in *SCOPE the scheduling contention scope of *ATTR. */ -int pthread_attr_getscope(const pthread_attr_t *attr, int *scope); - -/* Set scheduling contention scope in *ATTR according to SCOPE. */ -int pthread_attr_setscope(pthread_attr_t *attr, int scope); - -/* Return the previously set address for the stack. */ -int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr); - -/* Set the starting address of the stack of the thread to be created. - Depending on whether the stack grows up or down the value must either - be higher or lower than all the address in the memory block. The - minimal size of the block must be PTHREAD_STACK_MIN. */ -int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); - -/* Return the currently used minimal stack size. */ -int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); - -/* Add information about the minimum stack size needed for the thread - to be started. This size must never be less than PTHREAD_STACK_MIN - and must also not exceed the system limits. */ -int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); diff --git a/sys/posix/pthread/include/pthread_barrier.h b/sys/posix/pthread/include/pthread_barrier.h index bb6fa8647971a1949a44323716bdcc048c23b748..1225f67da8849a39207d5886cc133c8e48969cdb 100644 --- a/sys/posix/pthread/include/pthread_barrier.h +++ b/sys/posix/pthread/include/pthread_barrier.h @@ -1,9 +1,23 @@ -/* Functions to handle barriers. */ +/** + * @ingroup pthread + */ #include "mutex.h" -#define PTHREAD_PROCESS_SHARED (0) /**< Share the barrier with child processes (default). */ -#define PTHREAD_PROCESS_PRIVATE (1) /**< Do not share the barrier with child processes. */ +/** + * @def PTHREAD_PROCESS_SHARED + * @brief Share the structure with child processes (default). + * @note RIOT is a single-process OS. + * Setting the value of `pshared` does not change anything. + */ +#define PTHREAD_PROCESS_SHARED (0) +/** + * @def PTHREAD_PROCESS_SHARED + * @brief Don't share the structure with child processes. + * @note RIOT is a single-process OS. + * Setting the value of `pshared` does not change anything. + */ +#define PTHREAD_PROCESS_PRIVATE (1) /** * @brief Internal structure to store the list of waiting threads. @@ -18,13 +32,14 @@ typedef struct pthread_barrier_waiting_node /** * @brief A synchronization barrier. * @details Initialize with pthread_barrier_init(). - * For a zeroed out datum you do not need to call the initializer, it is enough to set `count`. + * For a zeroed out datum you do not need to call the initializer, + * it is enough to set pthread_barrier_t::count. */ typedef struct pthread_barrier { struct pthread_barrier_waiting_node *next; /**< The first waiting thread. */ mutex_t mutex; /**< Mutex to unlock to wake the thread up. */ - volatile int count; /**< Wait to N more threads before waking everyone up. */ + volatile int count; /**< Wait for N more threads before waking everyone up. */ } pthread_barrier_t; /** @@ -34,7 +49,7 @@ typedef struct pthread_barrier */ typedef struct pthread_barrierattr { - int pshared; /**< Set pthread_barrierattr_setpshared() and pthread_barrierattr_getpshared(). */ + int pshared; /**< See pthread_barrierattr_setpshared() and pthread_barrierattr_getpshared(). */ } pthread_barrierattr_t; /** @@ -93,7 +108,7 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshar * @brief Set if the barrier should be shared with child processes * @details Since RIOT is a single process OS, pthread_barrier_init() wil ignore the value. * @param attr Attribute set for pthread_barrier_init() - * @param pshared Either PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED + * @param pshared Either #PTHREAD_PROCESS_PRIVATE or #PTHREAD_PROCESS_SHARED * @returns 0, the invocation cannot fail */ int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared); diff --git a/sys/posix/pthread/include/pthread_cancellation.h b/sys/posix/pthread/include/pthread_cancellation.h new file mode 100644 index 0000000000000000000000000000000000000000..ef66da2599a9fa9a39bc01fc4289abcbc559af11 --- /dev/null +++ b/sys/posix/pthread/include/pthread_cancellation.h @@ -0,0 +1,43 @@ +/** + * @ingroup pthread + */ + +#define PTHREAD_CANCEL_DISABLE 0 +#define PTHREAD_CANCEL_ENABLE 1 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCELED ((void *) -2) + +/** + * @brief Cancellation point are not supported, yet. + * @param[in] state Unused + * @param[out] oldstate Unused + * @returns `-1`, this invocation fails + */ +int pthread_setcancelstate(int state, int *oldstate); + +/** + * @brief Cancellation point are not supported, yet. + * @param[in] type Unused + * @param[out] oldtype Unused + * @returns `-1`, this invocation fails + */ +int pthread_setcanceltype(int type, int *oldtype); + +/** + * @brief Tells a pthread that it should exit. + * @note Cancellation points are not supported, yet. + * @details A pthread `th` can call pthread_testcancel(). + * If pthread_cancel(th) was called before, it will exit then. + * @param[in] th Pthread to tell that it should cancel. + * @returns `-1`, this invocation fails + */ +int pthread_cancel(pthread_t th); + +/** + * @brief Exit the current pthread if pthread_cancel() was called for this thread before. + * @details If pthread_cancel() called before, the current thread exits with with the code #PTHREAD_CANCELED. + */ +void pthread_testcancel(void); diff --git a/sys/posix/pthread/include/pthread_cleanup.h b/sys/posix/pthread/include/pthread_cleanup.h index 8a2da6fa988afa9be482b291d2e46ee663b10747..d0dfd0d57e9ac49ff6868253f93da5c12d94a312 100644 --- a/sys/posix/pthread/include/pthread_cleanup.h +++ b/sys/posix/pthread/include/pthread_cleanup.h @@ -1,9 +1,18 @@ +/** + * @ingroup pthread + * @{ + * @file + * @brief Cleanup primitives for pthread threads. + * @author René Kijewski <kijewski@inf.fu-berlin.de> + * @} + */ + /** * @brief Internal structure for pthread_cleanup_push() */ typedef struct __pthread_cleanup_datum { - /** Cleanup handler to call next. */ + /** Cleanup handler to call next. */ struct __pthread_cleanup_datum *__next; /** Cleanup routine to call. */ diff --git a/sys/posix/pthread/include/pthread_cond.h b/sys/posix/pthread/include/pthread_cond.h index d6323509aed1384f875fab3ba529f734b3c147c9..1fae48f628ac8f30cae5a4b07bb1d743ddefaccc 100644 --- a/sys/posix/pthread/include/pthread_cond.h +++ b/sys/posix/pthread/include/pthread_cond.h @@ -1,5 +1,8 @@ /* Functions for handling conditional variables. */ +typedef unsigned long int pthread_cond_t; +typedef unsigned long int pthread_condattr_t; + /* Initialize condition variable COND using attributes ATTR, or use the default values if later is NULL. */ int pthread_cond_init(pthread_cond_t *cond, diff --git a/sys/posix/pthread/include/pthread_mutex.h b/sys/posix/pthread/include/pthread_mutex.h index 92ee0c24332d0d6661e036db108a12041d4ba25d..fff0e36d024af649eaf5f2b3b982be1c74e3cf0d 100644 --- a/sys/posix/pthread/include/pthread_mutex.h +++ b/sys/posix/pthread/include/pthread_mutex.h @@ -1,81 +1,91 @@ -/* Mutex handling. */ +/** + * @ingroup pthread + */ #include <time.h> #include "kernel.h" #include "mutex.h" -/* Initialize a mutex. */ -int pthread_mutex_init(pthread_mutex_t *mutex, - const pthread_mutexattr_t *mutexattr); - -/* Destroy a mutex. */ +/** + * @brief Pthread mutexes are quite the same as RIOT mutexes. + * @details Recursive locking is not supported. + * A thread can unlock a mutex even if it does not hold it. + */ +typedef mutex_t pthread_mutex_t; + +/** + * @brief Initialize a mutex. + * @details A zeroed out datum is initialized. + * @param[in,out] mutex Mutex to initialize. + * @param[in] mutexattr Unused. + * @returns `0` on success. `-1` iff `mutex == NULL`. + */ +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); + +/** + * @brief Destroy a mutex. + * @details This is currently a no-op. + *  Destroying a mutex locked is undefined behavior. + * @param[in,out] mutex Datum to destroy. + * @returns 0, this invocation is a no-op that cannot fail. + */ int pthread_mutex_destroy(pthread_mutex_t *mutex); -/* Try locking a mutex. */ +/** + * @brief Try to lock a mutex. + * @details This function won't block. + * @param[in] mutex Mutex to lock, must be initialized. + * @returns `0` if you hold the mutex now. + * `+1` if the mutex already was locked. + * `-1` if you managed to supply `NULL`. + */ int pthread_mutex_trylock(pthread_mutex_t *mutex); -/* Lock a mutex. */ +/** + * @brief Lock and hold a mutex. + * @details This invocation may block if the mutex was locked. + * @param[in] mutex Mutex to lock, must be initialized. + * @returns `-1` iff you managed to supply `NULL`. + * `0` otherwise, you hold the mutex now. + */ int pthread_mutex_lock(pthread_mutex_t *mutex); -/* Wait until lock becomes available, or specified time passes. */ -int pthread_mutex_timedlock(pthread_mutex_t *mutex, - const struct timespec *abstime); - -/* Unlock a mutex. */ +/** + * @brief Not implemented, yet. + * @details Will cause a linktime error ... + * @param[in] mutex The unused mutex. + * @param[in] abstime The used absolute time. + * @return Well ... you'll get a link time error, so nothing will be returned. + */ +int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime); + +/** + * @brief Unlock a mutex. + * @details It is possible to unlock a mutex that you don't hold. + * It is possible to unlock a mutex that is not held at all. + * The mutex can still be locked afterwards if there were threads queuing for this mutex. + * @param[in] mutex Mutex to unlock, must be initialized. + * @returns `-1` iff you managed to supply `NULL`. + * `0` otherwise. + */ int pthread_mutex_unlock(pthread_mutex_t *mutex); -/* Get the priority ceiling of MUTEX. */ -int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, - int *prioceiling); - -/* Set the priority ceiling of MUTEX to PRIOCEILING, return old - priority ceiling value in *OLD_CEILING. */ -int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, - int *old_ceiling); - -/* Functions for handling mutex attributes. */ - -/* Initialize mutex attribute object ATTR with default attributes - (kind is PTHREAD_MUTEX_TIMED_NP). */ -int pthread_mutexattr_init(pthread_mutexattr_t *attr); - -/* Destroy mutex attribute object ATTR. */ -int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); - -/* Get the process-shared flag of the mutex attribute ATTR. */ -int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, - int *pshared); - -/* Set the process-shared flag of the mutex attribute ATTR. */ -int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); - -/* Return in *KIND the mutex kind attribute in *ATTR. */ -int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind); - -/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, - PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or - PTHREAD_MUTEX_DEFAULT). */ -int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind); - -/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */ -int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, - int *protocol); - -/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either - PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */ -int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol); - -/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */ -int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, - int *prioceiling); - -/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */ -int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling); - -/* Get the robustness flag of the mutex attribute ATTR. */ -int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, - int *robustness); - -/* Set the robustness flag of the mutex attribute ATTR. */ -int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robustness); +/** + * @brief Not implemented, yet. + * @details Will cause a linktime error ... + * @param[in] mutex The unused mutex. + * @param[out] prioceiling Unused. + * @return Well ... you'll get a link time error, so nothing will be returned. + */ +int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling); + +/** + * @brief Not implemented, yet. + * @details Will cause a linktime error ... + * @param[in,out] mutex The unused mutex. + * @param[in] prioceiling Unused. + * @param[out] old_ceiling Unused. + * @return Well ... you'll get a link time error, so nothing will be returned. + */ +int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling); diff --git a/sys/posix/pthread/include/pthread_mutex_attr.h b/sys/posix/pthread/include/pthread_mutex_attr.h new file mode 100644 index 0000000000000000000000000000000000000000..957b83db82e2d556f5d5f958a5a45d59fff5ef91 --- /dev/null +++ b/sys/posix/pthread/include/pthread_mutex_attr.h @@ -0,0 +1,189 @@ +#include <errno.h> + +/** + * @def PTHREAD_MUTEX_NORMAL + * @brief A non-error correcting mutex (default). + */ +/** + * @def PTHREAD_MUTEX_RECURSIVE + * @brief A mutex that allows recursive locking. + * @note Not implemented, yet. + */ +/** + * @def PTHREAD_MUTEX_ERRORCHECK + * @brief A mutex that fails with `EDEADLK` if recursive locking was detected. + * @note Not implemented, yet. + */ +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_RECURSIVE 1 +#define PTHREAD_MUTEX_ERRORCHECK 2 +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL + +/** + * @def PTHREAD_MUTEX_DEFAULT + * @brief The default mutex kind for RIOT. + * @note Not implemented, yet. + */ +/** + * @def PTHREAD_MUTEX_DEFAULT + * @brief No priority inheritance. + * @details Prone to inversed priorities. + * The default mutex protocol. + */ +/** + * @def PTHREAD_PRIO_INHERIT + * @brief If a thread attempts to acquire a held lock, + * the holding thread gets its dynamic priority increased up to + * the priority of the blocked thread + * @note Not implemented, yet. + */ +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 + +/** + * @def PTHREAD_PRIO_PROTECT + * @brief Not implemented, yet. + */ +/** + * @def PTHREAD_MUTEX_STALLED + * @brief Mutexes aren't automatically released on the end of a thread. + * @see #pthread_cleanup_push() for an option to unlock mutexes on the end of a thread. + * @note This is the default. + */ +/** + * @def PTHREAD_MUTEX_ROBUST + * @brief Mutexes that are held at the exit of a thread get released automatically. + * @note Not implemented, yet. + */ +#define PTHREAD_PRIO_PROTECT 2 +#define PTHREAD_MUTEX_STALLED 0 +#define PTHREAD_MUTEX_ROBUST 1 + +/** + * @brief This type is unused right now, and only exists for POSIX compatibility. + */ +typedef struct pthread_mutexattr +{ + int pshared; /**< Whether to share the mutex with child processes. */ + int kind; /**< Type of the mutex. */ + int protocol; /**< Priority inheritance of the mutex. */ + int robustness; /**< What to do if a thread terminates while it holds a mutex. */ +} pthread_mutexattr_t; + +/** + * @brief Initialize a pthread_mutexattr_t + * @details A zeroed out datum is initialized + * @note This function is not implemented, yet. + * @param[out] attr Datum to initialize. + * @returns `0` on success. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_init(pthread_mutexattr_t *attr); + +/** + * @brief Destroys a pthread_mutexattr_t + * @details There is no need to ever call this function. + * This function is a no-op. + * @note This function is not implemented, yet. + * @param[in,out] attr Datum to destroy. + * @returns `0` on success. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); + +/** + * @brief Queries the attribute set whether to share the mutex with child processes. + * @note Since RIOT does not implement processes, this value is unused. + * @param[in] attr Attribute set to query. + * @param[out] pshared Either #PTHREAD_PROCESS_SHARED or #PTHREAD_PROCESS_PRIVATE. + * @returns `0` on success. + * `EINVAL` if `attr` or `pshared` are `NULL`. + */ +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared); + +/** + * @brief Set whether to share the mutex with child processes. + * @note Since RIOT does not implement processes, this value is unused. + * @param[in,out] attr Attribute set to change. + * @param[in] pshared Either #PTHREAD_PROCESS_SHARED or #PTHREAD_PROCESS_PRIVATE. + * @returns `0` on success. + * `EINVAL` if `pshared` is neither #PTHREAD_PROCESS_SHARED nor #PTHREAD_PROCESS_PRIVATE. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); + +/** + * @brief Query the type of the mutex to create. + * @note This implementation only supports PTHREAD_MUTEX_NORMAL mutexes. + * @param[in] attr Attribute set to query. + * @param[out] kind Either #PTHREAD_MUTEX_NORMAL or #PTHREAD_MUTEX_RECURSIVE or #PTHREAD_MUTEX_ERRORCHECK. + * @returns `0` on success. + * `EINVAL` if `attr` or `kind` are `NULL`. + */ +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind); + +/** + * @brief Sets the type of the mutex to create. + * @note This implementation only supports `PTHREAD_MUTEX_NORMAL` mutexes. + * @param[in,out] attr Attribute set to change. + * @param[in] kind Either #PTHREAD_MUTEX_NORMAL or #PTHREAD_MUTEX_RECURSIVE or #PTHREAD_MUTEX_ERRORCHECK. + * @returns `0` on success. + * `EINVAL` if the value of `kind` is unsupported. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind); + +/** + * @brief Query the priority inheritance of the mutex to create. + * @note This implementation only supports `PTHREAD_PRIO_NONE` mutexes. + * @param[in] attr Attribute set to query + * @param[out] protocol Either #PTHREAD_PRIO_NONE or #PTHREAD_PRIO_INHERIT or #PTHREAD_PRIO_PROTECT. + * @returns `0` on success. + * `EINVAL` if `attr` or `protocol` are `NULL`. + */ +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol); + +/** + * @brief Sets the priority inheritance of the mutex to create. + * @note This implementation only supports `PTHREAD_PRIO_NONE` mutexes. + * @param[in,out] attr Attribute set to change. + * @param[in] protocol Either #PTHREAD_PRIO_NONE or #PTHREAD_PRIO_INHERIT or #PTHREAD_PRIO_PROTECT. + * @returns `0` on success. + * `EINVAL` if the value of `protocol` is unsupported. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol); + +/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */ +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling); + +/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */ +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling); + +/** + * @brief Query the attribute set whether to create a robut mutex. + * @details A "robust" mutex releases gets released automagically if the threads exits while it hold the mutex. + * If the thread is cancellable, only rubust mutex should be held. + * @note This implementation does not support robust mutexes, yet. + * As it doesn't implement cancellation points, yet, this should not pose a problem. + * @param[in] attr Attribute set to query. + * @param[out] robustness Either #PTHREAD_MUTEX_STALLED or #PTHREAD_MUTEX_ROBUST. + * @returns `0` on success. + * `EINVAL` if the value of `protocol` is unsupported. + * `EINVAL` if `attr` or `robustness` is `NULL`. + */ +int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robustness); + +/** + * @brief Set whether the mutex to create should be robust. + * @details A "robust" mutex releases gets released automagically if the threads exits while it hold the mutex. + * If the thread is cancellable, only rubust mutex should be held. + * @note This implementation does not support robust mutexes, yet. + * As it doesn't implement cancellation points, yet, this should not pose a problem. + * @param[in,out] attr Attribute set to change. + * @param[in] robustness Either #PTHREAD_MUTEX_STALLED or #PTHREAD_MUTEX_ROBUST. + * @returns `0` on success. + * `EINVAL` if the value of `robustness` is unsupported. + * `EINVAL` if `attr == NULL`. + */ +int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robustness); diff --git a/sys/posix/pthread/include/pthread_once.h b/sys/posix/pthread/include/pthread_once.h new file mode 100644 index 0000000000000000000000000000000000000000..02e2495ec15729941e5b0c41afbf4eecde380670 --- /dev/null +++ b/sys/posix/pthread/include/pthread_once.h @@ -0,0 +1,26 @@ +/** + * @ingroup pthread + */ + +/** + * @brief Datatype to supply to pthread_once(). + */ +typedef volatile int pthread_once_t; + +/** + * @def PTHREAD_ONCE_INIT + * @brief Initialization for pthread_once_t. + * @details A zeroed out pthread_once_t is initialized. + */ +#define PTHREAD_ONCE_INIT 0 + +/** + * @brief Helper function that ensures that `init_routine` is called at once. + * @details Calling pthread_once() changes `once_control`. + * For the same `once_control` the supplied `init_routine` won't get called again, + * unless `once_control` is reset to `PTHREAD_ONCE_INIT` or zeroed out. + * @param[in,out] once_control Flag to ensure that the `init_routine` is called only once. + * @param[in] init_routine Function to call if `once_control` was not used, yet. + * @returns 0, this invocation cannot fail. + */ +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); diff --git a/sys/posix/pthread/include/pthread_rwlock.h b/sys/posix/pthread/include/pthread_rwlock.h index 7a726eba133663da6e90b853c5c36071dd596764..dd631575a94e2e3891ca2325b10ec51269665ef6 100644 --- a/sys/posix/pthread/include/pthread_rwlock.h +++ b/sys/posix/pthread/include/pthread_rwlock.h @@ -1,4 +1,9 @@ -/* Functions for handling read-write locks. */ +/** + * @ingroup pthread + */ + +typedef unsigned long int pthread_rwlock_t; +typedef unsigned long int pthread_rwlockattr_t; /* Initialize read-write lock RWLOCK using attributes ATTR, or use the default values if later is NULL. */ diff --git a/sys/posix/pthread/include/pthread_scheduling.h b/sys/posix/pthread/include/pthread_scheduling.h new file mode 100644 index 0000000000000000000000000000000000000000..1ab0d9f811d043d8057f3e434d26e95f188730d4 --- /dev/null +++ b/sys/posix/pthread/include/pthread_scheduling.h @@ -0,0 +1,32 @@ +/** + * @ingroup pthread + */ + +/** + * @brief Unimplemented. + * @note Due to the native of RIOT it is unlikely that this function will ever be implemented. + * @param[in] target_thread Unused + * @param[in] policy Unused + * @param[in] param Unused + * @returns The function is unimplemented. Using it will cause a link time error. + */ +int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param); + +/** + * @brief Unimplemented. + * @note Due to the native of RIOT it is unlikely that this function will ever be implemented. + * @param[in] target_thread Unused + * @param[in,out] policy Unused + * @param[out] param Unused + * @returns The function is unimplemented. Using it will cause a link time error. + */ +int pthread_getschedparam(pthread_t target_thread, int *policy, struct sched_param *param); + +/** + * @brief Unimplemented. + * @note Due to the native of RIOT it is unlikely that this function will ever be implemented. + * @param[in] target_thread Unused + * @param[in] prio Unused + * @returns The function is unimplemented. Using it will cause a link time error. + */ +int pthread_setschedprio(pthread_t target_thread, int prio); diff --git a/sys/posix/pthread/include/pthread_spin.h b/sys/posix/pthread/include/pthread_spin.h index 17c13ad913bef0e7f74c3bb9288f6e1d031f6d26..0a5bb62d9ccfd6126064d778e650eadf509a01d9 100644 --- a/sys/posix/pthread/include/pthread_spin.h +++ b/sys/posix/pthread/include/pthread_spin.h @@ -1,17 +1,64 @@ -/* Functions to handle spinlocks. */ +/** + * @ingroup pthread + */ -/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can - be shared between different processes. */ +#include <errno.h> + +/** + * @brief A spinlock. + * @warning Spinlocks should be avoided. + * They will burn away the battery needlessly, and may not work because RIOT is tickless. + * Use disableIRQ() and restoreIRQ() for shortterm locks instead. + */ +typedef volatile unsigned pthread_spinlock_t; + +/** + * @brief Intializes a spinlock. + * @warning See the warning in pthread_spinlock_t. + * @details A zeroed out datum is initialized. + * @param[in,out] lock Datum to initialize. + * @param[in] pshared Unused. + * @returns `0` on success. + * `EINVAL` if `lock == NULL`. + */ int pthread_spin_init(pthread_spinlock_t *lock, int pshared); -/* Destroy the spinlock LOCK. */ +/** + * @brief Destroys a spinlock. + * @warning See the warning in pthread_spinlock_t. + * @details Destroying a spinlock while a thread is waiting for it causes undefined behavior. + * This is a no-op. + * @param[in,out] lock Datum to destroy. + * @returns `0` on success. + * `EINVAL` if `lock == NULL`. + */ int pthread_spin_destroy(pthread_spinlock_t *lock); -/* Wait until spinlock LOCK is retrieved. */ +/** + * @brief Lock a spinlock. + * @warning See the warning in pthread_spinlock_t. + * @param[in,out] lock Lock to acquire. + * @return `0` on success. + * `EINVAL` if `lock == NULL`. + */ int pthread_spin_lock(pthread_spinlock_t *lock); -/* Try to lock spinlock LOCK. */ +/** + * @brief Tries to lock a spinlock, returns immediately if already locked. + * @warning See the warning in pthread_spinlock_t. + * @param[in,out] lock Lock to acquire. + * @return `0` on success. + * `EBUSY` if the lock was already locked. + * `EINVAL` if `lock == NULL`. + */ int pthread_spin_trylock(pthread_spinlock_t *lock); -/* Release spinlock LOCK. */ +/** + * @brief Releases a spinlock. + * @warning See the warning in pthread_spinlock_t. + * @param[in,out] lock Lock to release + * @return `0` on success. + * `EPERM` if the lock was not locked. + * `EINVAL` if `lock == NULL`. + */ int pthread_spin_unlock(pthread_spinlock_t *lock); diff --git a/sys/posix/pthread/include/pthread_threading.h b/sys/posix/pthread/include/pthread_threading.h new file mode 100644 index 0000000000000000000000000000000000000000..c77148fdbe7749f74493e6dd2198e2e1c0387c43 --- /dev/null +++ b/sys/posix/pthread/include/pthread_threading.h @@ -0,0 +1,85 @@ +/** + * @ingroup pthread + */ + +#include "attributes.h" + +/** + * @brief Datatype to identify a POSIX thread. + * @note The pthread ids are one off to the index in the internal array. + */ +typedef unsigned pthread_t; + +/** + * @brief Spawn a new POSIX thread. + * @details This functions starts a new thread. + * The thread will be joinable (from another pthread), + * unless `attr` tells to create the thread detached. + * A non-detached thread must be joined will stay a zombie into it is joined. + * You can call pthread_exit() inside the thread, or return from `start_routine()`. + * @note Cancellation is currently not implemented. + * @note In an embedded system you probably want to supply a statically allocated stack in `attr`. + * @param[out] newthread The identifier of the new thread. + * @param[in] attr An attribute set that describes how the new thread should be started. + * @param[in] start_routine The entry point of the new thread. + * @param[in] arg Argument supplied to `start_routine`. + * @return `== 0` on success. + * `!= 0` on error. + */ +int pthread_create(pthread_t *newthread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); + +/** + * @brief Exit calling pthread. + * @note Only pthreads must call this function. + * Native threads must call sched_thread_exit(). + * A pthread must not call sched_thread_exit(). + * @param[out] retval Return value, supplied to a joining thread. + * @return This function does not return. + */ +void pthread_exit(void *retval) NORETURN; + +/** + * @brief Join a pthread. + * @details The current thread sleeps until `th` exits. + * The exit value of `th` gets written into `thread_return`. + * You can only join pthreads, and only pthreads can join. + * A thread must not join itself. + * @param[in] th pthread to join, the id was supplied by pthread_create() + * @param[out] thread_return Exit code of `th`. + * @return `== 0` on success. + * `!= 0` on error. + */ +int pthread_join(pthread_t th, void **thread_return); + +/** + * @brief Make a pthread unjoinable. + * @details The resources of a detached thread get released as soon as it exits, + * without the need to call pthread_join() out of another pthread. + * In fact you cannot join a detached thread, it will return an error. + * Detaching a thread while another thread tries to join it causes undefined behavior. + * A pthread may detach himself. + * A non-pthread may call this function, too. + * A pthread cannot be "attached" again. + * @param[in] th pthread to detach. + * @return `== 0` on success. + * `!= 0` on error. + */ +int pthread_detach(pthread_t th); + +/** + * @brief Returns the pthread id of the calling/current thread. + * @note This function should not be used to determine if the calling thread is a pthread. + * If your logic is sane then there should be no need to do that. + * @return `> 0` identifies the calling pthread. + * `== 0` if the calling thread is not a pthread. + */ +pthread_t pthread_self(void); + +/** + * @brief Compared two pthread identifiers. + * @return `0` if the ids identify two different threads. + */ +static inline int pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} diff --git a/sys/posix/pthread/include/pthread_threading_attr.h b/sys/posix/pthread/include/pthread_threading_attr.h new file mode 100644 index 0000000000000000000000000000000000000000..133808ad9f568a9858f5fc588c2d2a2a848912b1 --- /dev/null +++ b/sys/posix/pthread/include/pthread_threading_attr.h @@ -0,0 +1,183 @@ +/** + * @ingroup pthread + */ + +/** + * @brief An attribute set to supply to pthread_create() + * @details A zeroed out datum is default initiliazed. + * @see pthread_create() for further information + */ +typedef struct pthread_attr +{ + uint8_t detached; /**< Start in detached state. */ + char *ss_sp; /**< Stack to use for new thread. */ + size_t ss_size; /**< Size of dynamically allocated stack, or supplied stack, resp. */ +} pthread_attr_t; + +/** + * @brief This structure is unused right now, and only exists for POSIX compatibility. + */ +struct sched_param { + int todo; /* TODO */ +}; + +#define PTHREAD_CREATE_JOINABLE (0) /**< Create new pthread as joinable (default). */ +#define PTHREAD_CREATE_DETACHED (1) /**< Create new pthread in detached state. */ + +/** + * @brief Initialize attributes for a new pthread. + * @see pthread_create() + * @details A zeroed out `attr` is initialized. + * @param[in,out] attr Structure to initialize + * @returns 0, invocation cannot fail + */ +int pthread_attr_init(pthread_attr_t *attr); + +/** + * @brief Destroys an attribute set. + * @details Since pthread_attr_t does not hold dynamic data, this is a no-op. + * @returns 0, since this a no-op that cannot fail + */ +int pthread_attr_destroy(pthread_attr_t *attr); + +/** + * @brief Tells whether to create a new pthread in a detached state. + * @param[in] attr Attribute set to query. + * @param[out] detachstate Either PTHREAD_CREATE_JOINABLE or PTHREAD_CREATE_DETACHED. + * @returns 0, the invocation cannot fail + */ +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); + +/** + * @brief Sets whether to create a new pthread in a detached state. + * @note Supplying a value different form PTHREAD_CREATE_JOINABLE or PTHREAD_CREATE_DETACHED + * causes undefined behavior. + * @param[in,out] attr Attribute set to operate on. + * @param[in] detachstate Either PTHREAD_CREATE_JOINABLE or PTHREAD_CREATE_DETACHED. + * @returns `0` on success. + * `-1` if you managed to supply an illegal value in `detachstate`. + */ +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in] attr Unused + * @param[out] guardsize Unused + * @returns -1, this function fails + */ +int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in,out] attr Unused + * @param[in] guardsize Unused + * @returns -1, this function fails + */ +int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in] attr Unused + * @param[out] param Unused + * @returns -1, this function fails + */ +int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in,out] attr Unused + * @param[in] param Unused + * @returns -1, this function fails + */ +int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in] attr Unused + * @param[out] policy Unused + * @returns -1, this function fails + */ +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in,out] attr Unused + * @param[in] policy Unused + * @returns -1, this function fails + */ +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in] attr Unused + * @param[out] inherit Unused + * @returns -1, this function fails + */ +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in,out] attr Unused + * @param[in] inherit Unused + * @returns -1, this function fails + */ +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in] attr Unused + * @param[out] scope Unused + * @returns -1, this function fails + */ +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope); + +/** + * @brief This function is unused right now, and only exists for POSIX compatibility. + * @param[in,out] attr Unused + * @param[in] scope Unused + * @returns -1, this function fails + */ +int pthread_attr_setscope(pthread_attr_t *attr, int scope); + +/** + * @brief Query assigned stack for new pthread. + * @see pthread_attr_setstackaddr() for more information + * @param[in] attr Attribute set to query + * @param[out] stackaddr Pointer to previously assigned stack, or `NULL` for dynamic allocation. + * @returns 0, this invocation cannot fail + */ +int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr); + +/** + * @brief Set address of the stack to use for the new pthread. + * @details If `*stackaddr == NULL`, then the stack is dynamically allocated with malloc(). + * No two running threads may operate on the same stack. + * The stack of a zombie thread (i.e. a non-detached thread that exited but was not yet joined) + * may in theory be reused even before joining, though there might be problems + * if the stack was preempted before pthread_exit() completed. + * @param[in,out] attr Attribute set to operate on. + * @param[in] stackaddr Static stack to use, or `NULL` for dynamic allocation. + * @returns 0, this invocation cannot fail + */ +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); + +/** + * @brief Query set stacksize for new pthread. + * @details Returns default stack size of the value is yet unset. + * @param[in] attr Attribute set to query. + * @param[out] stacksize Assigned or default stack size, resp. + * @returns 0, this invocation cannot fail + */ +int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); + +/** + * @brief Set the stack size for the new pthread. + * @details If you use pthread_attr_getstackaddr() to assign a static stack, + * then you must use this function to set the size of the stack. + * In case of dynamic memory allocation this overrules the default value. + * @param[in,out] attr Attribute set to operate on + * @param[in] stacksize Size of the stack of the new thread. + * Supply `0` to use the default value. + * @return 0, this invocation cannot fail. + */ +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); diff --git a/sys/posix/pthread/include/pthreadtypes.h b/sys/posix/pthread/include/pthreadtypes.h deleted file mode 100644 index 082acb53cefa3eb3d0aba98ce94d5708f72f5c05..0000000000000000000000000000000000000000 --- a/sys/posix/pthread/include/pthreadtypes.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PTHREADTYPES_H_ -#define PTHREADTYPES_H_ - -typedef unsigned long int pthread_t; - -typedef struct pthread_attr -{ - uint8_t detached; - char *ss_sp; - size_t ss_size; -} pthread_attr_t; - -struct sched_param { - int todo; /* TODO */ -}; - -/* Once-only execution */ -typedef int pthread_once_t; -/* Single execution handling. */ -#define PTHREAD_ONCE_INIT 0 - -typedef unsigned long int pthread_cond_t; -typedef unsigned long int pthread_condattr_t; - -typedef mutex_t pthread_mutex_t; -typedef unsigned long int pthread_mutexattr_t; - -typedef unsigned long int pthread_rwlock_t; -typedef unsigned long int pthread_rwlockattr_t; - -typedef volatile int pthread_spinlock_t; - -#endif /* PTHREADTYPES_H_ */ diff --git a/sys/posix/pthread/pthread.c b/sys/posix/pthread/pthread.c index 858f84218cc1e7f060600d1a9d00eaf0925f63e8..bffc6c1ae4f2d3ca58b25edff8c026c07d51dc80 100644 --- a/sys/posix/pthread/pthread.c +++ b/sys/posix/pthread/pthread.c @@ -1,16 +1,19 @@ -/** - * POSIX implementation of threading. - * +/* * Copyright (C) 2013 Freie Universität Berlin * * This file subject to the terms and conditions of the GNU Lesser General * Public License. See the file LICENSE in the top level directory for more * details. - * + */ + +/** + * @defgroup pthread POSIX threads + * POSIX conforming multi-threading features. * @ingroup posix * @{ - * @file pthread.c - * @brief Implementation of pthread. + * @file + * @brief Thread creation features. + * @see [The Open Group Base Specifications Issue 7: pthread.h - threads](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html) * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author René Kijewski <kijewski@inf.fu-berlin.de> * @} @@ -254,11 +257,6 @@ pthread_t pthread_self(void) return result; } -int pthread_equal(pthread_t thread1, pthread_t thread2) -{ - return (thread1 == thread2); -} - int pthread_cancel(pthread_t th) { pthread_thread_t *other = pthread_sched_threads[th-1]; @@ -275,21 +273,21 @@ int pthread_setcancelstate(int state, int *oldstate) { (void) state; (void) oldstate; - return 0; + return -1; } int pthread_setcanceltype(int type, int *oldtype) { (void) type; (void) oldtype; - return 0; + return -1; } void pthread_testcancel(void) { pthread_t self = pthread_self(); if (pthread_sched_threads[self-1]->should_cancel) { - pthread_exit(NULL); + pthread_exit(PTHREAD_CANCELED); } } diff --git a/sys/posix/pthread/pthread_attr.c b/sys/posix/pthread/pthread_attr.c index 9f4f524cda5b72ab91195541f0447a45bc48725b..de37963836e33b9a0998115937dabe8f05f12d20 100644 --- a/sys/posix/pthread/pthread_attr.c +++ b/sys/posix/pthread/pthread_attr.c @@ -1,16 +1,16 @@ -/** - * POSIX implementation of threading. - * +/* * Copyright (C) 2013 Freie Universität Berlin * * This file subject to the terms and conditions of the GNU Lesser General * Public License. See the file LICENSE in the top level directory for more * details. - * - * @ingroup posix + */ + +/** + * @ingroup pthread * @{ - * @file pthread.c - * @brief Implementation of pthread. + * @file + * @brief Thread creation attributes. * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author René Kijewski <kijewski@inf.fu-berlin.de> * @} @@ -147,6 +147,9 @@ int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) { *stacksize = attr->ss_size; + if (*stacksize == 0) { + /* FIXME: the standard says that this function should return the default value if no explicit value was set. */ + } return 0; } diff --git a/sys/posix/pthread/pthread_barrier.c b/sys/posix/pthread/pthread_barrier.c index 591a03ba1da21bec4c512802a76d18b25d459b43..fc4a24913f024f14dc4a74d3f966034a5acbd218 100644 --- a/sys/posix/pthread/pthread_barrier.c +++ b/sys/posix/pthread/pthread_barrier.c @@ -1,19 +1,21 @@ +/* + * POSIX compatible implementation of barriers. + * + * Copyright (C) 2014 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + /** -* POSIX compatible implementation of barriers. -* -* Copyright (C) 2014 Freie Universität Berlin -* -* This file subject to the terms and conditions of the GNU Lesser General -* Public License. See the file LICENSE in the top level directory for more -* details. -* -* @ingroup posix -* @{ -* @file -* @brief Implementation of the pthread barrier. -* @author René Kijewski <kijewski@inf.fu-berlin.de> -* @} -*/ + * @ingroup pthread + * @{ + * @file + * @brief Synchronization barriers. + * @author René Kijewski <kijewski@inf.fu-berlin.de> + * @} + */ #include "sched.h" #include "pthread.h" diff --git a/sys/posix/pthread/pthread_barrierattr.c b/sys/posix/pthread/pthread_barrierattr.c index e6f4e09a568bf60a9f06e3399d4768f4bfff6022..c0b5d96f65305d315061b94a77607acc2ac57bc5 100644 --- a/sys/posix/pthread/pthread_barrierattr.c +++ b/sys/posix/pthread/pthread_barrierattr.c @@ -1,19 +1,21 @@ +/* + * POSIX compatible implementation of barriers. + * + * Copyright (C) 2014 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + /** -* POSIX compatible implementation of barriers. -* -* Copyright (C) 2014 Freie Universität Berlin -* -* This file subject to the terms and conditions of the GNU Lesser General -* Public License. See the file LICENSE in the top level directory for more -* details. -* -* @ingroup posix -* @{ -* @file -* @brief Implementation of the pthread barrier attributes. -* @author René Kijewski <kijewski@inf.fu-berlin.de> -* @} -*/ + * @ingroup pthread + * @{ + * @file + * @brief Attributes for synchronization barriers. + * @author René Kijewski <kijewski@inf.fu-berlin.de> + * @} + */ #include "pthread.h" diff --git a/sys/posix/pthread/pthread_mutex.c b/sys/posix/pthread/pthread_mutex.c index 56219db17536f31ba57b7b12ee62736e0e612505..295d940b6f89f0f033b064af8927ac049ffe14e7 100644 --- a/sys/posix/pthread/pthread_mutex.c +++ b/sys/posix/pthread/pthread_mutex.c @@ -1,16 +1,16 @@ -/** - * POSIX implementation of threading. - * +/* * Copyright (C) 2013 Freie Universität Berlin * * This file subject to the terms and conditions of the GNU Lesser General * Public License. See the file LICENSE in the top level directory for more * details. - * - * @ingroup posix + */ + +/** + * @ingroup pthread * @{ - * @file pthread.c - * @brief Implementation of pthread. + * @file + * @brief Mutual exclusion. * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author René Kijewski <kijewski@inf.fu-berlin.de> * @} @@ -45,7 +45,9 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex) return -1; } - return (mutex_trylock(mutex) != 0); + /* mutex_trylock() returns 1 on success, and 0 otherwise. */ + /* We want the reverse. */ + return 1 - mutex_trylock(mutex); } int pthread_mutex_lock(pthread_mutex_t *mutex) diff --git a/sys/posix/pthread/pthread_mutex_attr.c b/sys/posix/pthread/pthread_mutex_attr.c new file mode 100644 index 0000000000000000000000000000000000000000..c1c9d47bc205a90827a254bd5bff11e96d4e5cdd --- /dev/null +++ b/sys/posix/pthread/pthread_mutex_attr.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @ingroup pthread + * @{ + * @file + * @brief Attributes for pthread mutexes. + * @author René Kijewski <rene.kijewski@fu-berlin.de> + * @} + */ + +#include "pthread.h" + +#include <string.h> + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + if (attr == NULL) { + return EINVAL; + } + + memset(attr, 0, sizeof (*attr)); + return 0; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + if (attr == NULL) { + return EINVAL; + } + + (void) attr; + return 0; +} + +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) +{ + if (attr == NULL || pshared == NULL) { + return EINVAL; + } + + *pshared = attr->pshared; + return 0; +} + +int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) +{ + if (attr == NULL || (pshared != PTHREAD_PROCESS_SHARED && + pshared != PTHREAD_PROCESS_PRIVATE)) { + return EINVAL; + } + + attr->pshared = pshared; + return 0; +} + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + if (attr == NULL || kind == NULL) { + return EINVAL; + } + + *kind = attr->kind; + return 0; +} + +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (attr == NULL || (kind != PTHREAD_MUTEX_NORMAL && + kind != PTHREAD_MUTEX_RECURSIVE && + kind != PTHREAD_MUTEX_ERRORCHECK)) { + return EINVAL; + } + + if (kind != PTHREAD_MUTEX_NORMAL) { + /* only "normal" mutexes are implemented, yet */ + return EINVAL; + } + + attr->kind = kind; + return 0; +} + +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol) +{ + if (attr == NULL || protocol == NULL) { + return EINVAL; + } + + *protocol = attr->protocol; + return 0; +} + +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) +{ + if (attr == NULL || (protocol != PTHREAD_PRIO_NONE && + protocol != PTHREAD_PRIO_INHERIT && + protocol != PTHREAD_PRIO_PROTECT)) { + return EINVAL; + } + + if (protocol != PTHREAD_PRIO_NONE) { + /* priority inheritance is not supported, yet */ + return EINVAL; + } + + attr->protocol = protocol; + return 0; +} + +int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robustness) +{ + if (attr == NULL || robustness == NULL) { + return EINVAL; + } + + *robustness = attr->robustness; + return 0; +} + +int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robustness) +{ + if (attr == NULL || (robustness != PTHREAD_MUTEX_STALLED && + robustness != PTHREAD_MUTEX_ROBUST)) { + return EINVAL; + } + + if (robustness != PTHREAD_MUTEX_STALLED) { + /* robust mutexes are not supported, yet */ + return EINVAL; + } + + attr->robustness = robustness; + return 0; +} diff --git a/sys/posix/pthread/pthread_once.c b/sys/posix/pthread/pthread_once.c index 7863516186a61e9227bdeb3451b41d517c75ac81..9f9d10a70c54866dd3a51330ec88f2a3928240cb 100644 --- a/sys/posix/pthread/pthread_once.c +++ b/sys/posix/pthread/pthread_once.c @@ -1,4 +1,4 @@ -/** +/* * POSIX implementation of threading. * * Copyright (C) 2013 Freie Universität Berlin @@ -6,11 +6,13 @@ * This file subject to the terms and conditions of the GNU Lesser General * Public License. See the file LICENSE in the top level directory for more * details. - * - * @ingroup posix + */ + +/** + * @ingroup pthread * @{ - * @file pthread.c - * @brief Implementation of pthread. + * @file + * @brief Singletons features / single-shot execution. * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author René Kijewski <kijewski@inf.fu-berlin.de> * @} diff --git a/sys/posix/pthread/pthread_spin.c b/sys/posix/pthread/pthread_spin.c index 351eccabd545349b3eecde7b7b14c2ad8422fcbc..5bc2ee839ad807b253e115025c1a3fb0e4eb6063 100644 --- a/sys/posix/pthread/pthread_spin.c +++ b/sys/posix/pthread/pthread_spin.c @@ -1,25 +1,30 @@ -/** - * POSIX implementation of threading. - * +/* * Copyright (C) 2013 Freie Universität Berlin * * This file subject to the terms and conditions of the GNU Lesser General * Public License. See the file LICENSE in the top level directory for more * details. - * - * @ingroup posix + */ + +/** + * @ingroup pthread * @{ - * @file pthread.c - * @brief Implementation of pthread. + * @file + * @brief Spin locks. * @author Christian Mehlis <mehlis@inf.fu-berlin.de> * @author René Kijewski <kijewski@inf.fu-berlin.de> * @} */ #include "pthread.h" +#include "atomic.h" int pthread_spin_init(pthread_spinlock_t *lock, int pshared) { + if (lock == NULL) { + return EINVAL; + } + (void) pshared; *lock = 0; return 0; @@ -27,29 +32,40 @@ int pthread_spin_init(pthread_spinlock_t *lock, int pshared) int pthread_spin_destroy(pthread_spinlock_t *lock) { + if (lock == NULL) { + return EINVAL; + } + (void) lock; return 0; } int pthread_spin_lock(pthread_spinlock_t *lock) { - while (*lock) { - ; /* spin */ + if (lock == NULL) { + return EINVAL; + } + + while (atomic_set_return((unsigned *) lock, 1) != 0) { + /* spin */ } return 0; } int pthread_spin_trylock(pthread_spinlock_t *lock) { - if (*lock) { - return 0; + if (lock == NULL) { + return EINVAL; } - return -1; + return atomic_set_return((unsigned *) lock, 1) == 0 ? 0 : EBUSY; } int pthread_spin_unlock(pthread_spinlock_t *lock) { - --*lock; - return 0; + if (lock == NULL) { + return EINVAL; + } + + return atomic_set_return((unsigned *) lock, 0) != 0 ? 0 : EPERM; }