224 lines
6.8 KiB
C
224 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
* conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
* provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <securec.h>
|
|
#include "los_config.h"
|
|
#include "los_hook.h"
|
|
#include "los_process_pri.h"
|
|
#include "los_plimits.h"
|
|
|
|
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
|
|
STATIC ProcMemLimiter *g_procMemLimiter = NULL;
|
|
|
|
VOID OsMemLimiterInit(UINTPTR limite)
|
|
{
|
|
ProcMemLimiter *procMemLimiter = (ProcMemLimiter *)limite;
|
|
procMemLimiter->limit = OS_NULL_INT;
|
|
g_procMemLimiter = procMemLimiter;
|
|
}
|
|
|
|
VOID OsMemLimitSetLimit(UINT32 limit)
|
|
{
|
|
g_procMemLimiter->limit = limit;
|
|
}
|
|
|
|
VOID *OsMemLimiterAlloc(VOID)
|
|
{
|
|
ProcMemLimiter *plimite = (ProcMemLimiter *)LOS_KernelMalloc(sizeof(ProcMemLimiter));
|
|
if (plimite == NULL) {
|
|
return NULL;
|
|
}
|
|
(VOID)memset_s(plimite, sizeof(ProcMemLimiter), 0, sizeof(ProcMemLimiter));
|
|
return (VOID *)plimite;
|
|
}
|
|
|
|
VOID OsMemLimiterFree(UINTPTR limite)
|
|
{
|
|
ProcMemLimiter *plimite = (ProcMemLimiter *)limite;
|
|
if (plimite == NULL) {
|
|
return;
|
|
}
|
|
|
|
LOS_KernelFree((VOID *)limite);
|
|
}
|
|
|
|
VOID OsMemLimiterCopy(UINTPTR dest, UINTPTR src)
|
|
{
|
|
ProcMemLimiter *plimiteDest = (ProcMemLimiter *)dest;
|
|
ProcMemLimiter *plimiteSrc = (ProcMemLimiter *)src;
|
|
plimiteDest->limit = plimiteSrc->limit;
|
|
return;
|
|
}
|
|
|
|
BOOL MemLimiteMigrateCheck(UINTPTR curr, UINTPTR parent)
|
|
{
|
|
ProcMemLimiter *currMemLimit = (ProcMemLimiter *)curr;
|
|
ProcMemLimiter *parentMemLimit = (ProcMemLimiter *)parent;
|
|
if ((currMemLimit->usage + parentMemLimit->usage) >= parentMemLimit->limit) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
VOID OsMemLimiterMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
|
|
{
|
|
ProcMemLimiter *currMemLimit = (ProcMemLimiter *)currLimit;
|
|
ProcMemLimiter *parentMemLimit = (ProcMemLimiter *)parentLimit;
|
|
LosProcessCB *pcb = (LosProcessCB *)process;
|
|
|
|
if (pcb == NULL) {
|
|
parentMemLimit->usage += currMemLimit->usage;
|
|
parentMemLimit->failcnt += currMemLimit->failcnt;
|
|
if (parentMemLimit->peak < parentMemLimit->usage) {
|
|
parentMemLimit->peak = parentMemLimit->usage;
|
|
}
|
|
return;
|
|
}
|
|
|
|
parentMemLimit->usage -= pcb->limitStat.memUsed;
|
|
currMemLimit->usage += pcb->limitStat.memUsed;
|
|
}
|
|
|
|
BOOL OsMemLimitAddProcessCheck(UINTPTR limit, UINTPTR process)
|
|
{
|
|
ProcMemLimiter *memLimit = (ProcMemLimiter *)limit;
|
|
LosProcessCB *pcb = (LosProcessCB *)process;
|
|
if ((memLimit->usage + pcb->limitStat.memUsed) > memLimit->limit) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
VOID OsMemLimitAddProcess(UINTPTR limit, UINTPTR process)
|
|
{
|
|
LosProcessCB *pcb = (LosProcessCB *)process;
|
|
ProcMemLimiter *plimits = (ProcMemLimiter *)limit;
|
|
plimits->usage += pcb->limitStat.memUsed;
|
|
if (plimits->peak < plimits->usage) {
|
|
plimits->peak = plimits->usage;
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID OsMemLimitDelProcess(UINTPTR limit, UINTPTR process)
|
|
{
|
|
LosProcessCB *pcb = (LosProcessCB *)process;
|
|
ProcMemLimiter *plimits = (ProcMemLimiter *)limit;
|
|
|
|
plimits->usage -= pcb->limitStat.memUsed;
|
|
return;
|
|
}
|
|
|
|
UINT32 OsMemLimitSetMemLimit(ProcMemLimiter *memLimit, UINT64 value)
|
|
{
|
|
UINT32 intSave;
|
|
if ((memLimit == NULL) || (value == 0)) {
|
|
return EINVAL;
|
|
}
|
|
|
|
if (memLimit == g_procMemLimiter) {
|
|
return EPERM;
|
|
}
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
if (value < memLimit->usage) {
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return EINVAL;
|
|
}
|
|
|
|
memLimit->limit = value;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return LOS_OK;
|
|
}
|
|
|
|
#define MEM_LIMIT_LOCK(state, locked) do { \
|
|
if (SCHEDULER_HELD()) { \
|
|
locked = TRUE; \
|
|
} else { \
|
|
SCHEDULER_LOCK(state); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define MEM_LIMIT_UNLOCK(state, locked) do { \
|
|
if (!locked) { \
|
|
SCHEDULER_UNLOCK(state); \
|
|
} \
|
|
} while (0)
|
|
|
|
UINT32 OsMemLimitCheckAndMemAdd(UINT32 size)
|
|
{
|
|
UINT32 intSave;
|
|
BOOL locked = FALSE;
|
|
MEM_LIMIT_LOCK(intSave, locked);
|
|
LosProcessCB *run = OsCurrProcessGet();
|
|
UINT32 currProcessID = run->processID;
|
|
if ((run == NULL) || (run->plimits == NULL)) {
|
|
MEM_LIMIT_UNLOCK(intSave, locked);
|
|
return LOS_OK;
|
|
}
|
|
|
|
ProcMemLimiter *memLimit = (ProcMemLimiter *)run->plimits->limitsList[PROCESS_LIMITER_ID_MEM];
|
|
if ((memLimit->usage + size) > memLimit->limit) {
|
|
memLimit->failcnt++;
|
|
MEM_LIMIT_UNLOCK(intSave, locked);
|
|
PRINT_ERR("plimits: process %u adjust the memory limit of Plimits group\n", currProcessID);
|
|
return ENOMEM;
|
|
}
|
|
|
|
memLimit->usage += size;
|
|
run->limitStat.memUsed += size;
|
|
if (memLimit->peak < memLimit->usage) {
|
|
memLimit->peak = memLimit->usage;
|
|
}
|
|
MEM_LIMIT_UNLOCK(intSave, locked);
|
|
return LOS_OK;
|
|
}
|
|
|
|
VOID OsMemLimitMemFree(UINT32 size)
|
|
{
|
|
UINT32 intSave;
|
|
BOOL locked = FALSE;
|
|
MEM_LIMIT_LOCK(intSave, locked);
|
|
LosProcessCB *run = OsCurrProcessGet();
|
|
if ((run == NULL) || (run->plimits == NULL)) {
|
|
MEM_LIMIT_UNLOCK(intSave, locked);
|
|
return;
|
|
}
|
|
|
|
ProcMemLimiter *memLimit = (ProcMemLimiter *)run->plimits->limitsList[PROCESS_LIMITER_ID_MEM];
|
|
if (run->limitStat.memUsed > size) {
|
|
run->limitStat.memUsed -= size;
|
|
memLimit->usage -= size;
|
|
}
|
|
MEM_LIMIT_UNLOCK(intSave, locked);
|
|
}
|
|
#endif
|