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,enum SemMode semMode,SemHandle * semHandle,U32 cookie)66 OS_SEC_L4_TEXT U32 OsSemCreate(U32 count, enum SemMode semMode, SemHandle *semHandle, U32 cookie)
67 {
68 uintptr_t intSave;
69 struct TagSemCb *semCreated = NULL;
70 struct TagListObject *unusedSem = NULL;
71
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->semOwner = OS_INVALID_OWNER_ID;
95 semCreated->maxSemCount = OS_SEM_COUNT_MAX;
96
97 INIT_LIST_OBJECT(&semCreated->semList);
98 *semHandle = (SemHandle)semCreated->semId;
99
100 OsIntRestore(intSave);
101 return OS_OK;
102 }
103
104 /*
105 * 描述:创建一个信号量
106 */
PRT_SemCreate(U32 count,SemHandle * semHandle)107 OS_SEC_L4_TEXT U32 PRT_SemCreate(U32 count, SemHandle *semHandle)
108 {
109 U32 ret;
110
111 if (count > OS_SEM_COUNT_MAX) {
112 return OS_ERRNO_SEM_OVERFLOW;
113 }
114
115 ret = OsSemCreate(count, SEM_MODE_FIFO, semHandle, (U32)(uintptr_t)semHandle);
116 return ret;
117 }
118
119 /*
120 * 描述:删除一个信号量
121 */
PRT_SemDelete(SemHandle semHandle)122 OS_SEC_L4_TEXT U32 PRT_SemDelete(SemHandle semHandle)
123 {
124 uintptr_t intSave;
125 struct TagSemCb *semDeleted = NULL;
126
127 if (semHandle >= (SemHandle)g_maxSem) {
128 return OS_ERRNO_SEM_INVALID;
129 }
130 semDeleted = GET_SEM(semHandle);
131
132 intSave = OsIntLock();
133
134 if (semDeleted->semStat == OS_SEM_UNUSED) {
135 OsIntRestore(intSave);
136 return OS_ERRNO_SEM_INVALID;
137 }
138 if (!ListEmpty(&semDeleted->semList)) {
139 OsIntRestore(intSave);
140 return OS_ERRNO_SEM_PENDED;
141 }
142 semDeleted->semStat = OS_SEM_UNUSED;
143 ListAdd(&semDeleted->semList, &g_unusedSemList);
144
145 OsIntRestore(intSave);
146 return OS_OK;
147 }
148