123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2010-10-26 Bernard the first version
- */
- #include <pthread.h>
- int pthread_barrierattr_destroy(pthread_barrierattr_t *attr)
- {
- if (!attr)
- return EINVAL;
- return 0;
- }
- RTM_EXPORT(pthread_barrierattr_destroy);
- int pthread_barrierattr_init(pthread_barrierattr_t *attr)
- {
- if (!attr)
- return EINVAL;
- *attr = PTHREAD_PROCESS_PRIVATE;
- return 0;
- }
- RTM_EXPORT(pthread_barrierattr_init);
- int pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr,
- int *pshared)
- {
- if (!attr)
- return EINVAL;
- *pshared = (int)*attr;
- return 0;
- }
- RTM_EXPORT(pthread_barrierattr_getpshared);
- int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared)
- {
- if (!attr)
- return EINVAL;
- if (pshared == PTHREAD_PROCESS_PRIVATE)
- {
- *attr = PTHREAD_PROCESS_PRIVATE;
- return 0;
- }
- return EINVAL;
- }
- RTM_EXPORT(pthread_barrierattr_setpshared);
- /**
- * @brief Destroys a barrier object.
- *
- * The `pthread_barrier_destroy` function releases any resources associated
- * with the specified barrier object. After a barrier has been destroyed,
- * it cannot be used again unless it is reinitialized using `pthread_barrier_init`.
- *
- * @param[in] barrier
- * A pointer to an initialized `pthread_barrier_t` object to be destroyed.
- *
- * @return
- * - `0` on success.
- * - `EINVAL` if the `barrier` is invalid or uninitialized.
- * - `EBUSY` if there are threads currently blocked on the barrier.
- *
- * @note
- * - Ensure that no threads are blocked on the barrier before calling this function.
- * - Attempting to destroy a barrier that is still in use results in undefined behavior.
- *
- * @warning
- * Destroying a barrier without ensuring it is no longer in use can lead to
- * resource leaks or undefined program behavior.
- *
- * @see pthread_barrier_init, pthread_barrier_wait
- */
- int pthread_barrier_destroy(pthread_barrier_t *barrier)
- {
- rt_err_t result;
- if (!barrier)
- return EINVAL;
- /* Lock the internal mutex to safely check the barrier's state*/
- result = pthread_mutex_lock(&(barrier->mutex));
- if (result != 0)
- return result;
- /* Check if any threads are currently waiting on the barrier*/
- if (barrier->count != 0)
- {
- pthread_mutex_unlock(&(barrier->mutex));
- return EBUSY; /* Threads are still waiting*/
- }
- /* Free resources associated with the barrier*/
- result = pthread_mutex_unlock(&(barrier->mutex));
- if (result != 0)
- {
- return result; /* Return mutex unlock error*/
- }
- result = pthread_mutex_destroy(&(barrier->mutex));
- if (result != 0)
- {
- return result; /* Return mutex destroy error*/
- }
- result = pthread_cond_destroy(&(barrier->cond));
- return result;
- }
- RTM_EXPORT(pthread_barrier_destroy);
- /**
- * @brief Initializes a barrier for synchronizing threads.
- *
- * The `pthread_barrier_init` function initializes a barrier object
- * that allows a specified number of threads to synchronize at a barrier point.
- * Each thread waits at the barrier until the required number of threads have called
- * `pthread_barrier_wait`.
- *
- * @param[out] barrier
- * A pointer to the `pthread_barrier_t` object to be initialized.
- * This object must not already be initialized.
- *
- * @param[in] attr
- * A pointer to a `pthread_barrierattr_t` object that specifies
- * attributes for the barrier (e.g., process-shared or process-private).
- * If NULL, the default attributes are used.
- *
- * @param[in] count
- * The number of threads that must call `pthread_barrier_wait`
- * before any of them successfully return from the barrier.
- *
- * @return
- * - `0` on success.
- * - `EINVAL` if the `count` is zero or `barrier` is invalid.
- *
- * @note The barrier must be destroyed using `pthread_barrier_destroy`
- * when it is no longer needed.
- *
- * @warning If `count` is set to zero, the behavior is undefined.
- *
- * @see pthread_barrier_wait, pthread_barrier_destroy
- */
- int pthread_barrier_init(pthread_barrier_t *barrier,
- const pthread_barrierattr_t *attr,
- unsigned count)
- {
- if (!barrier)
- return EINVAL;
- if (attr && (*attr != PTHREAD_PROCESS_PRIVATE))
- return EINVAL;
- if (count == 0)
- return EINVAL;
- barrier->count = count;
- pthread_cond_init(&(barrier->cond), NULL);
- pthread_mutex_init(&(barrier->mutex), NULL);
- return 0;
- }
- RTM_EXPORT(pthread_barrier_init);
- /**
- * @brief Synchronizes threads at a barrier.
- *
- * The `pthread_barrier_wait` function blocks the calling thread at the specified
- * barrier until the required number of threads have reached the barrier. Once
- * the required number of threads have called this function, all threads are
- * unblocked and can proceed.
- *
- * @param[in] barrier
- * A pointer to an initialized `pthread_barrier_t` object representing the barrier
- * at which threads will synchronize.
- *
- * @return
- * - `0` for all threads except one.
- * - `EINVAL` - The `barrier` is invalid or uninitialized.
- *
- * @note
- * - All threads participating in the barrier must call `pthread_barrier_wait`
- * before any of them are released.
- *
- * @warning
- * Ensure that the number of threads specified during the barrier's initialization
- * matches the number of threads calling this function, otherwise the program
- * may hang indefinitely.
- *
- * @see pthread_barrier_init, pthread_barrier_destroy
- */
- int pthread_barrier_wait(pthread_barrier_t *barrier)
- {
- rt_err_t result;
- if (!barrier)
- return EINVAL;
- result = pthread_mutex_lock(&(barrier->mutex));
- if (result != 0)
- return EINVAL;
- if (barrier->count == 0)
- result = EINVAL;
- else
- {
- barrier->count -= 1;
- if (barrier->count == 0) /* broadcast condition */
- pthread_cond_broadcast(&(barrier->cond));
- else
- pthread_cond_wait(&(barrier->cond), &(barrier->mutex));
- }
- pthread_mutex_unlock(&(barrier->mutex));
- return result;
- }
- RTM_EXPORT(pthread_barrier_wait);
|