1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/posix/pthread/include/pthread_rwlock.h
Oleg Hahm 037571445c Merge pull request #1974 from OlegHahm/cleanup_licenses
licenses: fix miss-spelled & missing boiler plates
2014-11-10 19:53:40 +01:00

185 lines
6.4 KiB
C

/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
*
* 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 Implementation of a fair, POSIX conforming reader/writer lock.
* @note Do not include this header file directly, but pthread.h.
*/
#ifndef __SYS__POSIX__PTHREAD_RWLOCK__H
#define __SYS__POSIX__PTHREAD_RWLOCK__H
#include "priority_queue.h"
#include "tcb.h"
#include <errno.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A fair reader writer lock.
* @details The implementation ensures that readers and writers of the same priority
* won't starve each other.
* E.g. no new readers will get into the critical section
* if a writer of the same or a higher priority already waits for the lock.
*/
typedef struct pthread_rwlock
{
/**
* @brief The current amount of reader inside the critical section.
* @details
* * `== 0`: no thread is in the critical section.
* * `> 0`: the number of readers currently in the critical section.
* * `< 0`: a writer is currently in the critical section.
*/
int readers;
/**
* @brief Queue of waiting threads.
*/
priority_queue_t queue;
/**
* @brief Provides mutual exclusion on reading and writing on the structure.
*/
mutex_t mutex;
} pthread_rwlock_t;
/**
* @brief Internal structure that stores one waiting thread.
*/
typedef struct __pthread_rwlock_waiter_node
{
bool is_writer; /**< `false`: reader; `true`: writer */
tcb_t *thread; /**< waiting thread */
priority_queue_node_t qnode; /**< Node to store in `pthread_rwlock_t::queue`. */
bool continue_; /**< This is not a spurious wakeup. */
} __pthread_rwlock_waiter_node_t;
/**
* @brief Initialize a reader/writer lock.
* @details A zeroed out datum is initialized.
* @param[in,out] rwlock Lock to initialize.
* @param[in] attr Unused.
* @returns `0` on success.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
/**
* @brief Destroy a reader/writer lock.
* @details This is a no-op.
* Destroying a reader/writer lock while a thread holds it, or
* there are threads waiting for it causes undefined behavior.
* Datum must be reinitialized before using it again.
* @param[in] rwlock Lock to destroy.
* @returns `0` on success.
* `EINVAL` if `rwlock == NULL`.
* `EBUSY` if the lock was in use.
*/
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
/**
* @brief Lock a reader/writer lock for reading.
* @details This function may block.
* @param[in] rwlock Lock to acquire for reading.
* @returns `0` if the lock could be acquired.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
/**
* @brief Try to lock a reader/writer lock for reader.
* @details This function won't block.
* @param[in] rwlock Lock to acquire for reading.
* @returns `0` if the lock could be acquired.
* `EBUSY` if acquiring the lock cannot be done without blocking.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
/**
* @brief Try to acquire a read lock in a given timeframe
* @param[in] rwlock Lock to acquire for reading.
* @param[in] abstime Maximum timestamp when to wakeup, absolute.
* @returns `0` if the lock could be acquired.
* `EDEADLK` if the lock could not be acquired in the given timeframe.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *abstime);
/**
* @brief Lock a reader/writer lock for writing.
* @details This function may block.
* @param[in] rwlock Lock to acquire for writing.
* @returns `0` if the lock could be acquired.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
/**
* @brief Try to lock a reader/writer lock for writing.
* @details This function won't block.
* @param[in] rwlock Lock to acquire for writing.
* @returns `0` if the lock could be acquired.
* `EBUSY` if acquiring the lock cannot be done without blocking.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
/**
* @brief Try to acquire a write lock in a given timeframe
* @param[in] rwlock Lock to acquire for writing.
* @param[in] abstime Maximum timestamp when to wakeup, absolute.
* @returns `0` if the lock could be acquired.
* `EDEADLK` if the lock could not be acquired in the given timeframe.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *abstime);
/**
* @brief Unlock the reader/writer lock.
* @details Must only be used if the lock is currently held.
* You may release the lock out of another thread, but the *lock*, *operate*, *unlock* logic must not be broken.
* @param[in] rwlock Lock to release
* @returns `0` on success.
* `EPERM` if the lock was not held for any operation.
* `EINVAL` if `rwlock == NULL`.
*/
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
/**
* @brief Internal function to determine of the lock can be acquired for reading.
* @param[in] rwlock Lock to query.
* @returns `false` if locking for reading is possible without blocking.
*/
bool __pthread_rwlock_blocked_readingly(const pthread_rwlock_t *rwlock);
/**
* @brief Internal function to determine of the lock can be acquired for writing.
* @param[in] rwlock Lock to query.
* @returns `false` if locking for writing is possible without blocking.
*/
bool __pthread_rwlock_blocked_writingly(const pthread_rwlock_t *rwlock);
#ifdef __cplusplus
}
#endif
#endif
/**
* @}
*/