forked from apache/nuttx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsemaphore.h
255 lines (213 loc) · 8.18 KB
/
semaphore.h
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/****************************************************************************
* include/semaphore.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_SEMAPHORE_H
#define __INCLUDE_SEMAPHORE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <limits.h>
#include <time.h>
#include <nuttx/queue.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Values for protocol attribute */
#define SEM_PRIO_NONE 0
#define SEM_PRIO_INHERIT 1
#define SEM_PRIO_PROTECT 2
#define SEM_PRIO_MASK 3
#define SEM_TYPE_MUTEX 4
/* Value returned by sem_open() in the event of a failure. */
#define SEM_FAILED NULL
#ifndef CONFIG_SEM_PREALLOCHOLDERS
# define CONFIG_SEM_PREALLOCHOLDERS 0
#endif
/****************************************************************************
* Public Type Declarations
****************************************************************************/
/* This structure contains information about the holder of a semaphore */
#ifdef CONFIG_PRIORITY_INHERITANCE
struct tcb_s; /* Forward reference */
struct sem_s;
struct semholder_s
{
#if CONFIG_SEM_PREALLOCHOLDERS > 0
FAR struct semholder_s *flink; /* List of semaphore's holder */
#endif
FAR struct semholder_s *tlink; /* List of task held semaphores */
FAR struct sem_s *sem; /* Ths corresponding semaphore */
FAR struct tcb_s *htcb; /* Ths corresponding TCB */
int16_t counts; /* Number of counts owned by this holder */
};
#if CONFIG_SEM_PREALLOCHOLDERS > 0
# define SEMHOLDER_INITIALIZER {NULL, NULL, NULL, NULL, 0}
# define INITIALIZE_SEMHOLDER(h) \
do { \
(h)->flink = NULL; \
(h)->tlink = NULL; \
(h)->sem = NULL; \
(h)->htcb = NULL; \
(h)->counts = 0; \
} while (0)
#else
# define SEMHOLDER_INITIALIZER {NULL, NULL, NULL, 0}
# define INITIALIZE_SEMHOLDER(h) \
do { \
(h)->tlink = NULL; \
(h)->sem = NULL; \
(h)->htcb = NULL; \
(h)->counts = 0; \
} while (0)
#endif
#endif /* CONFIG_PRIORITY_INHERITANCE */
#define SEM_WAITLIST_INITIALIZER {NULL, NULL}
/* This is the generic semaphore structure. */
struct sem_s
{
volatile int16_t semcount; /* >0 -> Num counts available */
/* <0 -> Num tasks waiting for semaphore */
/* If priority inheritance is enabled, then we have to keep track of which
* tasks hold references to the semaphore.
*/
uint8_t flags; /* See SEM_PRIO_* definitions */
dq_queue_t waitlist;
#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_PREALLOCHOLDERS > 0
FAR struct semholder_s *hhead; /* List of holders of semaphore counts */
# else
struct semholder_s holder; /* Slot for old and new holder */
# endif
#endif
#ifdef CONFIG_PRIORITY_PROTECT
uint8_t ceiling; /* The priority ceiling owned by mutex */
uint8_t saved; /* The saved priority of thread before boost */
#endif
};
typedef struct sem_s sem_t;
/* Initializers */
#ifdef CONFIG_PRIORITY_INHERITANCE
# if CONFIG_SEM_PREALLOCHOLDERS > 0
/* semcount, flags, waitlist, hhead */
# define SEM_INITIALIZER(c) \
{(c), 0, SEM_WAITLIST_INITIALIZER, NULL}
# else
/* semcount, flags, waitlist, holder[2] */
# define SEM_INITIALIZER(c) \
{(c), 0, SEM_WAITLIST_INITIALIZER, SEMHOLDER_INITIALIZER}
# endif
#else
/* semcount, flags, waitlist */
# define SEM_INITIALIZER(c) \
{(c), 0, SEM_WAITLIST_INITIALIZER}
#endif
#define SEM_WAITLIST(sem) (&((sem)->waitlist))
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Counting Semaphore Interfaces (based on POSIX APIs) */
int sem_init(FAR sem_t *sem, int pshared, unsigned int value);
int sem_destroy(FAR sem_t *sem);
int sem_wait(FAR sem_t *sem);
int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime);
int sem_clockwait(FAR sem_t *sem, clockid_t clockid,
FAR const struct timespec *abstime);
int sem_trywait(FAR sem_t *sem);
int sem_post(FAR sem_t *sem);
int sem_getvalue(FAR sem_t *sem, FAR int *sval);
#ifdef CONFIG_FS_NAMED_SEMAPHORES
FAR sem_t *sem_open(FAR const char *name, int oflag, ...);
int sem_close(FAR sem_t *sem);
int sem_unlink(FAR const char *name);
#endif
/****************************************************************************
* Name: sem_setprotocol
*
* Description:
* Set semaphore protocol attribute.
*
* One particularly important use of this function is when a semaphore
* is used for inter-task communication like:
*
* TASK A TASK B
* sem_init(sem, 0, 0);
* sem_wait(sem);
* sem_post(sem);
* Awakens as holder
*
* In this case priority inheritance can interfere with the operation of
* the semaphore. The problem is that when TASK A is restarted it is a
* holder of the semaphore. However, it never calls sem_post(sem) so it
* becomes *permanently* a holder of the semaphore and may have its
* priority boosted when any other task tries to acquire the semaphore.
*
* The fix is to call sem_setprotocol(SEM_PRIO_NONE) immediately after
* the sem_init() call so that there will be no priority inheritance
* operations on this semaphore.
*
* Input Parameters:
* sem - A pointer to the semaphore whose attributes are to be
* modified
* protocol - The new protocol to use
*
* Returned Value:
* This function is exposed as a non-standard application interface. It
* returns zero (OK) if successful. Otherwise, -1 (ERROR) is returned and
* the errno value is set appropriately.
*
****************************************************************************/
int sem_setprotocol(FAR sem_t *sem, int protocol);
/****************************************************************************
* Name: sem_getprotocol
*
* Description:
* Return the value of the semaphore protocol attribute.
*
* Input Parameters:
* sem - A pointer to the semaphore whose attributes are to be
* queried.
* protocol - The user provided location in which to store the protocol
* value.
*
* Returned Value:
* This function is exposed as a non-standard application interface. It
* returns zero (OK) if successful. Otherwise, -1 (ERROR) is returned and
* the errno value is set appropriately.
*
****************************************************************************/
int sem_getprotocol(FAR sem_t *sem, FAR int *protocol);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_SEMAPHORE_H */