pthread_barrier.h 4.52 KB
/*
 * Copyright (C) 2014 Freie Universität Berlin
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup pthread
 * @{
 * @file
 * @brief   Synchronization barriers.
 * @note    Do not include this header file directly, but pthread.h.
 */

#ifndef PTHREAD_BARRIER_H
#define PTHREAD_BARRIER_H

#include "mutex.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @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_PRIVATE
 * @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.
 */
typedef struct pthread_barrier_waiting_node
{
    struct pthread_barrier_waiting_node *next; /**< The next waiting thread. */
    kernel_pid_t pid; /**< The current thread to wake up. */
    volatile int cont; /**< 0 = spurious wake up, 1 = wake up */
} pthread_barrier_waiting_node_t;

/**
 * @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 pthread_barrier_t::count.
 */
typedef struct
{
    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 for N more threads before waking everyone up. */
} pthread_barrier_t;

/**
 * @brief     Details for a pthread_barrier_t.
 * @details   RIOT does not need this structure, because it is a single process OS.
 *            This is only here to POSIX compatibility.
 */
typedef struct
{
    int pshared; /**< See pthread_barrierattr_setpshared() and pthread_barrierattr_getpshared(). */
} pthread_barrierattr_t;

/**
 * @brief     Initializes a pthread_barrier_t
 * @param     barrier   Datum to initialize
 * @param     attr      (unused)
 * @param     count     Number of thread to wait for
 * @returns   0, the invocation cannot fail
 */
int pthread_barrier_init(pthread_barrier_t *barrier,
                         const pthread_barrierattr_t *attr,
                         unsigned int count);

/**
 * @brief     Destroys a pthread_barrier_t
 * @details   To use the barrier again you will need to call pthread_barrier_init() again.
 *            Destroying a barrier while threads are currently waiting for it causes indefined behavior.
 * @param     barrier   Barrier to destoy
 * @returns   0, the invocation cannot fail
 */
int pthread_barrier_destroy(pthread_barrier_t *barrier);

/**
 * @brief     Waiting on a synchronization barrier
 * @details   The barrier need to be initialized with pthread_barrier_init().
 * @param     barrier   Barrier to wait for
 * @returns   0, the invocation cannot fail
 */
int pthread_barrier_wait(pthread_barrier_t *barrier);

/**
 * @brief     Initialize a pthread_barrierattr_t
 * @details   A zeroed out datum is initialized.
 * @param     attr   Datum to initialize.
 * @returns   0, the invocation cannot fail
 */
int pthread_barrierattr_init(pthread_barrierattr_t *attr);

/**
 * @brief     Destroy a pthread_barrierattr_t
 * @details   This function does nothing.
 * @param     attr   Datum to destroy
 * @returns   0, the invocation cannot fail
 */
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);

/**
 * @brief     Returns whether the barrier attribute was set to be shared
 * @param     attr      Barrier attribute to read
 * @param     pshared   The value previously stored with pthread_barrierattr_setpshared().
 * @returns   0, the invocation cannot fail
 */
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared);

/**
 * @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
 * @returns   0, the invocation cannot fail
 */
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);

#ifdef __cplusplus
}
#endif

#endif /* PTHREAD_BARRIER_H */

/**
 * @}
 */