1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #ifdef LOSCFG_IPC_CONTAINER
31 #include "los_ipc_container_pri.h"
32 #include "los_config.h"
33 #include "los_queue_pri.h"
34 #include "los_vm_shm_pri.h"
35 #include "los_process_pri.h"
36 #include "vnode.h"
37 #include "proc_fs.h"
38 #include "pthread.h"
39
40 #define IPC_INIT_NUM 3
41
42 STATIC UINT32 g_currentIpcContainerNum = 0;
43
CreateNewIpcContainer(IpcContainer * parent)44 STATIC IpcContainer *CreateNewIpcContainer(IpcContainer *parent)
45 {
46 pthread_mutexattr_t attr;
47 UINT32 size = sizeof(IpcContainer);
48 IpcContainer *ipcContainer = (IpcContainer *)LOS_MemAlloc(m_aucSysMem1, size);
49 if (ipcContainer == NULL) {
50 return NULL;
51 }
52 (VOID)memset_s(ipcContainer, size, 0, size);
53
54 ipcContainer->allQueue = OsAllQueueCBInit(&ipcContainer->freeQueueList);
55 if (ipcContainer->allQueue == NULL) {
56 (VOID)LOS_MemFree(m_aucSysMem1, ipcContainer);
57 return NULL;
58 }
59 pthread_mutexattr_init(&attr);
60 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
61 pthread_mutex_init(&ipcContainer->mqueueMutex, &attr);
62
63 ipcContainer->shmSegs = OsShmCBInit(&ipcContainer->sysvShmMux, &ipcContainer->shmInfo,
64 &ipcContainer->shmUsedPageCount);
65 if (ipcContainer->shmSegs == NULL) {
66 (VOID)LOS_MemFree(m_aucSysMem1, ipcContainer->allQueue);
67 (VOID)LOS_MemFree(m_aucSysMem1, ipcContainer);
68 return NULL;
69 }
70 ipcContainer->containerID = OsAllocContainerID();
71
72 if (parent != NULL) {
73 LOS_AtomicSet(&ipcContainer->rc, 1);
74 } else {
75 LOS_AtomicSet(&ipcContainer->rc, 3); /* 3: Three system processes */
76 }
77 return ipcContainer;
78 }
79
CreateIpcContainer(LosProcessCB * child,LosProcessCB * parent)80 STATIC UINT32 CreateIpcContainer(LosProcessCB *child, LosProcessCB *parent)
81 {
82 UINT32 intSave;
83 IpcContainer *parentContainer = parent->container->ipcContainer;
84 IpcContainer *newIpcContainer = CreateNewIpcContainer(parentContainer);
85 if (newIpcContainer == NULL) {
86 return ENOMEM;
87 }
88
89 SCHEDULER_LOCK(intSave);
90 g_currentIpcContainerNum++;
91 child->container->ipcContainer = newIpcContainer;
92 SCHEDULER_UNLOCK(intSave);
93 return LOS_OK;
94 }
95
OsInitRootIpcContainer(IpcContainer ** ipcContainer)96 UINT32 OsInitRootIpcContainer(IpcContainer **ipcContainer)
97 {
98 UINT32 intSave;
99 IpcContainer *newIpcContainer = CreateNewIpcContainer(NULL);
100 if (newIpcContainer == NULL) {
101 return ENOMEM;
102 }
103
104 SCHEDULER_LOCK(intSave);
105 g_currentIpcContainerNum++;
106 *ipcContainer = newIpcContainer;
107 SCHEDULER_UNLOCK(intSave);
108 return LOS_OK;
109 }
110
OsCopyIpcContainer(UINTPTR flags,LosProcessCB * child,LosProcessCB * parent)111 UINT32 OsCopyIpcContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
112 {
113 UINT32 intSave;
114 IpcContainer *currIpcContainer = parent->container->ipcContainer;
115
116 if (!(flags & CLONE_NEWIPC)) {
117 SCHEDULER_LOCK(intSave);
118 LOS_AtomicInc(&currIpcContainer->rc);
119 child->container->ipcContainer = currIpcContainer;
120 SCHEDULER_UNLOCK(intSave);
121 return LOS_OK;
122 }
123
124 if (OsContainerLimitCheck(IPC_CONTAINER, &g_currentIpcContainerNum) != LOS_OK) {
125 return EPERM;
126 }
127
128 return CreateIpcContainer(child, parent);
129 }
130
OsUnshareIpcContainer(UINTPTR flags,LosProcessCB * curr,Container * newContainer)131 UINT32 OsUnshareIpcContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
132 {
133 UINT32 intSave;
134 IpcContainer *parentContainer = curr->container->ipcContainer;
135
136 if (!(flags & CLONE_NEWIPC)) {
137 SCHEDULER_LOCK(intSave);
138 newContainer->ipcContainer = parentContainer;
139 LOS_AtomicInc(&parentContainer->rc);
140 SCHEDULER_UNLOCK(intSave);
141 return LOS_OK;
142 }
143
144 if (OsContainerLimitCheck(IPC_CONTAINER, &g_currentIpcContainerNum) != LOS_OK) {
145 return EPERM;
146 }
147
148 IpcContainer *ipcContainer = CreateNewIpcContainer(parentContainer);
149 if (ipcContainer == NULL) {
150 return ENOMEM;
151 }
152
153 SCHEDULER_LOCK(intSave);
154 newContainer->ipcContainer = ipcContainer;
155 g_currentIpcContainerNum++;
156 SCHEDULER_UNLOCK(intSave);
157 return LOS_OK;
158 }
159
OsSetNsIpcContainer(UINT32 flags,Container * container,Container * newContainer)160 UINT32 OsSetNsIpcContainer(UINT32 flags, Container *container, Container *newContainer)
161 {
162 if (flags & CLONE_NEWIPC) {
163 newContainer->ipcContainer = container->ipcContainer;
164 LOS_AtomicInc(&container->ipcContainer->rc);
165 return LOS_OK;
166 }
167
168 newContainer->ipcContainer = OsCurrProcessGet()->container->ipcContainer;
169 LOS_AtomicInc(&newContainer->ipcContainer->rc);
170 return LOS_OK;
171 }
172
OsIpcContainerDestroy(Container * container)173 VOID OsIpcContainerDestroy(Container *container)
174 {
175 UINT32 intSave;
176 if (container == NULL) {
177 return;
178 }
179
180 SCHEDULER_LOCK(intSave);
181 IpcContainer *ipcContainer = container->ipcContainer;
182 if (ipcContainer == NULL) {
183 SCHEDULER_UNLOCK(intSave);
184 return;
185 }
186
187 LOS_AtomicDec(&ipcContainer->rc);
188 if (LOS_AtomicRead(&ipcContainer->rc) > 0) {
189 SCHEDULER_UNLOCK(intSave);
190 return;
191 }
192
193 g_currentIpcContainerNum--;
194 container->ipcContainer = NULL;
195 SCHEDULER_UNLOCK(intSave);
196 OsShmCBDestroy(ipcContainer->shmSegs, &ipcContainer->shmInfo, &ipcContainer->sysvShmMux);
197 ipcContainer->shmSegs = NULL;
198 OsMqueueCBDestroy(ipcContainer->queueTable);
199 (VOID)LOS_MemFree(m_aucSysMem1, ipcContainer->allQueue);
200 (VOID)LOS_MemFree(m_aucSysMem1, ipcContainer);
201 return;
202 }
203
OsGetIpcContainerID(IpcContainer * ipcContainer)204 UINT32 OsGetIpcContainerID(IpcContainer *ipcContainer)
205 {
206 if (ipcContainer == NULL) {
207 return OS_INVALID_VALUE;
208 }
209
210 return ipcContainer->containerID;
211 }
212
OsGetCurrIpcContainer(VOID)213 IpcContainer *OsGetCurrIpcContainer(VOID)
214 {
215 return OsCurrProcessGet()->container->ipcContainer;
216 }
217
OsGetIpcContainerCount(VOID)218 UINT32 OsGetIpcContainerCount(VOID)
219 {
220 return g_currentIpcContainerNum;
221 }
222 #endif
223