• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 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 
31 #ifdef LOSCFG_KERNEL_MEM_PLIMIT
32 #include <stdlib.h>
33 #include <securec.h>
34 #include "los_config.h"
35 #include "los_hook.h"
36 #include "los_process_pri.h"
37 #include "los_plimits.h"
38 
39 STATIC ProcMemLimiter *g_procMemLimiter = NULL;
40 
OsMemLimiterInit(UINTPTR limite)41 VOID OsMemLimiterInit(UINTPTR limite)
42 {
43     ProcMemLimiter *procMemLimiter = (ProcMemLimiter *)limite;
44     procMemLimiter->limit = OS_NULL_INT;
45     g_procMemLimiter = procMemLimiter;
46 }
47 
OsMemLimitSetLimit(UINT32 limit)48 VOID OsMemLimitSetLimit(UINT32 limit)
49 {
50     g_procMemLimiter->limit = limit;
51 }
52 
OsMemLimiterAlloc(VOID)53 VOID *OsMemLimiterAlloc(VOID)
54 {
55     ProcMemLimiter *plimite = (ProcMemLimiter *)LOS_MemAlloc(m_aucSysMem1, sizeof(ProcMemLimiter));
56     if (plimite == NULL) {
57         return NULL;
58     }
59     (VOID)memset_s(plimite, sizeof(ProcMemLimiter), 0, sizeof(ProcMemLimiter));
60     return (VOID *)plimite;
61 }
62 
OsMemLimiterFree(UINTPTR limite)63 VOID OsMemLimiterFree(UINTPTR limite)
64 {
65     ProcMemLimiter *plimite = (ProcMemLimiter *)limite;
66     if (plimite == NULL) {
67         return;
68     }
69 
70     (VOID)LOS_MemFree(m_aucSysMem1, (VOID *)limite);
71 }
72 
OsMemLimiterCopy(UINTPTR dest,UINTPTR src)73 VOID OsMemLimiterCopy(UINTPTR dest, UINTPTR src)
74 {
75     ProcMemLimiter *plimiteDest = (ProcMemLimiter *)dest;
76     ProcMemLimiter *plimiteSrc = (ProcMemLimiter *)src;
77     plimiteDest->limit = plimiteSrc->limit;
78     return;
79 }
80 
MemLimiteMigrateCheck(UINTPTR curr,UINTPTR parent)81 BOOL MemLimiteMigrateCheck(UINTPTR curr, UINTPTR parent)
82 {
83     ProcMemLimiter *currMemLimit = (ProcMemLimiter *)curr;
84     ProcMemLimiter *parentMemLimit = (ProcMemLimiter *)parent;
85     if ((currMemLimit->usage + parentMemLimit->usage) >= parentMemLimit->limit) {
86         return FALSE;
87     }
88     return TRUE;
89 }
90 
OsMemLimiterMigrate(UINTPTR currLimit,UINTPTR parentLimit,UINTPTR process)91 VOID OsMemLimiterMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
92 {
93     ProcMemLimiter *currMemLimit = (ProcMemLimiter *)currLimit;
94     ProcMemLimiter *parentMemLimit = (ProcMemLimiter *)parentLimit;
95     LosProcessCB *pcb = (LosProcessCB *)process;
96 
97     if (pcb == NULL) {
98         parentMemLimit->usage += currMemLimit->usage;
99         parentMemLimit->failcnt += currMemLimit->failcnt;
100         if (parentMemLimit->peak < parentMemLimit->usage) {
101             parentMemLimit->peak = parentMemLimit->usage;
102         }
103         return;
104     }
105 
106     parentMemLimit->usage -= pcb->limitStat.memUsed;
107     currMemLimit->usage += pcb->limitStat.memUsed;
108 }
109 
OsMemLimitAddProcessCheck(UINTPTR limit,UINTPTR process)110 BOOL OsMemLimitAddProcessCheck(UINTPTR limit, UINTPTR process)
111 {
112     ProcMemLimiter *memLimit = (ProcMemLimiter *)limit;
113     LosProcessCB *pcb = (LosProcessCB *)process;
114     if ((memLimit->usage + pcb->limitStat.memUsed) > memLimit->limit) {
115         return FALSE;
116     }
117     return TRUE;
118 }
119 
OsMemLimitAddProcess(UINTPTR limit,UINTPTR process)120 VOID OsMemLimitAddProcess(UINTPTR limit, UINTPTR process)
121 {
122     LosProcessCB *pcb = (LosProcessCB *)process;
123     ProcMemLimiter *plimits = (ProcMemLimiter *)limit;
124     plimits->usage += pcb->limitStat.memUsed;
125     if (plimits->peak < plimits->usage) {
126         plimits->peak = plimits->usage;
127     }
128     return;
129 }
130 
OsMemLimitDelProcess(UINTPTR limit,UINTPTR process)131 VOID OsMemLimitDelProcess(UINTPTR limit, UINTPTR process)
132 {
133     LosProcessCB *pcb = (LosProcessCB *)process;
134     ProcMemLimiter *plimits = (ProcMemLimiter *)limit;
135 
136     plimits->usage -= pcb->limitStat.memUsed;
137     return;
138 }
139 
OsMemLimitSetMemLimit(ProcMemLimiter * memLimit,UINT64 value)140 UINT32 OsMemLimitSetMemLimit(ProcMemLimiter *memLimit, UINT64 value)
141 {
142     UINT32 intSave;
143     if ((memLimit == NULL) || (value == 0)) {
144         return EINVAL;
145     }
146 
147     if (memLimit == g_procMemLimiter) {
148         return EPERM;
149     }
150 
151     SCHEDULER_LOCK(intSave);
152     if (value < memLimit->usage) {
153         SCHEDULER_UNLOCK(intSave);
154         return EINVAL;
155     }
156 
157     memLimit->limit = value;
158     SCHEDULER_UNLOCK(intSave);
159     return LOS_OK;
160 }
161 
162 #define MEM_LIMIT_LOCK(state, locked) do { \
163     if (SCHEDULER_HELD()) {                \
164         locked = TRUE;                     \
165     } else {                               \
166         SCHEDULER_LOCK(state);             \
167     }                                      \
168 } while (0)
169 
170 #define MEM_LIMIT_UNLOCK(state, locked) do { \
171     if (!locked) {                           \
172         SCHEDULER_UNLOCK(state);             \
173     }                                        \
174 } while (0)
175 
OsMemLimitCheckAndMemAdd(UINT32 size)176 UINT32 OsMemLimitCheckAndMemAdd(UINT32 size)
177 {
178     UINT32 intSave;
179     BOOL locked = FALSE;
180     MEM_LIMIT_LOCK(intSave, locked);
181     LosProcessCB *run = OsCurrProcessGet();
182     UINT32 currProcessID = run->processID;
183     if ((run == NULL) || (run->plimits == NULL)) {
184         MEM_LIMIT_UNLOCK(intSave, locked);
185         return LOS_OK;
186     }
187 
188     ProcMemLimiter *memLimit = (ProcMemLimiter *)run->plimits->limitsList[PROCESS_LIMITER_ID_MEM];
189     if ((memLimit->usage + size) > memLimit->limit) {
190         memLimit->failcnt++;
191         MEM_LIMIT_UNLOCK(intSave, locked);
192         PRINT_ERR("plimits: process %u adjust the memory limit of Plimits group\n", currProcessID);
193         return ENOMEM;
194     }
195 
196     memLimit->usage += size;
197     run->limitStat.memUsed += size;
198     if (memLimit->peak < memLimit->usage) {
199         memLimit->peak = memLimit->usage;
200     }
201     MEM_LIMIT_UNLOCK(intSave, locked);
202     return LOS_OK;
203 }
204 
OsMemLimitMemFree(UINT32 size)205 VOID OsMemLimitMemFree(UINT32 size)
206 {
207     UINT32 intSave;
208     BOOL locked = FALSE;
209     MEM_LIMIT_LOCK(intSave, locked);
210     LosProcessCB *run = OsCurrProcessGet();
211     if ((run == NULL) || (run->plimits == NULL)) {
212         MEM_LIMIT_UNLOCK(intSave, locked);
213         return;
214     }
215 
216     ProcMemLimiter *memLimit = (ProcMemLimiter *)run->plimits->limitsList[PROCESS_LIMITER_ID_MEM];
217     if (run->limitStat.memUsed > size) {
218         run->limitStat.memUsed -= size;
219         memLimit->usage -= size;
220     }
221     MEM_LIMIT_UNLOCK(intSave, locked);
222 }
223 #endif
224