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 #include "prt_sem_external.h"
16
17 OS_SEC_BSS struct TagListObject g_unusedSemList;
18 OS_SEC_BSS struct TagSemCb *g_allSem;
19
OsSemRegister(const struct SemModInfo * modInfo)20 OS_SEC_L4_TEXT U32 OsSemRegister(const struct SemModInfo *modInfo)
21 {
22 if (modInfo->maxNum == 0) {
23 return OS_ERRNO_SEM_REG_ERROR;
24 }
25
26 g_maxSem = modInfo->maxNum;
27
28 return OS_OK;
29 }
30
31 /*
32 * 描述:信号量初始化
33 */
OsSemInit(void)34 OS_SEC_L4_TEXT U32 OsSemInit(void)
35 {
36 struct TagSemCb *semNode = NULL;
37 U32 idx;
38 U32 ret = OS_OK;
39
40 /* g_maxSem在注册时已判断是否大于0,这里不需判断 */
41 g_allSem = (struct TagSemCb *)OsMemAllocAlign((U32)OS_MID_SEM,
42 OS_MEM_DEFAULT_FSC_PT,
43 g_maxSem * sizeof(struct TagSemCb),
44 MEM_ADDR_ALIGN_004);
45 if (g_allSem == NULL) {
46 return OS_ERRNO_SEM_NO_MEMORY;
47 }
48 if (memset_s((void *)g_allSem, g_maxSem * sizeof(struct TagSemCb), 0, g_maxSem * sizeof(struct TagSemCb)) !=
49 EOK) {
50 OS_GOTO_SYS_ERROR1();
51 }
52
53 INIT_LIST_OBJECT(&g_unusedSemList);
54 for (idx = 0; idx < g_maxSem; idx++) {
55 semNode = ((struct TagSemCb *)g_allSem) + idx;
56 semNode->semId = (U16)idx;
57 ListTailAdd(&semNode->semList, &g_unusedSemList);
58 }
59
60 return ret;
61 }
62
63 /*
64 * 描述:创建一个信号量
65 */
OsSemCreate(U32 count,U32 semType,enum SemMode semMode,SemHandle * semHandle,U32 cookie)66 OS_SEC_L4_TEXT U32 OsSemCreate(U32 count, U32 semType, enum SemMode semMode,
67 SemHandle *semHandle, U32 cookie)
68 {
69 uintptr_t intSave;
70 struct TagSemCb *semCreated = NULL;
71 struct TagListObject *unusedSem = NULL;
72 (void)cookie;
73
74 if (semHandle == NULL) {
75 return OS_ERRNO_SEM_PTR_NULL;
76 }
77
78 intSave = OsIntLock();
79
80 if (ListEmpty(&g_unusedSemList)) {
81 OsIntRestore(intSave);
82 return OS_ERRNO_SEM_ALL_BUSY;
83 }
84
85 /* 在空闲链表中取走一个控制节点 */
86 unusedSem = OS_LIST_FIRST(&(g_unusedSemList));
87 ListDelete(unusedSem);
88
89 /* 获取到空闲节点对应的信号量控制块,并开始填充控制块 */
90 semCreated = (GET_SEM_LIST(unusedSem));
91 semCreated->semCount = count;
92 semCreated->semStat = OS_SEM_USED;
93 semCreated->semMode = semMode;
94 semCreated->semType = semType;
95 semCreated->semOwner = OS_INVALID_OWNER_ID;
96 if (GET_SEM_TYPE(semType) == SEM_TYPE_BIN) {
97 INIT_LIST_OBJECT(&semCreated->semBList);
98 #if defined(OS_OPTION_SEM_RECUR_PV)
99 if (GET_MUTEX_TYPE(semType) == PTHREAD_MUTEX_RECURSIVE) {
100 semCreated->recurCount = 0;
101 }
102 #endif
103 }
104
105 INIT_LIST_OBJECT(&semCreated->semList);
106 *semHandle = (SemHandle)semCreated->semId;
107
108 OsIntRestore(intSave);
109 return OS_OK;
110 }
111
112 /*
113 * 描述:创建一个信号量
114 */
PRT_SemCreate(U32 count,SemHandle * semHandle)115 OS_SEC_L4_TEXT U32 PRT_SemCreate(U32 count, SemHandle *semHandle)
116 {
117 U32 ret;
118
119 if (count > OS_SEM_COUNT_MAX) {
120 return OS_ERRNO_SEM_OVERFLOW;
121 }
122
123 ret = OsSemCreate(count, SEM_TYPE_COUNT, SEM_MODE_FIFO, semHandle, (U32)(uintptr_t)semHandle);
124 return ret;
125 }
126
127 /*
128 * 描述:删除一个信号量
129 */
PRT_SemDelete(SemHandle semHandle)130 OS_SEC_L4_TEXT U32 PRT_SemDelete(SemHandle semHandle)
131 {
132 uintptr_t intSave;
133 struct TagSemCb *semDeleted = NULL;
134
135 if (semHandle >= (SemHandle)g_maxSem) {
136 return OS_ERRNO_SEM_INVALID;
137 }
138 semDeleted = GET_SEM(semHandle);
139
140 intSave = OsIntLock();
141
142 if (semDeleted->semStat == OS_SEM_UNUSED) {
143 OsIntRestore(intSave);
144 return OS_ERRNO_SEM_INVALID;
145 }
146 if (!ListEmpty(&semDeleted->semList)) {
147 OsIntRestore(intSave);
148 return OS_ERRNO_SEM_PENDED;
149 }
150 #ifdef OS_OPTION_BIN_SEM
151 if ((semDeleted->semOwner != OS_INVALID_OWNER_ID) && (GET_SEM_TYPE(semDeleted->semType) == SEM_TYPE_BIN)) {
152 ListDelete(&semDeleted->semBList);
153 }
154 #endif
155 semDeleted->semStat = OS_SEM_UNUSED;
156 ListAdd(&semDeleted->semList, &g_unusedSemList);
157
158 OsIntRestore(intSave);
159 return OS_OK;
160 }
161