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