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 #include "los_time_container_pri.h"
31 #include "los_process_pri.h"
32
33 #ifdef LOSCFG_TIME_CONTAINER
34 STATIC UINT32 g_currentTimeContainerNum;
35
CreateNewTimeContainer(TimeContainer * parent)36 STATIC TimeContainer *CreateNewTimeContainer(TimeContainer *parent)
37 {
38 UINT32 size = sizeof(TimeContainer);
39 TimeContainer *timeContainer = (TimeContainer *)LOS_MemAlloc(m_aucSysMem1, size);
40 if (timeContainer == NULL) {
41 return NULL;
42 }
43 (VOID)memset_s(timeContainer, size, 0, size);
44
45 timeContainer->containerID = OsAllocContainerID();
46 if (parent != NULL) {
47 timeContainer->frozenOffsets = FALSE;
48 LOS_AtomicSet(&timeContainer->rc, 1);
49 } else {
50 timeContainer->frozenOffsets = TRUE;
51 LOS_AtomicSet(&timeContainer->rc, 3); /* 3: Three system processes */
52 }
53 return timeContainer;
54 }
55
CreateTimeContainer(LosProcessCB * child,LosProcessCB * parent)56 STATIC UINT32 CreateTimeContainer(LosProcessCB *child, LosProcessCB *parent)
57 {
58 UINT32 intSave;
59
60 SCHEDULER_LOCK(intSave);
61 TimeContainer *newTimeContainer = parent->container->timeForChildContainer;
62 LOS_AtomicInc(&newTimeContainer->rc);
63 newTimeContainer->frozenOffsets = TRUE;
64 child->container->timeContainer = newTimeContainer;
65 child->container->timeForChildContainer = newTimeContainer;
66 SCHEDULER_UNLOCK(intSave);
67 return LOS_OK;
68 }
69
OsInitRootTimeContainer(TimeContainer ** timeContainer)70 UINT32 OsInitRootTimeContainer(TimeContainer **timeContainer)
71 {
72 UINT32 intSave;
73 TimeContainer *newTimeContainer = CreateNewTimeContainer(NULL);
74 if (newTimeContainer == NULL) {
75 return ENOMEM;
76 }
77
78 SCHEDULER_LOCK(intSave);
79 *timeContainer = newTimeContainer;
80 g_currentTimeContainerNum++;
81 SCHEDULER_UNLOCK(intSave);
82 return LOS_OK;
83 }
84
OsCopyTimeContainer(UINTPTR flags,LosProcessCB * child,LosProcessCB * parent)85 UINT32 OsCopyTimeContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
86 {
87 UINT32 intSave;
88 TimeContainer *currTimeContainer = parent->container->timeContainer;
89
90 if (currTimeContainer == parent->container->timeForChildContainer) {
91 SCHEDULER_LOCK(intSave);
92 LOS_AtomicInc(&currTimeContainer->rc);
93 child->container->timeContainer = currTimeContainer;
94 child->container->timeForChildContainer = currTimeContainer;
95 SCHEDULER_UNLOCK(intSave);
96 return LOS_OK;
97 }
98
99 if (OsContainerLimitCheck(TIME_CONTAINER, &g_currentTimeContainerNum) != LOS_OK) {
100 return EPERM;
101 }
102
103 return CreateTimeContainer(child, parent);
104 }
105
OsUnshareTimeContainer(UINTPTR flags,LosProcessCB * curr,Container * newContainer)106 UINT32 OsUnshareTimeContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
107 {
108 UINT32 intSave;
109 if (!(flags & CLONE_NEWTIME)) {
110 SCHEDULER_LOCK(intSave);
111 newContainer->timeContainer = curr->container->timeContainer;
112 newContainer->timeForChildContainer = curr->container->timeForChildContainer;
113 LOS_AtomicInc(&newContainer->timeContainer->rc);
114 if (newContainer->timeContainer != newContainer->timeForChildContainer) {
115 LOS_AtomicInc(&newContainer->timeForChildContainer->rc);
116 }
117 SCHEDULER_UNLOCK(intSave);
118 return LOS_OK;
119 }
120
121 if (OsContainerLimitCheck(TIME_CONTAINER, &g_currentTimeContainerNum) != LOS_OK) {
122 return EPERM;
123 }
124
125 TimeContainer *timeForChild = CreateNewTimeContainer(curr->container->timeContainer);
126 if (timeForChild == NULL) {
127 return ENOMEM;
128 }
129
130 SCHEDULER_LOCK(intSave);
131 if (curr->container->timeContainer != curr->container->timeForChildContainer) {
132 SCHEDULER_UNLOCK(intSave);
133 (VOID)LOS_MemFree(m_aucSysMem1, timeForChild);
134 return EINVAL;
135 }
136
137 (VOID)memcpy_s(&timeForChild->monotonic, sizeof(struct timespec64),
138 &curr->container->timeContainer->monotonic, sizeof(struct timespec64));
139 newContainer->timeContainer = curr->container->timeContainer;
140 LOS_AtomicInc(&newContainer->timeContainer->rc);
141 newContainer->timeForChildContainer = timeForChild;
142 g_currentTimeContainerNum++;
143 SCHEDULER_UNLOCK(intSave);
144 return LOS_OK;
145 }
146
OsSetNsTimeContainer(UINT32 flags,Container * container,Container * newContainer)147 UINT32 OsSetNsTimeContainer(UINT32 flags, Container *container, Container *newContainer)
148 {
149 LosProcessCB *curr = OsCurrProcessGet();
150 if (flags & CLONE_NEWTIME) {
151 container->timeContainer->frozenOffsets = TRUE;
152 newContainer->timeContainer = container->timeContainer;
153 newContainer->timeForChildContainer = container->timeContainer;
154 LOS_AtomicInc(&container->timeContainer->rc);
155 return LOS_OK;
156 }
157
158 newContainer->timeContainer = curr->container->timeContainer;
159 LOS_AtomicInc(&curr->container->timeContainer->rc);
160 newContainer->timeForChildContainer = curr->container->timeForChildContainer;
161 if (curr->container->timeContainer != curr->container->timeForChildContainer) {
162 LOS_AtomicInc(&curr->container->timeForChildContainer->rc);
163 }
164 return LOS_OK;
165 }
166
OsTimeContainerDestroy(Container * container)167 VOID OsTimeContainerDestroy(Container *container)
168 {
169 UINT32 intSave;
170 TimeContainer *timeContainer = NULL;
171 TimeContainer *timeForChild = NULL;
172
173 if (container == NULL) {
174 return;
175 }
176
177 SCHEDULER_LOCK(intSave);
178 if (container->timeContainer == NULL) {
179 SCHEDULER_UNLOCK(intSave);
180 return;
181 }
182
183 if ((container->timeForChildContainer != NULL) && (container->timeContainer != container->timeForChildContainer)) {
184 LOS_AtomicDec(&container->timeForChildContainer->rc);
185 if (LOS_AtomicRead(&container->timeForChildContainer->rc) <= 0) {
186 g_currentTimeContainerNum--;
187 timeForChild = container->timeForChildContainer;
188 container->timeForChildContainer = NULL;
189 }
190 }
191
192 LOS_AtomicDec(&container->timeContainer->rc);
193 if (LOS_AtomicRead(&container->timeContainer->rc) <= 0) {
194 g_currentTimeContainerNum--;
195 timeContainer = container->timeContainer;
196 container->timeContainer = NULL;
197 container->timeForChildContainer = NULL;
198 }
199 SCHEDULER_UNLOCK(intSave);
200 (VOID)LOS_MemFree(m_aucSysMem1, timeForChild);
201 (VOID)LOS_MemFree(m_aucSysMem1, timeContainer);
202 return;
203 }
204
OsGetTimeContainerID(TimeContainer * timeContainer)205 UINT32 OsGetTimeContainerID(TimeContainer *timeContainer)
206 {
207 if (timeContainer == NULL) {
208 return OS_INVALID_VALUE;
209 }
210
211 return timeContainer->containerID;
212 }
213
OsGetCurrTimeContainer(VOID)214 TimeContainer *OsGetCurrTimeContainer(VOID)
215 {
216 return OsCurrProcessGet()->container->timeContainer;
217 }
218
OsGetTimeContainerMonotonic(LosProcessCB * processCB,struct timespec64 * offsets)219 UINT32 OsGetTimeContainerMonotonic(LosProcessCB *processCB, struct timespec64 *offsets)
220 {
221 if ((processCB == NULL) || (offsets == NULL)) {
222 return EINVAL;
223 }
224
225 if (OsProcessIsInactive(processCB)) {
226 return ESRCH;
227 }
228
229 TimeContainer *timeContainer = processCB->container->timeForChildContainer;
230 (VOID)memcpy_s(offsets, sizeof(struct timespec64), &timeContainer->monotonic, sizeof(struct timespec64));
231 return LOS_OK;
232 }
233
OsSetTimeContainerMonotonic(LosProcessCB * processCB,struct timespec64 * offsets)234 UINT32 OsSetTimeContainerMonotonic(LosProcessCB *processCB, struct timespec64 *offsets)
235 {
236 if ((processCB == NULL) || (offsets == NULL)) {
237 return EINVAL;
238 }
239
240 if (OsProcessIsInactive(processCB)) {
241 return ESRCH;
242 }
243
244 TimeContainer *timeContainer = processCB->container->timeForChildContainer;
245 if (timeContainer->frozenOffsets) {
246 return EACCES;
247 }
248
249 timeContainer->monotonic.tv_sec = offsets->tv_sec;
250 timeContainer->monotonic.tv_nsec = offsets->tv_nsec;
251 return LOS_OK;
252 }
253
OsGetTimeContainerCount(VOID)254 UINT32 OsGetTimeContainerCount(VOID)
255 {
256 return g_currentTimeContainerNum;
257 }
258 #endif
259