sema.h
4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.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.
*/
/**
* @defgroup sys_sema Semaphores
* @ingroup sys
* @brief Lightweight semaphore implementation
* @{
*
* @file
* @brief Semaphore definitions
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Christian Mehlis <mehlis@inf.fu-berlin.de>
* @author René Kijewski <kijewski@inf.fu-berlin.de>
*/
#ifndef SEM_H_
#define SEM_H_
#include "msg.h"
#include "priority_queue.h"
#include "timex.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Creates semaphore statically.
*
* @param[in] value Initial value for the semaphore.
*
* @return Statically initialized semaphore.
*/
#define SEMA_CREATE(value) { (value), PRIORITY_QUEUE_INIT }
/**
* @brief A Semaphore.
*/
typedef struct {
volatile unsigned int value; /**< value of the semaphore */
priority_queue_t queue; /**< list of threads waiting for the semaphore */
} sema_t;
/**
* @brief Creates semaphore dynamically.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
* The Open Group Base Specifications Issue 7, sem_init()
* </a> (without `pshared` parameter)
*
* @param[out] sema The created semaphore.
* @param[in] value Initial value for the semaphore.
*
* @return 0 on success.
* @return -EINVAL, if semaphore is invalid.
*/
int sema_create(sema_t *sema, unsigned int value);
/**
* @brief Destroys a semaphore.
*
* @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html">
* The Open Group Base Specifications Issue 7, sem_destroy()
* </a>
*
* @param[in] sema The semaphore to destroy.
*
* @return 0 on success.
* @return -EINVAL, if semaphore is invalid.
*/
int sema_destroy(sema_t *sema);
/**
* @brief Wait for a semaphore being posted.
*
* @pre Message queue of active thread is initialized (see @ref msg_init_queue()).
*
* @param[in] sema A semaphore.
* @param[in] timeout Time in microseconds until the semaphore times out. 0 for no timeout.
* @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN).
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -ETIMEDOUT, if the semaphore times out.
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the thread received a message while waiting for the lock.
*/
int sema_wait_timed_msg(sema_t *sema, uint64_t timeout, msg_t *msg);
/**
* @brief Wait for a semaphore being posted (without timeout).
*
* @param[in] sema A semaphore.
* @param[out] msg Container for a spurious message during the timed wait (result == -EAGAIN).
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the thread received a message while waiting for the lock.
*/
static inline int sema_wait_msg(sema_t *sema, msg_t *msg)
{
return sema_wait_timed_msg(sema, 0, msg);
}
/**
* @brief Wait for a semaphore being posted (dropping spurious messages).
* @details Any spurious messages received while waiting for the semaphore are silently dropped.
*
* @param[in] sema A semaphore.
* @param[in] timeout Time in microseconds until the semaphore times out. 0 for no timeout.
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -ETIMEDOUT, if the semaphore times out.
* @return -ECANCELED, if the semaphore was destroyed.
*/
int sema_wait_timed(sema_t *sema, uint64_t timeout);
/**
* @brief Wait for a semaphore being posted (without timeout, dropping spurious messages).
*
* @param[in] sema A semaphore.
*
* @return 0 on success
* @return -EINVAL, if semaphore is invalid.
* @return -ECANCELED, if the semaphore was destroyed.
*/
static inline int sema_wait(sema_t *sema)
{
return sema_wait_timed(sema, 0);
}
/**
* @brief Signal semaphore.
*
* @param[in] sema A semaphore.
*
* @return 0, on success
* @return -EINVAL, if semaphore is invalid.
* @return -EOVERFLOW, if the semaphore's value would overflow.
*/
int sema_post(sema_t *sema);
#ifdef __cplusplus
}
#endif
#endif /* SEM_H_ */
/** @} */