• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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