• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: 信号量模块对外头文件。
14  */
15 #ifndef PRT_SEM_H
16 #define PRT_SEM_H
17 
18 #include "prt_module.h"
19 #include "prt_errno.h"
20 
21 #ifdef __cplusplus
22 #if __cplusplus
23 extern "C" {
24 #endif
25 #endif /* __cplusplus */
26 
27 /*
28  * 信号量错误码:初始化信号量内存不足。
29  *
30  * 值: 0x02000701
31  *
32  * 解决方案: 可以将私有的静态内存空间配大。
33  */
34 #define OS_ERRNO_SEM_NO_MEMORY OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x01)
35 
36 /*
37  * 信号量错误码:信号量句柄非法(错误或已删除)。
38  *
39  * 值: 0x02000702
40  *
41  * 解决方案: 查看输入的信号量句柄值是否有效。
42  */
43 #define OS_ERRNO_SEM_INVALID OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x02)
44 
45 /*
46  * 信号量错误码:输入指针为空。
47  *
48  * 值: 0x02000703
49  *
50  * 解决方案: 查看指针是否输入为空。
51  */
52 #define OS_ERRNO_SEM_PTR_NULL OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x03)
53 
54 /*
55  * 信号量错误码:没有空闲信号量。
56  *
57  * 值: 0x02000704
58  *
59  * 解决方案: 查看信号量模块是否打开,或配置更多信号量。
60  */
61 #define OS_ERRNO_SEM_ALL_BUSY OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x04)
62 
63 /*
64  * 信号量错误码:信号量没有可用资源且Pend时设为不等待(等待时间为0)时获取信号量失败。
65  *
66  * 值: 0x02000705
67  *
68  * 解决方案: 无。
69  */
70 #define OS_ERRNO_SEM_UNAVAILABLE OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x05)
71 
72 /*
73  * 信号量错误码:禁止中断处理函数阻塞于信号量。
74  *
75  * 值: 0x02000706
76  *
77  * 解决方案: 查看是否在中断中Pend信号量。
78  */
79 #define OS_ERRNO_SEM_PEND_INTERR OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x06)
80 
81 /*
82  * 信号量错误码:任务切换锁定时,禁止任务阻塞于信号量。
83  *
84  * 值: 0x02000707
85  *
86  * 解决方案: 不要在锁任务时pend没有资源可用的信号量。
87  */
88 #define OS_ERRNO_SEM_PEND_IN_LOCK OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x07)
89 
90 /*
91  * 信号量错误码:信号量等待超时。
92  *
93  * 值: 0x02000708
94  *
95  * 解决方案: 无。
96  */
97 #define OS_ERRNO_SEM_TIMEOUT OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x08)
98 
99 /*
100  * 信号量错误码:信号量发生溢出。
101  *
102  * 值: 0x02000709
103  *
104  * 解决方案: 查看输入的信号量计数值是否有效。
105  */
106 #define OS_ERRNO_SEM_OVERFLOW OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x09)
107 
108 /*
109  * 信号量错误码:信号量删除和重设当前值时有阻塞于信号量的任务。
110  *
111  * 值: 0x0200070a
112  *
113  * 解决方案: 如果当前信号量有任务阻塞,不能进行删除和重设计数值操作。
114  */
115 #define OS_ERRNO_SEM_PENDED OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0a)
116 
117 /*
118  * 信号量错误码:注册核内信号量个数为0导致注册失败。
119  *
120  * 值: 0x0200070b
121  *
122  * 解决方案: 查看信号量模块配置的最大个数是否为0。
123  */
124 #define OS_ERRNO_SEM_REG_ERROR OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0b)
125 
126 /*
127  * 信号量错误码:调用#PRT_SemGetPendList时,指定的内存空间不足,无法存入全部的阻塞任务PID。
128  *
129  * 值: 0x0200070c
130  *
131  * 解决方案: 建议将数组长度配置为(#OS_TSK_MAX_SUPPORT_NUM + 1) * 4。
132  */
133 #define OS_ERRNO_SEM_INPUT_BUF_NOT_ENOUGH OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0c)
134 
135 /*
136  * 信号量错误码:调用#PRT_SemGetPendList时,输入指针为空或者bufLen小于4。
137  *
138  * 值: 0x0200070d
139  *
140  * 解决方案: 出参不能为NULL,指定的缓存长度不能小于4。
141  */
142 #define OS_ERRNO_SEM_INPUT_ERROR OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0d)
143 
144 /*
145  * 信号量错误码:获取信号量详细信息时出参结构体指针为NULL。
146  *
147  * 值: 0x0200070e
148  *
149  * 解决方案: 用来保存信号量详细信息的结构体指针不能为NULL。
150  */
151 #define OS_ERRNO_SEM_INFO_NULL OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0e)
152 
153 /*
154  * 信号量错误码:获取当前信号量计数时传入的出参为NULL。
155  *
156  * 值: 0x0200070f
157  *
158  * 解决方案: 互斥型信号量的唤醒方式不能为FIFO。
159  */
160 #define OS_ERRNO_SEM_COUNT_GET_PTR_NULL OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x0f)
161 
162 /*
163  * 信号量错误码:非当前互斥信号量的持有者释放该信号量。
164  *
165  * 值: 0x02000710
166  *
167  * 解决方案: 互斥信号量只能由其持有者释放,即互斥信号量的PV操作必须配对使用。
168  */
169 #define OS_ERRNO_SEM_MUTEX_NOT_OWNER_POST OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x10)
170 
171 /*
172  * 信号量错误码:在中断中释放互斥型信号量。
173  *
174  * 值: 0x02000711
175  *
176  * 解决方案: 只能在任务中对互斥型信号量进行PV操作。
177  */
178 #define OS_ERRNO_SEM_MUTEX_POST_INTERR OS_ERRNO_BUILD_ERROR(OS_MID_SEM, 0x11)
179 
180 /*
181  * 信号量等待时间设定:表示不等待。
182  */
183 #define OS_NO_WAIT 0
184 
185 /*
186  * 信号量等待时间设定:表示永久等待。
187  */
188 #define OS_WAIT_FOREVER 0xFFFFFFFF
189 
190 /*
191  * 二进制信号量空闲状态,互斥型信号量初始计数值。
192  */
193 #define OS_SEM_FULL  1
194 
195 /*
196  * 二进制信号量占用状态,同步型信号量初始计数值。
197  */
198 #define OS_SEM_EMPTY 0
199 
200 /*
201  * 计数型信号量最大计数值。
202  */
203 #define OS_SEM_COUNT_MAX 0xFFFFFFFE
204 
205 /*
206  * 信号量不被任何任务持有,处于空闲状态。
207  */
208 #define OS_INVALID_OWNER_ID 0xFFFFFFFE
209 
210 /*
211  * 信号量句柄类型定义。
212  */
213 typedef U16 SemHandle;
214 
215 /*
216  * 信号量类型。
217  */
218 /* 计数型信号量 */
219 #define SEM_TYPE_COUNT 0
220 /* 二进制信号量 */
221 #define SEM_TYPE_BIN 1
222 
223 /*
224  * 信号量模块被阻塞线程唤醒方式。
225  */
226 enum SemMode {
227     SEM_MODE_FIFO,  // 信号量FIFO唤醒模式
228     SEM_MODE_PRIOR, // 信号量优先级唤醒模式
229     SEM_MODE_BUTT   // 信号量非法唤醒方式
230 };
231 
232 /*
233  * 信号量模块配置信息的结构体定义。
234  */
235 struct SemModInfo {
236     /* 最大支持的信号量数 */
237     U16 maxNum;
238     /* 保留 */
239     U16 reserved;
240 };
241 
242 /*
243  * 信号量模块获取信号量详细信息时的信息结构体。
244  */
245 struct SemInfo {
246     /* 信号量计数 */
247     U32 count;
248     /* 信号量占用者,对于计数型信号量,记录的是最后一次信号量获得者;如果没有被任务获得,则为OS_THREAD_ID_INVALID */
249     U32 owner;
250     /* 信号量唤醒方式,为SEM_MODE_FIFO或SEM_MODE_PRIOR */
251     enum SemMode mode;
252     /* 信号量类型,为SEM_TYPE_COUNT(计数型)或SEM_TYPE_BIN(互斥型) */
253     U32 type;
254 };
255 
256 /*
257  * @brief 创建一个计数型信号量。
258  *
259  * @par 描述
260  * 根据用户指定的计数值,创建一个计数型信号量,设定初始计数器数值,唤醒方式为FIFO。
261  * @attention
262  * <ul><li>创建是否成功会受到"核内信号量裁剪开关"和"最大支持信号量"配置项的限制。</li></ul>
263  *
264  * @param count     [IN]  类型#U32,计数器初始值,取值范围为[0, 0xFFFFFFFE]。
265  * @param semHandle [OUT] 类型#SemHandle *,输出信号量句柄。
266  *
267  * @retval #OS_OK  0x00000000,操作成功。
268  * @retval #其它值,操作失败。
269  * @par 依赖
270  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
271  * @see PRT_SemDelete
272  */
273 extern U32 PRT_SemCreate(U32 count, SemHandle *semHandle);
274 
275 /*
276  * @brief 删除一个信号量。
277  *
278  * @par 描述
279  * 删除用户传入的信号量句柄指定的信号量,如果有任务阻塞于该信号量,则删除失败。
280  * @attention  无
281  *
282  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
283  *
284  * @retval #OS_OK  0x00000000,操作成功。
285  * @retval #其它值,操作失败。
286  * @par 依赖
287  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
288  * @see PRT_SemCreate
289  */
290 extern U32 PRT_SemDelete(SemHandle semHandle);
291 
292 /*
293  * @brief 获取信号量计数器数值。
294  *
295  * @par 描述
296  * 根据用户输入信号量句柄和计数值,获取信号量计数器数值。
297  * @attention 无
298  *
299  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
300  * @param semCnt    [OUT] 类型#U32 *,保存信号量计数值指针。
301  *
302  * @retval #OS_OK  0x00000000,获取信号量计数器值成功。
303  * @retval #其它值,获取失败。
304  * @par 依赖
305  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
306  * @see PRT_SemCreate | PRT_SemGetInfo
307  */
308 extern U32 PRT_SemGetCount(SemHandle semHandle, U32 *semCnt);
309 
310 /*
311  * @brief 等待一个信号量。
312  *
313  * @par 描述
314  * 等待用户传入信号量句柄指定的信号量,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,
315  * 等待其他线程发布该信号量,等待超时时间可设定。
316  * @attention
317  * <ul>
318  * <li>在osStart之前不能调用该接口。</li>
319  * <li>等待时间可以选择零等待、等待特定时间、永久等待。</li>
320  * <li>该接口只能被任务调用。</li>
321  * <li>在锁任务情况下,用户要PEND信号量,要保证当前有可用信号量资源。</li>
322  * </ul>
323  *
324  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
325  * @param timeout   [IN]  类型#U32,等待时间限制,单位为tick,取值范围为[0, 0xffffffff]。#OS_NO_WAIT或0表示不等待,
326  * #OS_WAIT_FOREVER或0xffffffff表示永久等待。
327  *
328  * @retval #OS_OK  0x00000000,操作成功。
329  * @retval #其它值,操作失败。
330  * @par 依赖
331  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
332  * @see PRT_SemPost
333  */
334 extern U32 PRT_SemPend(SemHandle semHandle, U32 timeout);
335 
336 /*
337  * @brief 发布指定的信号量。
338  *
339  * @par 描述
340  * 发布指定的信号量,若没有任务等待该信号量,则直接将计数器加1返回。
341  * 否则根据唤醒方式唤醒相应的阻塞任务,FIFO方式唤醒最早阻塞的任务,优先级方式唤醒阻塞在此信号量的最高优先级任务。
342  * @attention
343  * <ul>
344  * <li>在osStart之前不能调用该接口。</li>
345  * <li>在未锁任务的情况下,如果唤醒的任务优先级高于当前任务,则会立刻发生任务切换。</li>
346  * <li>发生任务切换时,如果支持优先级唤醒方式,且创建信号量时指定唤醒方式为优先级,
347  * 则唤醒阻塞在该信号量上的最高优先级任务。</li>
348  * </ul>
349  *
350  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
351  *
352  * @retval #OS_OK  0x00000000,操作成功。
353  * @retval #其它值,操作失败。
354  * @par 依赖
355  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
356  * @see PRT_SemPend
357  */
358 extern U32 PRT_SemPost(SemHandle semHandle);
359 
360 /*
361  * @brief 获取阻塞在指定核内信号量上的任务PID清单。
362  *
363  * @par 描述
364  * 根据用户指定的核内信号量句柄,获取阻塞在指定核内信号量上的任务PID清单。
365  * 若有任务阻塞于该核内信号量,则返回阻塞于该核内信号量的任务数目,以及相应任务的PID。
366  * 若没有任务阻塞于该核内信号量,则返回阻塞于该核内信号量的任务数目为0。
367  * @attention
368  * <ul><li>用户应保证存储任务PID清单的内存空间足够大,建议将bufLen配置为(#OS_TSK_MAX_SUPPORT_NUM + 1)
369  * 4bytes。</li></ul>
370  *
371  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
372  * @param tskCnt    [OUT] 类型#U32 *,阻塞于该核内信号量的任务数。
373  * @param pidBuf    [OUT] 类型#U32 *,由用户指定的内存区域首地址,用于存储阻塞于指定核内信号量的任务PID。
374  * @param bufLen    [IN]  类型#U32,用户指定的内存区域的长度(单位:字节)。
375  *
376  * @retval #OS_OK  0x00000000,操作成功。
377  * @retval #其它值,操作失败。
378  * @par 依赖
379  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
380  * @see PRT_TaskGetPendSem | PRT_SemGetInfo
381  */
382 extern U32 PRT_SemGetPendList(SemHandle semHandle, U32 *tskCnt, U32 *pidBuf, U32 bufLen);
383 
384 /*
385  * @brief 获取信号量详细信息:信号量当前计数值,信号量持有者(最后一次pend成功的线程ID),信号量唤醒方式,信号量类型。
386  *
387  * @par 描述
388  * 根据用户输入信号量句柄获取信号量详细信息。
389  * @attention 无
390  *
391  * @param semHandle [IN]  类型#SemHandle,信号量句柄,来源于信号量创建成功的输出值。
392  * @param semInfo   [OUT] 类型#struct SemInfo *,信号量详细信息:count--信号量计数,owner--信号量占用者,
393  * mode--信号量唤醒方式,type--信号量类型。
394  *
395  * @retval #OS_OK  0x00000000,获取信号量计数器值成功。
396  * @retval #其它值,获取失败。
397  * @par 依赖
398  * <ul><li>prt_sem.h:该接口声明所在的头文件。</li></ul>
399  * @see PRT_SemGetCount | PRT_SemGetPendList
400  */
401 extern U32 PRT_SemGetInfo(SemHandle semHandle, struct SemInfo *semInfo);
402 
403 #ifdef __cplusplus
404 #if __cplusplus
405 }
406 #endif
407 #endif /* __cplusplus */
408 
409 #endif /* PRT_SEM_H */
410