未验证 提交 f0a435dc 编写于 作者: O openharmony_ci 提交者: Gitee

!1123 支持资源限额控制器

Merge pull request !1123 from zhushengle/cgroups_2
......@@ -252,6 +252,11 @@ config("container_config") {
"-DLOSCFG_TIME_CONTAINER",
"-DLOSCFG_USER_CONTAINER",
"-DLOSCFG_PROC_PROCESS_DIR",
"-DLOSCFG_KERNEL_PLIMITS",
"-DLOSCFG_KERNEL_MEM_PLIMIT",
"-DLOSCFG_KERNEL_IPC_PLIMIT",
"-DLOSCFG_KERNEL_DEV_PLIMIT",
"-DLOSCFG_KERNEL_SCHED_PLIMIT",
]
}
}
......
......@@ -113,7 +113,9 @@ STATIC INLINE struct mqarray *GetMqueueCBByName(const CHAR *name)
STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB)
{
UINT32 ret;
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
OsIPCLimitMqFree();
#endif
if (mqueueCB->mq_name != NULL) {
LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
mqueueCB->mq_name = NULL;
......@@ -163,11 +165,29 @@ STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB)
return LOS_OK;
}
STATIC VOID MqueueCBInit(struct mqarray *mqueueCB, const struct mq_attr *attr, INT32 openFlag, UINT32 mode)
{
mqueueCB->unlinkflag = FALSE;
mqueueCB->unlink_ref = 0;
mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;
mqueueCB->mq_personal->mq_next = NULL;
mqueueCB->mq_personal->mq_posixdes = mqueueCB;
mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));
mqueueCB->mq_personal->mq_mode = mode;
mqueueCB->mq_personal->mq_refcount = 0;
mqueueCB->mq_notify.pid = 0;
}
STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag, UINT32 mode)
{
struct mqarray *mqueueCB = NULL;
UINT32 mqueueID;
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
if (OsIPCLimitMqAlloc() != LOS_OK) {
return (struct mqpersonal *)-1;
}
#endif
UINT32 err = LOS_QueueCreate(NULL, attr->mq_maxmsg, &mqueueID, 0, attr->mq_msgsize);
if (map_errno(err) != ENOERR) {
goto ERROUT;
......@@ -201,15 +221,7 @@ STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR
goto ERROUT;
}
mqueueCB->unlinkflag = FALSE;
mqueueCB->unlink_ref = 0;
mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;
mqueueCB->mq_personal->mq_next = NULL;
mqueueCB->mq_personal->mq_posixdes = mqueueCB;
mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));
mqueueCB->mq_personal->mq_mode = mode;
mqueueCB->mq_personal->mq_refcount = 0;
mqueueCB->mq_notify.pid = 0;
MqueueCBInit(mqueueCB, attr, openFlag, mode);
return mqueueCB->mq_personal;
ERROUT:
......@@ -218,6 +230,9 @@ ERROUT:
LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
mqueueCB->mq_name = NULL;
}
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
OsIPCLimitMqFree();
#endif
return (struct mqpersonal *)-1;
}
......
......@@ -38,6 +38,7 @@ kernel_module(module_name) {
"os_adapt/fs_cache_proc.c",
"os_adapt/mem_info.c",
"os_adapt/mounts_proc.c",
"os_adapt/plimits_proc.c",
"os_adapt/power_proc.c",
"os_adapt/proc_init.c",
"os_adapt/proc_vfs.c",
......
......@@ -55,6 +55,16 @@ void ProcSysMemInfoInit(void);
void ProcFileSysInit(void);
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
void ProcLimitsInit(void);
#endif
void ProcEntryClearVnode(struct ProcDirEntry *entry);
void ProcDetachNode(struct ProcDirEntry *pn);
void RemoveProcEntryTravalsal(struct ProcDirEntry *pn);
void ProcPmInit(void);
void ProcVmmInit(void);
......
......@@ -93,6 +93,15 @@ struct ProcFileOperations {
ssize_t (*readLink)(struct ProcDirEntry *pde, char *buf, size_t bufLen);
};
#ifdef LOSCFG_KERNEL_PLIMITS
struct ProcDirOperations {
int (*rmdir)(struct ProcDirEntry *parent, struct ProcDirEntry *pde, const char *name);
int (*mkdir)(struct ProcDirEntry *parent, const char *dirName, mode_t mode, struct ProcDirEntry **pde);
};
#endif
#define PROC_DATA_STATIC 0
#define PROC_DATA_FREE 1
struct ProcDirEntry {
uint uid;
uint gid;
......@@ -101,6 +110,10 @@ struct ProcDirEntry {
const struct ProcFileOperations *procFileOps;
struct ProcFile *pf;
struct ProcDirEntry *next, *parent, *subdir;
#ifdef LOSCFG_KERNEL_PLIMITS
const struct ProcDirOperations *procDirOps;
#endif
int dataType;
void *data;
atomic_t count; /* open file count */
spinlock_t pdeUnloadLock;
......@@ -111,6 +124,11 @@ struct ProcDirEntry {
enum VnodeType type;
};
struct ProcDataParm {
void *data;
int dataType;
};
struct ProcFile {
fmode_t fMode;
spinlock_t fLock;
......@@ -274,7 +292,7 @@ extern struct ProcDirEntry *ProcCreate(const char *name, mode_t mode,
*
*/
extern struct ProcDirEntry *ProcCreateData(const char *name, mode_t mode, struct ProcDirEntry *parent,
const struct ProcFileOperations *procFileOps, void *data);
const struct ProcFileOperations *procFileOps, struct ProcDataParm *param);
/**
* @ingroup procfs
* @brief init proc fs
......
此差异已折叠。
......@@ -72,6 +72,9 @@ void ProcFsInit(void)
ProcSysMemInfoInit();
ProcFileSysInit();
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
ProcLimitsInit();
#endif
}
LOS_MODULE_INIT(ProcFsInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
......
......@@ -239,6 +239,53 @@ int VfsProcfsStat(struct Vnode *node, struct stat *buf)
return LOS_OK;
}
#ifdef LOSCFG_KERNEL_PLIMITS
int VfsProcfsMkdir(struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode)
{
struct ProcDirEntry *parentEntry = VnodeToEntry(parent);
struct ProcDirEntry *pde = NULL;
if ((parentEntry->procDirOps == NULL) || (parentEntry->procDirOps->mkdir == NULL)) {
return -ENOSYS;
}
int ret = parentEntry->procDirOps->mkdir(parentEntry, dirName, mode, &pde);
if ((ret < 0) || (pde == NULL)) {
return ret;
}
*vnode = EntryToVnode(pde);
(*vnode)->vop = parent->vop;
(*vnode)->parent = parent;
(*vnode)->originMount = parent->originMount;
if ((*vnode)->type == VNODE_TYPE_DIR) {
(*vnode)->mode = S_IFDIR | PROCFS_DEFAULT_MODE;
} else {
(*vnode)->mode = S_IFREG | PROCFS_DEFAULT_MODE;
}
return ret;
}
int VfsProcfsRmdir(struct Vnode *parent, struct Vnode *vnode, const char *dirName)
{
if (parent == NULL) {
return -EINVAL;
}
struct ProcDirEntry *parentEntry = VnodeToEntry(parent);
if ((parentEntry->procDirOps == NULL) || (parentEntry->procDirOps->rmdir == NULL)) {
return -ENOSYS;
}
struct ProcDirEntry *dirEntry = VnodeToEntry(vnode);
int ret = parentEntry->procDirOps->rmdir(parentEntry, dirEntry, dirName);
if (ret < 0) {
return ret;
}
vnode->data = NULL;
return 0;
}
#endif
int VfsProcfsReaddir(struct Vnode *node, struct fs_dirent_s *dir)
{
int result;
......@@ -350,7 +397,7 @@ int VfsProcfsClose(struct file *filep)
VnodeHold();
struct Vnode *node = filep->f_vnode;
struct ProcDirEntry *pde = VnodeToEntry(node);
if (pde == NULL) {
if ((pde == NULL) || (pde->pf == NULL)) {
VnodeDrop();
return -EPERM;
}
......@@ -410,6 +457,10 @@ static struct VnodeOps g_procfsVops = {
.Closedir = VfsProcfsClosedir,
.Truncate = VfsProcfsTruncate,
.Readlink = VfsProcfsReadlink,
#ifdef LOSCFG_KERNEL_PLIMITS
.Mkdir = VfsProcfsMkdir,
.Rmdir = VfsProcfsRmdir,
#endif
};
static struct file_operations_vfs g_procfsFops = {
......
......@@ -588,6 +588,7 @@ void ProcFreeProcessDir(struct ProcDirEntry *processDir)
static struct ProcDirEntry *ProcCreatePorcess(UINT32 pid, struct ProcProcess *porcess, uintptr_t processCB)
{
int ret;
struct ProcDataParm dataParm;
char pidName[PROC_PID_DIR_LEN] = {0};
struct ProcessData *data = (struct ProcessData *)malloc(sizeof(struct ProcessData));
if (data == NULL) {
......@@ -613,7 +614,9 @@ static struct ProcDirEntry *ProcCreatePorcess(UINT32 pid, struct ProcProcess *po
data->process = processCB;
data->type = porcess->type;
struct ProcDirEntry *container = ProcCreateData(pidName, porcess->mode, NULL, porcess->fileOps, (void *)data);
dataParm.data = data;
dataParm.dataType = PROC_DATA_FREE;
struct ProcDirEntry *container = ProcCreateData(pidName, porcess->mode, NULL, porcess->fileOps, &dataParm);
if (container == NULL) {
free(data);
PRINT_ERR("create /proc/%s error!\n", pidName);
......
......@@ -296,7 +296,7 @@ static int ProcAddNode(struct ProcDirEntry *parent, struct ProcDirEntry *pn)
return 0;
}
static void ProcDetachNode(struct ProcDirEntry *pn)
void ProcDetachNode(struct ProcDirEntry *pn)
{
struct ProcDirEntry *parent = pn->parent;
struct ProcDirEntry **iter = NULL;
......@@ -379,7 +379,7 @@ struct ProcDirEntry *CreateProcEntry(const char *name, mode_t mode, struct ProcD
return pde;
}
static void ProcEntryClearVnode(struct ProcDirEntry *entry)
void ProcEntryClearVnode(struct ProcDirEntry *entry)
{
struct Vnode *item = NULL;
struct Vnode *nextItem = NULL;
......@@ -404,16 +404,14 @@ static void FreeProcEntry(struct ProcDirEntry *entry)
return;
}
ProcEntryClearVnode(entry);
if (entry->pf != NULL) {
free(entry->pf);
entry->pf = NULL;
}
if (entry->data != NULL) {
if ((entry->dataType == PROC_DATA_FREE) && (entry->data != NULL)) {
free(entry->data);
entry->data = NULL;
}
entry->data = NULL;
free(entry);
}
......@@ -424,7 +422,7 @@ void ProcFreeEntry(struct ProcDirEntry *pn)
}
}
static void RemoveProcEntryTravalsal(struct ProcDirEntry *pn)
void RemoveProcEntryTravalsal(struct ProcDirEntry *pn)
{
if (pn == NULL) {
return;
......@@ -432,6 +430,8 @@ static void RemoveProcEntryTravalsal(struct ProcDirEntry *pn)
RemoveProcEntryTravalsal(pn->next);
RemoveProcEntryTravalsal(pn->subdir);
ProcEntryClearVnode(pn);
ProcFreeEntry(pn);
}
......@@ -461,6 +461,9 @@ void RemoveProcEntry(const char *name, struct ProcDirEntry *parent)
spin_unlock(&procfsLock);
RemoveProcEntryTravalsal(pn->subdir);
ProcEntryClearVnode(pn);
ProcFreeEntry(pn);
}
......@@ -475,14 +478,17 @@ struct ProcDirEntry *ProcMkdir(const char *name, struct ProcDirEntry *parent)
}
struct ProcDirEntry *ProcCreateData(const char *name, mode_t mode, struct ProcDirEntry *parent,
const struct ProcFileOperations *procFileOps, void *data)
const struct ProcFileOperations *procFileOps, struct ProcDataParm *param)
{
struct ProcDirEntry *pde = CreateProcEntry(name, mode, parent);
if (pde != NULL) {
if (procFileOps != NULL) {
pde->procFileOps = procFileOps;
}
pde->data = data;
if (param != NULL) {
pde->data = param->data;
pde->dataType = param->dataType;
}
}
return pde;
}
......@@ -639,12 +645,15 @@ int WriteProcFile(struct ProcDirEntry *pde, const void *buf, size_t len)
return -EISDIR;
}
#ifndef LOSCFG_KERNEL_PLIMITS
spin_lock(&procfsLock);
#endif
if ((pde->procFileOps != NULL) && (pde->procFileOps->write != NULL)) {
result = pde->procFileOps->write(pde->pf, (const char *)buf, len, &(pde->pf->fPos));
}
#ifndef LOSCFG_KERNEL_PLIMITS
spin_unlock(&procfsLock);
#endif
return result;
}
......
......@@ -214,7 +214,7 @@ VOID OsPidContainerDestroyAllProcess(LosProcessCB *curr)
for (UINT32 index = 2; index < LOSCFG_BASE_CORE_PROCESS_LIMIT; index++) { /* 2: ordinary process */
SCHEDULER_LOCK(intSave);
LosProcessCB *processCB = OS_PCB_FROM_PID(index);
if (OsProcessIsUnused(processCB)) {
if (OsProcessIsUnused(processCB) || (processCB->parentProcess == NULL)) {
SCHEDULER_UNLOCK(intSave);
continue;
}
......
......@@ -451,7 +451,9 @@ LITE_OS_SEC_TEXT VOID OsProcessResourcesToFree(LosProcessCB *processCB)
}
processCB->files = NULL;
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
OsPLimitsDeleteProcess(processCB);
#endif
if (processCB->resourceLimit != NULL) {
(VOID)LOS_MemFree((VOID *)m_aucSysMem0, processCB->resourceLimit);
processCB->resourceLimit = NULL;
......@@ -606,7 +608,9 @@ UINT32 OsProcessInit(VOID)
#ifdef LOSCFG_KERNEL_CONTAINER
OsInitRootContainer();
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
OsProcLimiterSetInit();
#endif
SystemProcessEarlyInit(OsGetIdleProcess());
SystemProcessEarlyInit(OsGetUserInitProcess());
SystemProcessEarlyInit(OsGetKernelInitProcess());
......@@ -883,6 +887,13 @@ STATIC UINT32 OsSystemProcessInit(LosProcessCB *processCB, UINT32 flags, const C
}
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
ret = OsPLimitsAddProcess(NULL, processCB);
if (ret != LOS_OK) {
ret = LOS_ENOMEM;
goto EXIT;
}
#endif
return LOS_OK;
EXIT:
......@@ -2066,6 +2077,13 @@ STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 si
if (ret != LOS_OK) {
goto ERROR_INIT;
}
#ifdef LOSCFG_KERNEL_PLIMITS
ret = OsPLimitsAddProcess(run->plimits, child);
if (ret != LOS_OK) {
goto ERROR_INIT;
}
#endif
#endif
ret = OsForkInitPCB(flags, child, name, sp, size);
......
......@@ -50,6 +50,9 @@
#ifdef LOSCFG_KERNEL_CONTAINER
#include "los_container_pri.h"
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
#include "los_plimits.h"
#endif
#ifdef __cplusplus
#if __cplusplus
......@@ -139,6 +142,11 @@ typedef struct ProcessCB {
#ifdef LOSCFG_PROC_PROCESS_DIR
struct ProcDirEntry *procDir;
#endif
#ifdef LOSCFG_KERNEL_PLIMITS
ProcLimiterSet *plimits;
LOS_DL_LIST plimitsList; /* plimit process list */
PLimitsData limitStat;
#endif
} LosProcessCB;
extern LosProcessCB *g_processCBArray;
......
......@@ -429,7 +429,7 @@ typedef struct TagTaskCB {
PidContainer *pidContainer;
#endif
#ifdef LOSCFG_IPC_CONTAINER
BOOL cloneIpc;
BOOL cloneIpc;
#endif
} LosTaskCB;
......@@ -619,6 +619,10 @@ STATIC INLINE VOID SchedTaskUnfreeze(LosTaskCB *taskCB)
g_taskScheduled &= ~(1U << (cpuid)); \
} while (0);
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
BOOL OsSchedLimitCheckTime(LosTaskCB *task);
#endif
STATIC INLINE LosTaskCB *HPFRunqueueTopTaskGet(HPFRunqueue *rq)
{
LosTaskCB *newTask = NULL;
......@@ -634,6 +638,12 @@ STATIC INLINE LosTaskCB *HPFRunqueueTopTaskGet(HPFRunqueue *rq)
while (bitmap) {
UINT32 priority = CLZ(bitmap);
LOS_DL_LIST_FOR_EACH_ENTRY(newTask, &queueList->priQueList[priority], LosTaskCB, pendList) {
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
if (!OsSchedLimitCheckTime(newTask)) {
bitmap &= ~(1U << (OS_PRIORITY_QUEUE_NUM - priority - 1));
continue;
}
#endif
#ifdef LOSCFG_KERNEL_SMP
if (newTask->cpuAffiMask & (1U << cpuid)) {
#endif
......
......@@ -54,6 +54,7 @@ extern "C" {
/* scheduler lock */
extern SPIN_LOCK_S g_taskSpin;
#define SCHEDULER_HELD() LOS_SpinHeld(&g_taskSpin)
#define SCHEDULER_LOCK(state) LOS_SpinLockSave(&g_taskSpin, &(state))
#define SCHEDULER_UNLOCK(state) LOS_SpinUnlockRestore(&g_taskSpin, state)
......
......@@ -98,6 +98,9 @@ STATIC VOID HPFTimeSliceUpdate(SchedRunqueue *rq, LosTaskCB *taskCB, UINT64 curr
taskCB->schedStat.timeSliceRealTime += incTime;
#endif
}
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
OsSchedLimitUpdateRuntime(taskCB, currTime, incTime);
#endif
taskCB->irqUsedTime = 0;
taskCB->startTime = currTime;
if (taskCB->timeSlice <= OS_TIME_SLICE_MIN) {
......
......@@ -359,6 +359,12 @@ STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
return LOS_ERRNO_VM_ACCESS_DENIED;
}
#ifdef LOSCFG_KERNEL_PLIMITS
if (OsMemLimitCheckAndMemAdd(PAGE_SIZE) != LOS_OK) {
return LOS_ERRNO_VM_NO_MEMORY;
}
#endif
(VOID)LOS_MuxAcquire(&space->regionMux);
region = LOS_RegionFind(space, vaddr);
if (region == NULL) {
......@@ -450,6 +456,9 @@ VMM_MAP_FAILED:
}
CHECK_FAILED:
OsFaultTryFixup(frame, excVaddr, &status);
#ifdef LOSCFG_KERNEL_PLIMITS
OsMemLimitMemFree(PAGE_SIZE);
#endif
DONE:
(VOID)LOS_MuxRelease(&space->regionMux);
return status;
......
......@@ -34,7 +34,9 @@
#include "los_vm_phys.h"
#include "los_vm_boot.h"
#include "los_vm_filemap.h"
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
#include "los_plimits.h"
#endif
#ifdef LOSCFG_KERNEL_VM
......@@ -81,7 +83,8 @@ VOID OsVmPageStartup(VOID)
* struct LosVmPage occupied, which satisfies the equation:
* nPage * sizeof(LosVmPage) + nPage * PAGE_SIZE = OsVmPhysPageNumGet() * PAGE_SIZE.
*/
nPage = OsVmPhysPageNumGet() * PAGE_SIZE / (sizeof(LosVmPage) + PAGE_SIZE);
UINT32 pageNum = OsVmPhysPageNumGet();
nPage = pageNum * PAGE_SIZE / (sizeof(LosVmPage) + PAGE_SIZE);
g_vmPageArraySize = nPage * sizeof(LosVmPage);
g_vmPageArray = (LosVmPage *)OsVmBootMemAlloc(g_vmPageArraySize);
......@@ -89,6 +92,9 @@ VOID OsVmPageStartup(VOID)
OsVmPhysSegAdd();
OsVmPhysInit();
#ifdef LOSCFG_KERNEL_PLIMITS
OsMemLimitSetLimit(pageNum * PAGE_SIZE);
#endif
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
......
......@@ -456,6 +456,9 @@ VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages)
OsVmPhysPagesFreeContiguous(page, nPages);
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
#ifdef LOSCFG_KERNEL_PLIMITS
OsMemLimitMemFree(nPages * PAGE_SIZE);
#endif
}
PADDR_T OsKVaddrToPaddr(VADDR_T kvaddr)
......@@ -503,6 +506,9 @@ VOID LOS_PhysPageFree(LosVmPage *page)
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
#ifdef LOSCFG_KERNEL_PLIMITS
OsMemLimitMemFree(PAGE_SIZE);
#endif
}
LosVmPage *LOS_PhysPageAlloc(VOID)
......
......@@ -193,40 +193,58 @@ STATIC VOID ShmPagesRefDec(struct shmIDSource *seg)
}
}
STATIC INT32 ShmAllocSeg(key_t key, size_t size, INT32 shmflg)
STATIC INT32 ShmAllocSegCheck(key_t key, size_t *size, INT32 *segNum)
{
INT32 i;
INT32 segNum = -1;
struct shmIDSource *seg = NULL;
size_t count;
if ((size == 0) || (size < IPC_SHM_INFO.shmmin) ||
(size > IPC_SHM_INFO.shmmax)) {
if ((*size == 0) || (*size < IPC_SHM_INFO.shmmin) ||
(*size > IPC_SHM_INFO.shmmax)) {
return -EINVAL;
}
size = LOS_Align(size, PAGE_SIZE);
if ((IPC_SHM_USED_PAGE_COUNT + (size >> PAGE_SHIFT)) > IPC_SHM_INFO.shmall) {
*size = LOS_Align(*size, PAGE_SIZE);
if ((IPC_SHM_USED_PAGE_COUNT + (*size >> PAGE_SHIFT)) > IPC_SHM_INFO.shmall) {
return -ENOMEM;
}
for (i = 0; i < IPC_SHM_INFO.shmmni; i++) {
if (IPC_SHM_SEGS[i].status & SHM_SEG_FREE) {
IPC_SHM_SEGS[i].status &= ~SHM_SEG_FREE;
segNum = i;
*segNum = i;
break;
}
}
if (segNum < 0) {
if (*segNum < 0) {
return -ENOSPC;
}
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
if (OsIPCLimitShmAlloc(*size) != LOS_OK) {
return -ENOMEM;
}
#endif
return 0;
}
STATIC INT32 ShmAllocSeg(key_t key, size_t size, INT32 shmflg)
{
INT32 segNum = -1;
struct shmIDSource *seg = NULL;
size_t count;
INT32 ret = ShmAllocSegCheck(key, &size, &segNum);
if (ret < 0) {
return ret;
}
seg = &IPC_SHM_SEGS[segNum];
count = LOS_PhysPagesAlloc(size >> PAGE_SHIFT, &seg->node);
if (count != (size >> PAGE_SHIFT)) {
(VOID)LOS_PhysPagesFree(&seg->node);
seg->status = SHM_SEG_FREE;
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
OsIPCLimitShmFree(size);
#endif
return -ENOMEM;
}
......@@ -264,6 +282,9 @@ STATIC INLINE VOID ShmFreeSeg(struct shmIDSource *seg, UINT32 *shmUsedPageCount)
VM_ERR("free physical pages failed, count = %d, size = %d", count, seg->ds.shm_segsz >> PAGE_SHIFT);
return;
}
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
OsIPCLimitShmFree(seg->ds.shm_segsz);
#endif
if (shmUsedPageCount != NULL) {
(*shmUsedPageCount) -= seg->ds.shm_segsz >> PAGE_SHIFT;
}
......
......@@ -42,6 +42,7 @@ group("extended") {
"lms",
"perf",
"pipes",
"plimit",
"power",
"trace",
"vdso",
......@@ -62,5 +63,6 @@ config("public") {
"perf:public",
"lms:public",
"power:public",
"plimit:public",
]
}
......@@ -76,6 +76,31 @@ config KERNEL_PIPE
help
Answer Y to enable LiteOS support pipes.
config KERNEL_PLIMITS
bool "Enable plimits Feature"
default n
depends on KERNEL_EXTKERNEL
config KERNEL_MEM_PLIMIT
bool "Enable mem limits Feature"
default n
depends on KERNEL_PLIMITS
config KERNEL_IPC_PLIMIT
bool "Enable ipc limits Feature"
default n
depends on KERNEL_PLIMITS
config KERNEL_DEV_PLIMIT
bool "Enable dev limits Feature"
default n
depends on KERNEL_PLIMITS
config KERNEL_SCHED_PLIMIT
bool "Enable sched limits Feature"
default n
depends on KERNEL_PLIMITS
config BASE_CORE_HILOG
bool "Enable Hilog"
default y
......@@ -104,4 +129,4 @@ source "kernel/extended/perf/Kconfig"
source "kernel/extended/lms/Kconfig"
######################### config options of hilog #########################
source "kernel/extended/hilog/Kconfig"
\ No newline at end of file
source "kernel/extended/hilog/Kconfig"
# Copyright (c) 2023-2023 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.
import("//kernel/liteos_a/liteos.gni")
module_switch = true
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"los_devicelimit.c",
"los_ipclimit.c",
"los_memlimit.c",
"los_plimits.c",
"los_processlimit.c",
"los_schedlimit.c",
]
}
config("public") {
include_dirs = [ "." ]
}
# Copyright (c) 2023-2023 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 $(LITEOSTOPDIR)/config.mk
MODULE_NAME := $(notdir $(shell pwd))
LOCAL_SRCS := $(wildcard *.c)
include $(MODULE)
/*
* Copyright (c) 2023-2023 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 "los_seq_buf.h"
#include "los_bitmap.h"
#include "los_process_pri.h"
#include "los_devicelimit.h"
#ifdef LOSCFG_KERNEL_DEV_PLIMIT
#define TYPE_CHAR_LEN (1)
#define DEVICE_NAME_PREFIX_SPACE (1)
#define DEVICE_ACCESS_MAXLEN (3)
#define BUF_SEPARATOR (5)
STATIC ProcDevLimit *g_procDevLimit = NULL;
VOID OsDevLimitInit(UINTPTR limit)
{
ProcDevLimit *deviceLimit = (ProcDevLimit *)limit;
deviceLimit->behavior = DEVLIMIT_DEFAULT_ALLOW;
LOS_ListInit(&(deviceLimit->accessList));
g_procDevLimit = deviceLimit;
}
VOID *OsDevLimitAlloc(VOID)
{
ProcDevLimit *plimit = (ProcDevLimit *)LOS_KernelMalloc(sizeof(ProcDevLimit));
if (plimit == NULL) {
return NULL;
}
(VOID)memset_s(plimit, sizeof(ProcDevLimit), 0, sizeof(ProcDevLimit));
LOS_ListInit(&(plimit->accessList));
plimit->behavior = DEVLIMIT_DEFAULT_NONE;
LOS_AtomicSet(&plimit->rc, 1);
return (VOID *)plimit;
}
STATIC VOID DevAccessListDelete(ProcDevLimit *devLimit)
{
DevAccessItem *delItem = NULL;
DevAccessItem *tmpItem = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(delItem, tmpItem, &devLimit->accessList, DevAccessItem, list) {
LOS_ListDelete(&delItem->list);
LOS_KernelFree((VOID *)delItem);
}
}
VOID OsDevLimitFree(UINTPTR limit)
{
ProcDevLimit *devLimit = (ProcDevLimit *)limit;
if (devLimit == NULL) {
return;
}
LOS_AtomicDec(&devLimit->rc);
if (LOS_AtomicRead(&devLimit->rc) <= 0) {
DevAccessListDelete(devLimit);
LOS_KernelFree(devLimit);
}
}
STATIC UINT32 DevLimitCopyAccess(ProcDevLimit *devLimitDest, ProcDevLimit *devLimitSrc)
{
DevAccessItem *tmpItem = NULL;
INT32 itemSize = sizeof(DevAccessItem);
devLimitDest->behavior = devLimitSrc->behavior;
LOS_DL_LIST_FOR_EACH_ENTRY(tmpItem, &devLimitSrc->accessList, DevAccessItem, list) {
DevAccessItem *newItem = (DevAccessItem *)LOS_KernelMalloc(itemSize);
if (newItem == NULL) {
return ENOMEM;
}
(VOID)memcpy_s(newItem, sizeof(DevAccessItem), tmpItem, sizeof(DevAccessItem));
LOS_ListTailInsert(&devLimitDest->accessList, &newItem->list);
}
return LOS_OK;
}
VOID OsDevLimitCopy(UINTPTR dest, UINTPTR src)
{
ProcDevLimit *devLimitDest = (ProcDevLimit *)dest;
ProcDevLimit *devLimitSrc = (ProcDevLimit *)src;
(VOID)DevLimitCopyAccess(devLimitDest, devLimitSrc);
devLimitDest->parent = (ProcDevLimit *)src;
}
VOID OsDevLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
{
(VOID)currLimit;
ProcDevLimit *parentDevLimit = (ProcDevLimit *)parentLimit;
LosProcessCB *pcb = (LosProcessCB *)process;
if (pcb == NULL) {
LOS_AtomicInc(&parentDevLimit->rc);
}
}
STATIC INLINE INT32 IsSpace(INT32 c)
{
return (c == ' ' || (unsigned)c - '\t' < BUF_SEPARATOR);
}
STATIC UINT32 ParseItemAccess(const CHAR *buf, DevAccessItem *item)
{
switch (*buf) {
case 'a':
item->type = DEVLIMIT_DEV_ALL;
return LOS_OK;
case 'b':
item->type = DEVLIMIT_DEV_BLOCK;
break;
case 'c':
item->type = DEVLIMIT_DEV_CHAR;
break;
default:
return EINVAL;
}
buf += DEVICE_NAME_PREFIX_SPACE;
if (!IsSpace(*buf)) {
return EINVAL;
}
buf += DEVICE_NAME_PREFIX_SPACE;
for (INT32 count = 0; count < sizeof(item->name) - 1; count++) {
if (IsSpace(*buf)) {
break;
}
item->name[count] = *buf;
buf += TYPE_CHAR_LEN;
}
if (!IsSpace(*buf)) {
return EINVAL;
}
buf += DEVICE_NAME_PREFIX_SPACE;
for (INT32 i = 0; i < DEVICE_ACCESS_MAXLEN; i++) {
switch (*buf) {
case 'r':
item->access |= DEVLIMIT_ACC_READ;
break;
case 'w':
item->access |= DEVLIMIT_ACC_WRITE;
break;
case 'm':
item->access |= DEVLIMIT_ACC_MKNOD;
break;
case '\n':
case '\0':
i = DEVICE_ACCESS_MAXLEN;
break;
default:
return EINVAL;
}
buf += TYPE_CHAR_LEN;
}
return LOS_OK;
}
STATIC BOOL DevLimitMayAllowAll(ProcDevLimit *parent)
{
if (parent == NULL) {
return TRUE;
}
return (parent->behavior == DEVLIMIT_DEFAULT_ALLOW);
}
STATIC BOOL DevLimitHasChildren(ProcLimitSet *procLimitSet, ProcDevLimit *devLimit)
{
ProcLimitSet *parent = procLimitSet;
ProcLimitSet *childProcLimitSet = NULL;
if (devLimit == NULL) {
return FALSE;
}
LOS_DL_LIST_FOR_EACH_ENTRY(childProcLimitSet, &(procLimitSet->childList), ProcLimitSet, childList) {
if (childProcLimitSet == NULL) {
continue;
}
if (childProcLimitSet->parent != parent) {
continue;
}
if (!((childProcLimitSet->mask) & BIT(PROCESS_LIMITER_ID_DEV))) {
continue;
}
return TRUE;
}
return FALSE;
}
STATIC UINT32 DealItemAllAccess(ProcLimitSet *procLimitSet, ProcDevLimit *devLimit,
ProcDevLimit *devParentLimit, INT32 filetype)
{
switch (filetype) {
case DEVLIMIT_ALLOW: {
if (DevLimitHasChildren(procLimitSet, devLimit)) {
return EINVAL;
}
if (!DevLimitMayAllowAll(devParentLimit)) {
return EPERM;
}
DevAccessListDelete(devLimit);
devLimit->behavior = DEVLIMIT_DEFAULT_ALLOW;
if (devParentLimit == NULL) {
break;
}
DevLimitCopyAccess(devLimit, devParentLimit);
break;
}
case DEVLIMIT_DENY: {
if (DevLimitHasChildren(procLimitSet, devLimit)) {
return EINVAL;
}
DevAccessListDelete(devLimit);
devLimit->behavior = DEVLIMIT_DEFAULT_DENY;
break;
}
default:
return EINVAL;
}
return LOS_OK;
}
STATIC BOOL DevLimitMatchItemPartial(LOS_DL_LIST *list, DevAccessItem *item)
{
if ((list == NULL) || (item == NULL)) {
return FALSE;
}
if (LOS_ListEmpty(list)) {
return FALSE;
}
DevAccessItem *walk = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(walk, list, DevAccessItem, list) {
if (item->type != walk->type) {
continue;
}
if ((strcmp(walk->name, "*") != 0) && (strcmp(item->name, "*") != 0)
&& (strcmp(walk->name, item->name) != 0)) {
continue;
}
if (!(item->access & ~(walk->access))) {
return TRUE;
}
}
return FALSE;
}
STATIC BOOL DevLimitParentAllowsRmItem(ProcDevLimit *devParentLimit, DevAccessItem *item)
{
if (devParentLimit == NULL) {
return TRUE;
}
/* Make sure you're not removing part or a whole item existing in the parent plimits */
return !DevLimitMatchItemPartial(&devParentLimit->accessList, item);
}
STATIC BOOL DevLimitMatchItem(LOS_DL_LIST *list, DevAccessItem *item)
{
if ((list == NULL) || (item == NULL)) {
return FALSE;
}
if (LOS_ListEmpty(list)) {
return FALSE;
}
DevAccessItem *walk = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(walk, list, DevAccessItem, list) {
if (item->type != walk->type) {
continue;
}
if ((strcmp(walk->name, "*") != 0) && (strcmp(walk->name, item->name) != 0)) {
continue;
}
if (!(item->access & ~(walk->access))) {
return TRUE;
}
}
return FALSE;
}
/**
* This is used to make sure a child plimits won't have more privileges than its parent
*/
STATIC BOOL DevLimitVerifyNewItem(ProcDevLimit *parent, DevAccessItem *item, INT32 currBehavior)
{
if (parent == NULL) {
return TRUE;
}
if (parent->behavior == DEVLIMIT_DEFAULT_ALLOW) {
if (currBehavior == DEVLIMIT_DEFAULT_ALLOW) {
return TRUE;
}
return !DevLimitMatchItemPartial(&parent->accessList, item);
}
return DevLimitMatchItem(&parent->accessList, item);
}
STATIC BOOL DevLimitParentAllowsAddItem(ProcDevLimit *devParentLimit, DevAccessItem *item, INT32 currBehavior)
{
return DevLimitVerifyNewItem(devParentLimit, item, currBehavior);
}
STATIC VOID DevLimitAccessListRm(ProcDevLimit *devLimit, DevAccessItem *item)
{
if ((item == NULL) || (devLimit == NULL)) {
return;
}
DevAccessItem *walk, *tmp = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(walk, tmp, &devLimit->accessList, DevAccessItem, list) {
if (walk->type != item->type) {
continue;
}
if (strcmp(walk->name, item->name) != 0) {
continue;
}
walk->access &= ~item->access;
if (!walk->access) {
LOS_ListDelete(&walk->list);
LOS_KernelFree((VOID *)walk);
}
}
}
STATIC UINT32 DevLimitAccessListAdd(ProcDevLimit *devLimit, DevAccessItem *item)
{
if ((item == NULL) || (devLimit == NULL)) {
return ENOMEM;
}
DevAccessItem *walk = NULL;
DevAccessItem *newItem = (DevAccessItem *)LOS_KernelMalloc(sizeof(DevAccessItem));
if (newItem == NULL) {
return ENOMEM;
}
(VOID)memcpy_s(newItem, sizeof(DevAccessItem), item, sizeof(DevAccessItem));
LOS_DL_LIST_FOR_EACH_ENTRY(walk, &devLimit->accessList, DevAccessItem, list) {
if (walk->type != item->type) {
continue;
}
if (strcmp(walk->name, item->name) != 0) {
continue;
}
walk->access |= item->access;
LOS_KernelFree((VOID *)newItem);
newItem = NULL;
}
if (newItem != NULL) {
LOS_ListTailInsert(&devLimit->accessList, &newItem->list);
}
return LOS_OK;
}
/**
* Revalidate permissions
*/
STATIC VOID DevLimitRevalidateActiveItems(ProcDevLimit *devLimit, ProcDevLimit *devParentLimit)
{
if ((devLimit == NULL) || (devParentLimit == NULL)) {
return;
}
DevAccessItem *walK = NULL;
DevAccessItem *tmp = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(walK, tmp, &devLimit->accessList, DevAccessItem, list) {
if (!DevLimitParentAllowsAddItem(devParentLimit, walK, devLimit->behavior)) {
DevLimitAccessListRm(devLimit, walK);
}
}
}
/**
* propagates a new item to the children
*/
STATIC UINT32 DevLimitPropagateItem(ProcLimitSet *procLimitSet, ProcDevLimit *devLimit, DevAccessItem *item)
{
UINT32 ret = LOS_OK;
ProcLimitSet *parent = procLimitSet;
ProcLimitSet *childProcLimitSet = NULL;
if ((procLimitSet == NULL) || (item == NULL)) {
return ENOMEM;
}
if (devLimit == NULL) {
return LOS_OK;
}
LOS_DL_LIST_FOR_EACH_ENTRY(childProcLimitSet, &procLimitSet->childList, ProcLimitSet, childList) {
if (childProcLimitSet == NULL) {
continue;
}
if (childProcLimitSet->parent != parent) {
continue;
}
if (!((childProcLimitSet->mask) & BIT(PROCESS_LIMITER_ID_DEV))) {
continue;
}
ProcDevLimit *devLimitChild = (ProcDevLimit *)childProcLimitSet->limitsList[PROCESS_LIMITER_ID_DEV];
if (devLimit->behavior == DEVLIMIT_DEFAULT_ALLOW &&
devLimitChild->behavior == DEVLIMIT_DEFAULT_ALLOW) {
ret = DevLimitAccessListAdd(devLimitChild, item);
} else {
DevLimitAccessListRm(devLimitChild, item);
}
DevLimitRevalidateActiveItems(devLimitChild, (ProcDevLimit *)parent->limitsList[PROCESS_LIMITER_ID_DEV]);
}
return ret;
}
STATIC UINT32 DevLimitUpdateAccess(ProcLimitSet *procLimitSet, const CHAR *buf, INT32 filetype)
{
UINT32 ret;
UINT32 intSave;
DevAccessItem item = {0};
SCHEDULER_LOCK(intSave);
ProcDevLimit *devLimit = (ProcDevLimit *)(procLimitSet->limitsList[PROCESS_LIMITER_ID_DEV]);
ProcDevLimit *devParentLimit = devLimit->parent;
ret = ParseItemAccess(buf, &item);
if (ret != LOS_OK) {
SCHEDULER_UNLOCK(intSave);
return ret;
}
if (item.type == DEVLIMIT_DEV_ALL) {
ret = DealItemAllAccess(procLimitSet, devLimit, devParentLimit, filetype);
SCHEDULER_UNLOCK(intSave);
return ret;
}
switch (filetype) {
case DEVLIMIT_ALLOW: {
if (devLimit->behavior == DEVLIMIT_DEFAULT_ALLOW) {
if (!DevLimitParentAllowsRmItem(devParentLimit, &item)) {
SCHEDULER_UNLOCK(intSave);
return EPERM;
}
DevLimitAccessListRm(devLimit, &item);
break;
}
if (!DevLimitParentAllowsAddItem(devParentLimit, &item, devLimit->behavior)) {
SCHEDULER_UNLOCK(intSave);
return EPERM;
}
ret = DevLimitAccessListAdd(devLimit, &item);
break;
}
case DEVLIMIT_DENY: {
if (devLimit->behavior == DEVLIMIT_DEFAULT_DENY) {
DevLimitAccessListRm(devLimit, &item);
} else {
ret = DevLimitAccessListAdd(devLimit, &item);
}
// update child access list
ret = DevLimitPropagateItem(procLimitSet, devLimit, &item);
break;
}
default:
ret = EINVAL;
break;
}
SCHEDULER_UNLOCK(intSave);
return ret;
}
UINT32 OsDevLimitWriteAllow(ProcLimitSet *plimit, const CHAR *buf, UINT32 size)
{
(VOID)size;
return DevLimitUpdateAccess(plimit, buf, DEVLIMIT_ALLOW);
}
UINT32 OsDevLimitWriteDeny(ProcLimitSet *plimit, const CHAR *buf, UINT32 size)
{
(VOID)size;
return DevLimitUpdateAccess(plimit, buf, DEVLIMIT_DENY);
}
STATIC VOID DevLimitItemSetAccess(CHAR *acc, INT16 access)
{
INT32 index = 0;
(VOID)memset_s(acc, ACCLEN, 0, ACCLEN);
if (access & DEVLIMIT_ACC_READ) {
acc[index++] = 'r';
}
if (access & DEVLIMIT_ACC_WRITE) {
acc[index++] = 'w';
}
if (access & DEVLIMIT_ACC_MKNOD) {
acc[index++] = 'm';
}
}
STATIC CHAR DevLimitItemTypeToChar(INT16 type)
{
if (type == DEVLIMIT_DEV_ALL) {
return 'a';
} else if (type == DEVLIMIT_DEV_CHAR) {
return 'c';
} else if (type == DEVLIMIT_DEV_BLOCK) {
return 'b';
}
return 'X';
}
UINT32 OsDevLimitShow(ProcDevLimit *devLimit, struct SeqBuf *seqBuf)
{
DevAccessItem *item = NULL;
CHAR acc[ACCLEN];
UINT32 intSave;
if ((devLimit == NULL) || (seqBuf == NULL)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
if (devLimit->behavior == DEVLIMIT_DEFAULT_ALLOW) {
DevLimitItemSetAccess(acc, DEVLIMIT_ACC_MASK);
SCHEDULER_UNLOCK(intSave);
LosBufPrintf(seqBuf, "%c %s %s\n", DevLimitItemTypeToChar(DEVLIMIT_DEV_ALL), "*", acc);
return LOS_OK;
}
LOS_DL_LIST_FOR_EACH_ENTRY(item, &devLimit->accessList, DevAccessItem, list) {
DevLimitItemSetAccess(acc, item->access);
LosBufPrintf(seqBuf, "%c %s %s\n", DevLimitItemTypeToChar(item->type), item->name, acc);
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
STATIC INLINE INT16 ConversionDevType(INT32 vnodeType)
{
INT16 type = 0;
if (vnodeType == VNODE_TYPE_BLK) {
type = DEVLIMIT_DEV_BLOCK;
} else if (vnodeType == VNODE_TYPE_CHR) {
type = DEVLIMIT_DEV_CHAR;
}
return type;
}
STATIC INLINE INT16 ConversionDevAccess(INT32 flags)
{
INT16 access = 0;
if ((flags & O_ACCMODE) == O_RDONLY) {
access |= DEVLIMIT_ACC_READ;
}
if (flags & O_WRONLY) {
access |= DEVLIMIT_ACC_WRITE;
}
if (flags & O_RDWR) {
access |= DEVLIMIT_ACC_WRITE | DEVLIMIT_ACC_READ;
}
if (flags & O_CREAT) {
access |= DEVLIMIT_ACC_MKNOD;
}
return access;
}
UINT32 OsDevLimitCheckPermission(INT32 vnodeType, const CHAR *pathName, INT32 flags)
{
BOOL matched = FALSE;
DevAccessItem item = {0};
LosProcessCB *run = OsCurrProcessGet();
if ((run == NULL) || (run->plimits == NULL)) {
return LOS_OK;
}
if (pathName == NULL) {
return EINVAL;
}
ProcDevLimit *devLimit = (ProcDevLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_DEV];
item.type = ConversionDevType(vnodeType);
item.access = ConversionDevAccess(flags);
LOS_ListInit(&(item.list));
(VOID)strncpy_s(item.name, PATH_MAX, pathName, PATH_MAX);
if (devLimit->behavior == DEVLIMIT_DEFAULT_ALLOW) {
matched = !DevLimitMatchItemPartial(&devLimit->accessList, &item);
} else {
matched = DevLimitMatchItem(&devLimit->accessList, &item);
}
if (!matched) {
return EPERM;
}
return LOS_OK;
}
#endif
/*
* Copyright (c) 2023-2023 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.
*/
#ifndef _LOS_DEVICELIMIT_H
#define _LOS_DEVICELIMIT_H
#include "los_typedef.h"
#include "los_atomic.h"
#include "los_list.h"
#include "vfs_config.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define DEVLIMIT_ACC_MKNOD 1
#define DEVLIMIT_ACC_READ 2
#define DEVLIMIT_ACC_WRITE 4
#define DEVLIMIT_ACC_MASK (DEVLIMIT_ACC_MKNOD | DEVLIMIT_ACC_READ | DEVLIMIT_ACC_WRITE)
#define DEVLIMIT_DEV_BLOCK 1
#define DEVLIMIT_DEV_CHAR 2
#define DEVLIMIT_DEV_ALL 4 /* all devices */
#define DEVLIMIT_ALLOW 1
#define DEVLIMIT_DENY 2
#define ACCLEN 4
struct SeqBuf;
typedef struct TagPLimiterSet ProcLimitSet;
enum DevLimitBehavior {
DEVLIMIT_DEFAULT_NONE,
DEVLIMIT_DEFAULT_ALLOW,
DEVLIMIT_DEFAULT_DENY,
};
typedef struct DevAccessItem {
INT16 type;
INT16 access;
LOS_DL_LIST list;
CHAR name[PATH_MAX];
} DevAccessItem;
typedef struct ProcDevLimit {
struct ProcDevLimit *parent;
Atomic rc;
UINT8 allowFile;
UINT8 denyFile;
LOS_DL_LIST accessList; // device belong to devicelimite
enum DevLimitBehavior behavior;
} ProcDevLimit;
VOID OsDevLimitInit(UINTPTR limit);
VOID *OsDevLimitAlloc(VOID);
VOID OsDevLimitFree(UINTPTR limit);
VOID OsDevLimitCopy(UINTPTR dest, UINTPTR src);
VOID OsDevLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process);
UINT32 OsDevLimitWriteAllow(ProcLimitSet *plimit, const CHAR *buf, UINT32 size);
UINT32 OsDevLimitWriteDeny(ProcLimitSet *plimit, const CHAR *buf, UINT32 size);
UINT32 OsDevLimitShow(ProcDevLimit *devLimit, struct SeqBuf *seqBuf);
UINT32 OsDevLimitCheckPermission(INT32 vnodeType, const CHAR *pathName, INT32 flags);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_DEVICELIMIT_H */
/*
* Copyright (c) 2023-2023 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 "los_ipclimit.h"
#include "los_process_pri.h"
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
STATIC ProcIPCLimit *g_rootIPCLimit = NULL;
#define PLIMIT_IPC_SHM_LIMIT_MAX 104857600
VOID OsIPCLimitInit(UINTPTR limite)
{
ProcIPCLimit *plimite = (ProcIPCLimit *)limite;
plimite->mqCountLimit = LOSCFG_BASE_IPC_QUEUE_LIMIT;
plimite->shmSizeLimit = PLIMIT_IPC_SHM_LIMIT_MAX;
g_rootIPCLimit = plimite;
}
VOID *OsIPCLimitAlloc(VOID)
{
ProcIPCLimit *plimite = (ProcIPCLimit *)LOS_KernelMalloc(sizeof(ProcIPCLimit));
if (plimite == NULL) {
return NULL;
}
(VOID)memset_s(plimite, sizeof(ProcIPCLimit), 0, sizeof(ProcIPCLimit));
LOS_AtomicSet(&plimite->rc, 1);
return (VOID *)plimite;
}
VOID OsIPCLimitFree(UINTPTR limite)
{
ProcIPCLimit *plimite = (ProcIPCLimit *)limite;
if (plimite == NULL) {
return;
}
LOS_AtomicDec(&plimite->rc);
if (LOS_AtomicRead(&plimite->rc) <= 0) {
LOS_KernelFree((VOID *)plimite);
}
}
VOID OsIPCLimitCopy(UINTPTR dest, UINTPTR src)
{
ProcIPCLimit *plimiteDest = (ProcIPCLimit *)dest;
ProcIPCLimit *plimiteSrc = (ProcIPCLimit *)src;
plimiteDest->mqCountLimit = plimiteSrc->mqCountLimit;
plimiteDest->shmSizeLimit = plimiteSrc->shmSizeLimit;
return;
}
BOOL OsIPCLimiteMigrateCheck(UINTPTR curr, UINTPTR parent)
{
ProcIPCLimit *currIpcLimit = (ProcIPCLimit *)curr;
ProcIPCLimit *parentIpcLimit = (ProcIPCLimit *)parent;
if ((currIpcLimit->mqCount + parentIpcLimit->mqCount) >= parentIpcLimit->mqCountLimit) {
return FALSE;
}
if ((currIpcLimit->shmSize + parentIpcLimit->shmSize) >= parentIpcLimit->shmSizeLimit) {
return FALSE;
}
return TRUE;
}
VOID OsIPCLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
{
ProcIPCLimit *currIpcLimit = (ProcIPCLimit *)currLimit;
ProcIPCLimit *parentIpcLimit = (ProcIPCLimit *)parentLimit;
LosProcessCB *pcb = (LosProcessCB *)process;
if (pcb == NULL) {
parentIpcLimit->mqCount += currIpcLimit->mqCount;
parentIpcLimit->mqFailedCount += currIpcLimit->mqFailedCount;
parentIpcLimit->shmSize += currIpcLimit->shmSize;
parentIpcLimit->shmFailedCount += currIpcLimit->shmFailedCount;
LOS_AtomicInc(&parentIpcLimit->rc);
return;
}
parentIpcLimit->mqCount -= pcb->limitStat.mqCount;
parentIpcLimit->shmSize -= pcb->limitStat.shmSize;
currIpcLimit->mqCount += pcb->limitStat.mqCount;
currIpcLimit->shmSize += pcb->limitStat.shmSize;
}
BOOL OsIPCLimitAddProcessCheck(UINTPTR limit, UINTPTR process)
{
ProcIPCLimit *ipcLimit = (ProcIPCLimit *)limit;
LosProcessCB *pcb = (LosProcessCB *)process;
if ((ipcLimit->mqCount + pcb->limitStat.mqCount) >= ipcLimit->mqCountLimit) {
return FALSE;
}
if ((ipcLimit->shmSize + pcb->limitStat.shmSize) >= ipcLimit->shmSizeLimit) {
return FALSE;
}
return TRUE;
}
VOID OsIPCLimitAddProcess(UINTPTR limit, UINTPTR process)
{
LosProcessCB *pcb = (LosProcessCB *)process;
ProcIPCLimit *plimits = (ProcIPCLimit *)limit;
plimits->mqCount += pcb->limitStat.mqCount;
plimits->shmSize += pcb->limitStat.shmSize;
return;
}
VOID OsIPCLimitDelProcess(UINTPTR limit, UINTPTR process)
{
LosProcessCB *pcb = (LosProcessCB *)process;
ProcIPCLimit *plimits = (ProcIPCLimit *)limit;
plimits->mqCount -= pcb->limitStat.mqCount;
plimits->shmSize -= pcb->limitStat.shmSize;
return;
}
UINT32 OsIPCLimitSetMqLimit(ProcIPCLimit *ipcLimit, UINT32 value)
{
UINT32 intSave;
if ((ipcLimit == NULL) || (value == 0) || (value > LOSCFG_BASE_IPC_QUEUE_LIMIT)) {
return EINVAL;
}
if (ipcLimit == g_rootIPCLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
if (value < ipcLimit->mqCount) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
ipcLimit->mqCountLimit = value;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT32 OsIPCLimitSetShmLimit(ProcIPCLimit *ipcLimit, UINT32 value)
{
UINT32 intSave;
if ((ipcLimit == NULL) || (value == 0) || (value > PLIMIT_IPC_SHM_LIMIT_MAX)) {
return EINVAL;
}
if (ipcLimit == g_rootIPCLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
if (value < ipcLimit->shmSize) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
ipcLimit->shmSizeLimit = value;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT32 OsIPCLimitMqAlloc(VOID)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
LosProcessCB *run = OsCurrProcessGet();
ProcIPCLimit *ipcLimit = (ProcIPCLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_IPC];
if (ipcLimit->mqCount >= ipcLimit->mqCountLimit) {
ipcLimit->mqFailedCount++;
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
run->limitStat.mqCount++;
ipcLimit->mqCount++;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
VOID OsIPCLimitMqFree(VOID)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
LosProcessCB *run = OsCurrProcessGet();
ProcIPCLimit *ipcLimit = (ProcIPCLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_IPC];
ipcLimit->mqCount--;
run->limitStat.mqCount--;
SCHEDULER_UNLOCK(intSave);
return;
}
UINT32 OsIPCLimitShmAlloc(UINT32 size)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
LosProcessCB *run = OsCurrProcessGet();
ProcIPCLimit *ipcLimit = (ProcIPCLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_IPC];
if ((ipcLimit->shmSize + size) >= ipcLimit->shmSizeLimit) {
ipcLimit->shmFailedCount++;
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
run->limitStat.shmSize += size;
ipcLimit->shmSize += size;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
VOID OsIPCLimitShmFree(UINT32 size)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
LosProcessCB *run = OsCurrProcessGet();
ProcIPCLimit *ipcLimit = (ProcIPCLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_IPC];
ipcLimit->shmSize -= size;
run->limitStat.shmSize -= size;
SCHEDULER_UNLOCK(intSave);
return;
}
#endif
/*
* 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.
*/
#ifndef _LOS_IPCLIMIT_H
#define _LOS_IPCLIMIT_H
#include "los_typedef.h"
#include "los_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct ProcIPCLimit {
Atomic rc;
UINT32 mqCount;
UINT32 mqFailedCount;
UINT32 mqCountLimit;
UINT32 shmSize;
UINT32 shmFailedCount;
UINT32 shmSizeLimit;
UINT64 migrateTime;
} ProcIPCLimit;
enum IPCStatType {
IPC_STAT_TYPE_MQ = 0,
IPC_STAT_TYPE_SHM = 3,
IPC_STAT_TYPE_BUT // buttock
};
enum IPCStatOffset {
IPC_STAT_OFFSET_MQ = 0,
IPC_STAT_OFFSET_SHM = 3,
IPC_STAT_OFFSET_BUT // buttock
};
enum StatItem {
STAT_ITEM_TOTAL,
STAT_ITEM_FAILED,
STAT_ITEM_LIMIT,
STAT_ITEM_BUT // buttock
};
VOID OsIPCLimitInit(UINTPTR limite);
VOID *OsIPCLimitAlloc(VOID);
VOID OsIPCLimitFree(UINTPTR limite);
VOID OsIPCLimitCopy(UINTPTR dest, UINTPTR src);
BOOL OsIPCLimiteMigrateCheck(UINTPTR curr, UINTPTR parent);
VOID OsIPCLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process);
BOOL OsIPCLimitAddProcessCheck(UINTPTR limit, UINTPTR process);
VOID OsIPCLimitAddProcess(UINTPTR limit, UINTPTR process);
VOID OsIPCLimitDelProcess(UINTPTR limit, UINTPTR process);
UINT32 OsIPCLimitSetMqLimit(ProcIPCLimit *ipcLimit, UINT32 value);
UINT32 OsIPCLimitSetShmLimit(ProcIPCLimit *ipcLimit, UINT32 value);
UINT32 OsIPCLimitMqAlloc(VOID);
VOID OsIPCLimitMqFree(VOID);
UINT32 OsIPCLimitShmAlloc(UINT32 size);
VOID OsIPCLimitShmFree(UINT32 size);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_IPCIMIT_H */
/*
* 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));
LOS_AtomicSet(&plimite->rc, 1);
return (VOID *)plimite;
}
VOID OsMemLimiterFree(UINTPTR limite)
{
ProcMemLimiter *plimite = (ProcMemLimiter *)limite;
if (plimite == NULL) {
return;
}
LOS_AtomicDec(&plimite->rc);
if (LOS_AtomicRead(&plimite->rc) <= 0) {
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;
}
LOS_AtomicInc(&parentMemLimit->rc);
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
/*
* 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.
*/
#ifndef _LOS_MEMLIMIT_H
#define _LOS_MEMLIMIT_H
#include "los_typedef.h"
#include "los_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct ProcMemLimiter {
Atomic rc;
UINT64 usage;
UINT64 limit;
UINT64 peak;
UINT32 failcnt;
} ProcMemLimiter;
VOID OsMemLimiterInit(UINTPTR limite);
VOID *OsMemLimiterAlloc(VOID);
VOID OsMemLimiterFree(UINTPTR limite);
VOID OsMemLimiterCopy(UINTPTR dest, UINTPTR src);
BOOL MemLimiteMigrateCheck(UINTPTR curr, UINTPTR parent);
VOID OsMemLimiterMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process);
BOOL OsMemLimitAddProcessCheck(UINTPTR limit, UINTPTR process);
VOID OsMemLimitAddProcess(UINTPTR limit, UINTPTR process);
VOID OsMemLimitDelProcess(UINTPTR limit, UINTPTR process);
UINT32 OsMemLimitSetMemLimit(ProcMemLimiter *memLimit, UINT64 value);
VOID OsMemLimitSetLimit(UINTPTR limit);
UINT32 OsMemLimitCheckAndMemAdd(UINT32 size);
VOID OsMemLimitMemFree(UINT32 size);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_MEMLIMIT_H */
/*
* Copyright (c) 2023-2023 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 "los_base.h"
#include "los_process_pri.h"
#include "hal_timer.h"
#include "los_plimits.h"
#ifdef LOSCFG_KERNEL_PLIMITS
typedef struct PlimiteOperations {
VOID (*LimiterInit)(UINTPTR);
VOID *(*LimiterAlloc)(VOID);
VOID (*LimiterFree)(UINTPTR);
VOID (*LimiterCopy)(UINTPTR, UINTPTR);
BOOL (*LimiterAddProcessCheck)(UINTPTR, UINTPTR);
VOID (*LimiterAddProcess)(UINTPTR, UINTPTR);
VOID (*LimiterDelProcess)(UINTPTR, UINTPTR);
BOOL (*LimiterMigrateCheck)(UINTPTR, UINTPTR);
VOID (*LimiterMigrate)(UINTPTR, UINTPTR, UINTPTR);
} PlimiteOperations;
static PlimiteOperations g_limiteOps[PROCESS_LIMITER_COUNT] = {
[PROCESS_LIMITER_ID_PIDS] = {
.LimiterInit = PidLimiterInit,
.LimiterAlloc = PidLimiterAlloc,
.LimiterFree = PidLimterFree,
.LimiterCopy = PidLimiterCopy,
.LimiterAddProcessCheck = OsPidLimitAddProcessCheck,
.LimiterAddProcess = OsPidLimitAddProcess,
.LimiterDelProcess = OsPidLimitDelProcess,
.LimiterMigrateCheck = PidLimitMigrateCheck,
.LimiterMigrate = OsPidLimiterMigrate,
},
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
[PROCESS_LIMITER_ID_MEM] = {
.LimiterInit = OsMemLimiterInit,
.LimiterAlloc = OsMemLimiterAlloc,
.LimiterFree = OsMemLimiterFree,
.LimiterCopy = OsMemLimiterCopy,
.LimiterAddProcessCheck = OsMemLimitAddProcessCheck,
.LimiterAddProcess = OsMemLimitAddProcess,
.LimiterDelProcess = OsMemLimitDelProcess,
.LimiterMigrateCheck = MemLimiteMigrateCheck,
.LimiterMigrate = OsMemLimiterMigrate,
},
#endif
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
[PROCESS_LIMITER_ID_SCHED] = {
.LimiterInit = OsSchedLimitInit,
.LimiterAlloc = OsSchedLimitAlloc,
.LimiterFree = OsSchedLimitFree,
.LimiterCopy = OsSchedLimitCopy,
.LimiterAddProcessCheck = NULL,
.LimiterAddProcess = NULL,
.LimiterDelProcess = NULL,
.LimiterMigrateCheck = NULL,
.LimiterMigrate = OsSchedLimitMigrate,
},
#endif
#ifdef LOSCFG_KERNEL_DEV_PLIMIT
[PROCESS_LIMITER_ID_DEV] = {
.LimiterInit = OsDevLimitInit,
.LimiterAlloc = OsDevLimitAlloc,
.LimiterFree = OsDevLimitFree,
.LimiterCopy = OsDevLimitCopy,
.LimiterAddProcessCheck = NULL,
.LimiterAddProcess = NULL,
.LimiterDelProcess = NULL,
.LimiterMigrateCheck = NULL,
.LimiterMigrate = OsDevLimitMigrate,
},
#endif
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
[PROCESS_LIMITER_ID_IPC] = {
.LimiterInit = OsIPCLimitInit,
.LimiterAlloc = OsIPCLimitAlloc,
.LimiterFree = OsIPCLimitFree,
.LimiterCopy = OsIPCLimitCopy,
.LimiterAddProcessCheck = OsIPCLimitAddProcessCheck,
.LimiterAddProcess = OsIPCLimitAddProcess,
.LimiterDelProcess = OsIPCLimitDelProcess,
.LimiterMigrateCheck = OsIPCLimiteMigrateCheck,
.LimiterMigrate = OsIPCLimitMigrate,
},
#endif
};
STATIC ProcLimiterSet *g_rootPLimite = NULL;
ProcLimiterSet *OsRootPLimitsGet(VOID)
{
return g_rootPLimite;
}
UINT32 OsProcLimiterSetInit(VOID)
{
g_rootPLimite = (ProcLimiterSet *)LOS_KernelMalloc(sizeof(ProcLimiterSet));
if (g_rootPLimite == NULL) {
return ENOMEM;
}
(VOID)memset_s(g_rootPLimite, sizeof(ProcLimiterSet), 0, sizeof(ProcLimiterSet));
LOS_ListInit(&g_rootPLimite->childList);
LOS_ListInit(&g_rootPLimite->processList);
ProcLimiterSet *procLimiterSet = g_rootPLimite;
for (INT32 plimiteID = 0; plimiteID < PROCESS_LIMITER_COUNT; ++plimiteID) {
procLimiterSet->limitsList[plimiteID] = (UINTPTR)g_limiteOps[plimiteID].LimiterAlloc();
if (procLimiterSet->limitsList[plimiteID] == (UINTPTR)NULL) {
OsPLimitsFree(procLimiterSet);
return ENOMEM;
}
if (g_limiteOps[plimiteID].LimiterInit != NULL) {
g_limiteOps[plimiteID].LimiterInit(procLimiterSet->limitsList[plimiteID]);
}
}
return LOS_OK;
}
STATIC UINT32 PLimitsAddProcess(ProcLimiterSet *plimits, LosProcessCB *processCB)
{
UINT32 limitsID;
if (plimits == NULL) {
plimits = g_rootPLimite;
}
if (processCB->plimits == g_rootPLimite) {
return EPERM;
}
if (processCB->plimits == plimits) {
return LOS_OK;
}
for (limitsID = 0; limitsID < PROCESS_LIMITER_COUNT; limitsID++) {
if (g_limiteOps[limitsID].LimiterAddProcessCheck == NULL) {
continue;
}
if (!g_limiteOps[limitsID].LimiterAddProcessCheck(plimits->limitsList[limitsID], (UINTPTR)processCB)) {
return EACCES;
}
}
for (limitsID = 0; limitsID < PROCESS_LIMITER_COUNT; limitsID++) {
if (g_limiteOps[limitsID].LimiterAddProcess == NULL) {
continue;
}
g_limiteOps[limitsID].LimiterAddProcess(plimits->limitsList[limitsID], (UINTPTR)processCB);
}
LOS_ListTailInsert(&plimits->processList, &processCB->plimitsList);
plimits->pidCount++;
processCB->plimits = plimits;
return LOS_OK;
}
UINT32 OsPLimitsAddProcess(ProcLimiterSet *plimits, LosProcessCB *processCB)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
UINT32 ret = PLimitsAddProcess(plimits, processCB);
SCHEDULER_UNLOCK(intSave);
return ret;
}
UINT32 OsPLimitsAddPid(ProcLimiterSet *plimits, UINT32 pid)
{
UINT32 intSave, ret;
if ((plimits == NULL) || OS_PID_CHECK_INVALID(pid) || (pid == 0)) {
return EINVAL;
}
if (plimits == g_rootPLimite) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
LosProcessCB *processCB = OS_PCB_FROM_PID((unsigned int)pid);
if (OsProcessIsInactive(processCB)) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
ret = PLimitsAddProcess(plimits, processCB);
SCHEDULER_UNLOCK(intSave);
return ret;
}
STATIC VOID PLimitsDeleteProcess(LosProcessCB *processCB)
{
if ((processCB == NULL) || (processCB->plimits == NULL)) {
return;
}
ProcLimiterSet *plimits = processCB->plimits;
for (UINT32 limitsID = 0; limitsID < PROCESS_LIMITER_COUNT; limitsID++) {
if (g_limiteOps[limitsID].LimiterDelProcess == NULL) {
continue;
}
g_limiteOps[limitsID].LimiterDelProcess(plimits->limitsList[limitsID], (UINTPTR)processCB);
}
plimits->pidCount--;
LOS_ListDelete(&processCB->plimitsList);
processCB->plimits = NULL;
return;
}
VOID OsPLimitsDeleteProcess(LosProcessCB *processCB)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
PLimitsDeleteProcess(processCB);
SCHEDULER_UNLOCK(intSave);
}
UINT32 OsPLimitsPidsGet(const ProcLimiterSet *plimits, UINT32 *pids, UINT32 size)
{
UINT32 intSave;
LosProcessCB *processCB = NULL;
UINT32 minSize = LOS_GetSystemProcessMaximum() * sizeof(UINT32);
if ((plimits == NULL) || (pids == NULL) || (size < minSize)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
LOS_DL_LIST *listHead = (LOS_DL_LIST *)&plimits->processList;
if (LOS_ListEmpty(listHead)) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
LOS_DL_LIST_FOR_EACH_ENTRY(processCB, listHead, LosProcessCB, plimitsList) {
pids[OsGetPid(processCB)] = 1;
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
STATIC VOID PLimitsProcessMerge(ProcLimiterSet *currPLimits, ProcLimiterSet *parentPLimits)
{
LOS_DL_LIST *head = &currPLimits->processList;
while (!LOS_ListEmpty(head)) {
LosProcessCB *processCB = LOS_DL_LIST_ENTRY(head->pstNext, LosProcessCB, plimitsList);
PLimitsDeleteProcess(processCB);
PLimitsAddProcess(parentPLimits, processCB);
}
LOS_ListDelete(&currPLimits->childList);
currPLimits->parent = NULL;
return;
}
STATIC UINT32 PLimitsMigrateCheck(ProcLimiterSet *currPLimits, ProcLimiterSet *parentPLimits)
{
for (UINT32 limiteID = 0; limiteID < PROCESS_LIMITER_COUNT; limiteID++) {
UINTPTR currLimit = currPLimits->limitsList[limiteID];
UINTPTR parentLimit = parentPLimits->limitsList[limiteID];
if (g_limiteOps[limiteID].LimiterMigrateCheck == NULL) {
continue;
}
if (!g_limiteOps[limiteID].LimiterMigrateCheck(currLimit, parentLimit)) {
return EPERM;
}
}
return LOS_OK;
}
UINT32 OsPLimitsFree(ProcLimiterSet *currPLimits)
{
UINT32 intSave, ret;
if (currPLimits == NULL) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
ProcLimiterSet *parentPLimits = currPLimits->parent;
ret = PLimitsMigrateCheck(currPLimits, parentPLimits);
if (ret != LOS_OK) {
SCHEDULER_UNLOCK(intSave);
return ret;
}
PLimitsProcessMerge(currPLimits, parentPLimits);
SCHEDULER_UNLOCK(intSave);
for (INT32 limiteID = 0; limiteID < PROCESS_LIMITER_COUNT; ++limiteID) {
UINTPTR procLimiter = currPLimits->limitsList[limiteID];
if (g_limiteOps[limiteID].LimiterFree != NULL) {
g_limiteOps[limiteID].LimiterFree(procLimiter);
}
}
LOS_KernelFree(currPLimits);
return LOS_OK;
}
ProcLimiterSet *OsPLimitsCreate(ProcLimiterSet *parentPLimits)
{
UINT32 intSave;
ProcLimiterSet *newPLimits = (ProcLimiterSet *)LOS_MemAlloc(m_aucSysMem1, sizeof(ProcLimiterSet));
if (newPLimits == NULL) {
return NULL;
}
(VOID)memset_s(newPLimits, sizeof(ProcLimiterSet), 0, sizeof(ProcLimiterSet));
LOS_ListInit(&newPLimits->childList);
LOS_ListInit(&newPLimits->processList);
SCHEDULER_LOCK(intSave);
newPLimits->parent = parentPLimits;
newPLimits->level = parentPLimits->level + 1;
newPLimits->mask = parentPLimits->mask;
for (INT32 plimiteID = 0; plimiteID < PROCESS_LIMITER_COUNT; ++plimiteID) {
newPLimits->limitsList[plimiteID] = (UINTPTR)g_limiteOps[plimiteID].LimiterAlloc();
if (newPLimits->limitsList[plimiteID] == (UINTPTR)NULL) {
SCHEDULER_UNLOCK(intSave);
OsPLimitsFree(newPLimits);
return NULL;
}
if (g_limiteOps[plimiteID].LimiterCopy != NULL) {
g_limiteOps[plimiteID].LimiterCopy(newPLimits->limitsList[plimiteID],
parentPLimits->limitsList[plimiteID]);
}
}
LOS_ListTailInsert(&g_rootPLimite->childList, &newPLimits->childList);
(VOID)PLimitsDeleteProcess(OsCurrProcessGet());
(VOID)PLimitsAddProcess(newPLimits, OsCurrProcessGet());
SCHEDULER_UNLOCK(intSave);
return newPLimits;
}
UINT32 OsPLimitsAddLimiters(ProcLimiterSet *procLimiterSet, enum ProcLimiterID plimiteID)
{
UINT32 intSave;
UINT32 mask = BIT(plimiteID);
if ((procLimiterSet == NULL) || (plimiteID > PROCESS_LIMITER_COUNT)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
if (procLimiterSet->level == 0) {
SCHEDULER_UNLOCK(intSave);
return EPERM;
}
if (procLimiterSet->mask & mask) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
UINTPTR currLimit = procLimiterSet->limitsList[plimiteID];
UINTPTR parentPLimit = procLimiterSet->parent->limitsList[plimiteID];
procLimiterSet->limitsList[plimiteID] = (UINTPTR)g_limiteOps[plimiteID].LimiterAlloc();
if (procLimiterSet->limitsList[plimiteID] == (UINTPTR)NULL) {
procLimiterSet->limitsList[plimiteID] = parentPLimit;
SCHEDULER_UNLOCK(intSave);
return ENOMEM;
}
g_limiteOps[plimiteID].LimiterCopy(procLimiterSet->limitsList[plimiteID], parentPLimit);
g_limiteOps[plimiteID].LimiterMigrate(procLimiterSet->limitsList[plimiteID],
parentPLimit, (UINTPTR)OsCurrProcessGet());
g_limiteOps[plimiteID].LimiterFree(currLimit);
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT32 OsPLimitsDeleteLimiters(ProcLimiterSet *procLimiterSet, enum ProcLimiterID plimiteID, UINT32 *mask)
{
UINT32 intSave;
if ((procLimiterSet == NULL) || (plimiteID > PROCESS_LIMITER_COUNT) || (mask == NULL)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
if (!(procLimiterSet->mask & BIT(plimiteID))) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
if (procLimiterSet->level == 0) {
SCHEDULER_UNLOCK(intSave);
return EPERM;
}
UINTPTR currLimit = procLimiterSet->limitsList[plimiteID];
UINTPTR parentPLimit = procLimiterSet->parent->limitsList[plimiteID];
if ((g_limiteOps[plimiteID].LimiterMigrateCheck != NULL) &&
!g_limiteOps[plimiteID].LimiterMigrateCheck(currLimit, parentPLimit)) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
g_limiteOps[plimiteID].LimiterMigrate(currLimit, parentPLimit, 0);
procLimiterSet->limitsList[plimiteID] = parentPLimit;
g_limiteOps[plimiteID].LimiterFree(currLimit);
procLimiterSet->mask &= (~BIT(plimiteID));
*mask = procLimiterSet->mask;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
UINT32 OsPLimitsMemUsageGet(ProcLimiterSet *plimits, UINT64 *usage, UINT32 size)
{
UINT32 intSave;
LosProcessCB *processCB = NULL;
UINT32 minSize = LOS_GetSystemProcessMaximum() * sizeof(UINT64) + sizeof(ProcMemLimiter);
ProcMemLimiter *memLimit = (ProcMemLimiter *)usage;
UINT64 *memSuage = (UINT64 *)((UINTPTR)usage + sizeof(ProcMemLimiter));
if ((plimits == NULL) || (usage == NULL) || (size < minSize)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(memLimit, sizeof(ProcMemLimiter),
(VOID *)plimits->limitsList[PROCESS_LIMITER_ID_MEM], sizeof(ProcMemLimiter));
LOS_DL_LIST *listHead = (LOS_DL_LIST *)&plimits->processList;
if (LOS_ListEmpty(listHead)) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
LOS_DL_LIST_FOR_EACH_ENTRY(processCB, listHead, LosProcessCB, plimitsList) {
memSuage[OsGetPid(processCB)] = processCB->limitStat.memUsed;
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#endif
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
UINT32 OsPLimitsIPCStatGet(ProcLimiterSet *plimits, ProcIPCLimit *ipc, UINT32 size)
{
UINT32 intSave;
if ((plimits == NULL) || (ipc == NULL) || (size != sizeof(ProcIPCLimit))) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
(VOID)memcpy_s(ipc, sizeof(ProcIPCLimit),
(VOID *)plimits->limitsList[PROCESS_LIMITER_ID_IPC], sizeof(ProcIPCLimit));
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#endif
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
UINT32 OsPLimitsSchedUsageGet(ProcLimiterSet *plimits, UINT64 *usage, UINT32 size)
{
UINT32 intSave;
LosProcessCB *processCB = NULL;
UINT32 minSize = LOS_GetSystemProcessMaximum() * sizeof(UINT64);
if ((plimits == NULL) || (usage == NULL) || (size < minSize)) {
return EINVAL;
}
SCHEDULER_LOCK(intSave);
LOS_DL_LIST *listHead = (LOS_DL_LIST *)&plimits->processList;
if (LOS_ListEmpty(listHead)) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
LOS_DL_LIST_FOR_EACH_ENTRY(processCB, listHead, LosProcessCB, plimitsList) {
usage[OsGetPid(processCB)] = processCB->limitStat.allRuntime;
}
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#endif
#endif
/*
* Copyright (c) 2023-2023 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.
*/
#ifndef _LOS_PLIMITS_H
#define _LOS_PLIMITS_H
#include "los_list.h"
#include "los_typedef.h"
#include "los_processlimit.h"
#include "los_memlimit.h"
#include "los_ipclimit.h"
#include "los_devicelimit.h"
#include "los_schedlimit.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* proc limit set lock */
#define PLIMITS_MIN_PERIOD_IN_US 1000000
#define PLIMITS_MIN_QUOTA_IN_US 1
#define PLIMITS_DELETE_WAIT_TIME 1000
typedef struct ProcessCB LosProcessCB;
enum ProcLimiterID {
PROCESS_LIMITER_ID_PIDS = 0,
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
PROCESS_LIMITER_ID_MEM,
#endif
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
PROCESS_LIMITER_ID_SCHED,
#endif
#ifdef LOSCFG_KERNEL_DEV_PLIMIT
PROCESS_LIMITER_ID_DEV,
#endif
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
PROCESS_LIMITER_ID_IPC,
#endif
PROCESS_LIMITER_COUNT,
};
typedef struct {
#ifdef LOSCFG_KERNEL_MEM_PLIMIT
UINT64 memUsed;
#endif
#ifdef LOSCFG_KERNEL_IPC_PLIMIT
UINT32 mqCount;
UINT32 shmSize;
#endif
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
UINT64 allRuntime;
#endif
} PLimitsData;
typedef struct TagPLimiterSet {
struct TagPLimiterSet *parent; /* plimite parent */
LOS_DL_LIST childList; /* plimite childList */
LOS_DL_LIST processList;
UINT32 pidCount;
UINTPTR limitsList[PROCESS_LIMITER_COUNT]; /* plimite list */
UINT32 mask; /* each bit indicates that a limite exists */
UINT8 level; /* plimits hierarchy level */
} ProcLimiterSet;
typedef struct ProcessCB LosProcessCB;
ProcLimiterSet *OsRootPLimitsGet(VOID);
UINT32 OsPLimitsAddProcess(ProcLimiterSet *plimits, LosProcessCB *processCB);
UINT32 OsPLimitsAddPid(ProcLimiterSet *plimits, UINT32 pid);
VOID OsPLimitsDeleteProcess(LosProcessCB *processCB);
UINT32 OsPLimitsPidsGet(const ProcLimiterSet *plimits, UINT32 *pids, UINT32 size);
UINT32 OsPLimitsFree(ProcLimiterSet *currPLimits);
ProcLimiterSet *OsPLimitsCreate(ProcLimiterSet *parentProcLimiterSet);
UINT32 OsProcLimiterSetInit(VOID);
UINT32 OsPLimitsAddLimiters(ProcLimiterSet *procLimiterSet, enum ProcLimiterID plimiteID);
UINT32 OsPLimitsDeleteLimiters(ProcLimiterSet *procLimiterSet, enum ProcLimiterID plimiteID, UINT32 *mask);
UINT32 OsPLimitsMemUsageGet(ProcLimiterSet *plimits, UINT64 *usage, UINT32 size);
UINT32 OsPLimitsIPCStatGet(ProcLimiterSet *plimits, ProcIPCLimit *ipc, UINT32 size);
UINT32 OsPLimitsSchedUsageGet(ProcLimiterSet *plimits, UINT64 *usage, UINT32 size);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_PLIMITS_H */
/*
* Copyright (c) 2023-2023 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 "los_config.h"
#include "los_process_pri.h"
#include "los_process.h"
#include "los_plimits.h"
#include "los_task_pri.h"
#include "los_processlimit.h"
#ifdef LOSCFG_KERNEL_PLIMITS
STATIC PidLimit *g_rootPidLimit = NULL;
VOID PidLimiterInit(UINTPTR limit)
{
PidLimit *pidLimit = (PidLimit *)limit;
if (pidLimit == NULL) {
return;
}
pidLimit->pidLimit = LOS_GetSystemProcessMaximum();
pidLimit->priorityLimit = OS_USER_PROCESS_PRIORITY_HIGHEST;
g_rootPidLimit = pidLimit;
}
VOID *PidLimiterAlloc(VOID)
{
PidLimit *plimite = (PidLimit *)LOS_KernelMalloc(sizeof(PidLimit));
if (plimite == NULL) {
return NULL;
}
(VOID)memset_s(plimite, sizeof(PidLimit), 0, sizeof(PidLimit));
LOS_AtomicSet(&plimite->rc, 1);
return (VOID *)plimite;
}
VOID PidLimterFree(UINTPTR limit)
{
PidLimit *pidLimit = (PidLimit *)limit;
if (pidLimit == NULL) {
return;
}
LOS_AtomicDec(&pidLimit->rc);
if (LOS_AtomicRead(&pidLimit->rc) <= 0) {
LOS_KernelFree((VOID *)limit);
}
}
BOOL PidLimitMigrateCheck(UINTPTR curr, UINTPTR parent)
{
PidLimit *currPidLimit = (PidLimit *)curr;
PidLimit *parentPidLimit = (PidLimit *)parent;
if ((currPidLimit == NULL) || (parentPidLimit == NULL)) {
return FALSE;
}
if ((currPidLimit->pidCount + parentPidLimit->pidCount) >= parentPidLimit->pidLimit) {
return FALSE;
}
return TRUE;
}
VOID OsPidLimiterMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
{
(VOID)currLimit;
PidLimit *parentPidLimit = (PidLimit *)parentLimit;
LosProcessCB *pcb = (LosProcessCB *)process;
if (pcb == NULL) {
LOS_AtomicInc(&parentPidLimit->rc);
}
}
BOOL OsPidLimitAddProcessCheck(UINTPTR limit, UINTPTR process)
{
(VOID)process;
PidLimit *pidLimit = (PidLimit *)limit;
if (pidLimit->pidCount >= pidLimit->pidLimit) {
return FALSE;
}
return TRUE;
}
VOID OsPidLimitAddProcess(UINTPTR limit, UINTPTR process)
{
(VOID)process;
PidLimit *plimits = (PidLimit *)limit;
plimits->pidCount++;
return;
}
VOID OsPidLimitDelProcess(UINTPTR limit, UINTPTR process)
{
(VOID)process;
PidLimit *plimits = (PidLimit *)limit;
plimits->pidCount--;
return;
}
VOID PidLimiterCopy(UINTPTR curr, UINTPTR parent)
{
PidLimit *currPidLimit = (PidLimit *)curr;
PidLimit *parentPidLimit = (PidLimit *)parent;
if ((currPidLimit == NULL) || (parentPidLimit == NULL)) {
return;
}
currPidLimit->pidLimit = parentPidLimit->pidLimit;
currPidLimit->priorityLimit = parentPidLimit->priorityLimit;
currPidLimit->pidCount = 0;
return;
}
UINT32 PidLimitSetPidLimit(PidLimit *pidLimit, UINT32 pidMax)
{
UINT32 intSave;
if ((pidLimit == NULL) || (pidMax > LOS_GetSystemProcessMaximum())) {
return EINVAL;
}
if (pidLimit == g_rootPidLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
if (pidLimit->pidCount >= pidMax) {
SCHEDULER_UNLOCK(intSave);
return EPERM;
}
pidLimit->pidLimit = pidMax;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT32 PidLimitSetPriorityLimit(PidLimit *pidLimit, UINT32 priority)
{
UINT32 intSave;
if ((pidLimit == NULL) ||
(priority < OS_USER_PROCESS_PRIORITY_HIGHEST) ||
(priority > OS_PROCESS_PRIORITY_LOWEST)) {
return EINVAL;
}
if (pidLimit == g_rootPidLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
pidLimit->priorityLimit = priority;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT16 OsPidLimitGetPriorityLimit(VOID)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
LosProcessCB *run = OsCurrProcessGet();
PidLimit *pidLimit = (PidLimit *)run->plimits->limitsList[PROCESS_LIMITER_ID_PIDS];
UINT16 priority = pidLimit->priorityLimit;
SCHEDULER_UNLOCK(intSave);
return priority;
}
#endif
/*
* Copyright (c) 2023-2023 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.
*/
#ifndef _LOS_PROCESSLIMIT_H
#define _LOS_PROCESSLIMIT_H
#include "los_list.h"
#include "los_typedef.h"
#include "los_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
typedef struct PidLimit {
Atomic rc;
UINT32 pidLimit;
UINT32 priorityLimit;
UINT32 pidCount;
} PidLimit;
VOID PidLimiterInit(UINTPTR limit);
VOID *PidLimiterAlloc(VOID);
VOID PidLimterFree(UINTPTR limit);
VOID PidLimiterCopy(UINTPTR curr, UINTPTR parent);
BOOL PidLimitMigrateCheck(UINTPTR curr, UINTPTR parent);
VOID OsPidLimiterMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process);
BOOL OsPidLimitAddProcessCheck(UINTPTR limit, UINTPTR process);
VOID OsPidLimitAddProcess(UINTPTR limit, UINTPTR process);
VOID OsPidLimitDelProcess(UINTPTR limit, UINTPTR process);
UINT32 PidLimitSetPidLimit(PidLimit *pidLimit, UINT32 pidMax);
UINT32 PidLimitSetPriorityLimit(PidLimit *pidLimit, UINT32 priority);
UINT16 OsPidLimitGetPriorityLimit(VOID);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
/*
* Copyright (c) 2023-2023 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 "los_schedlimit.h"
#include "los_process_pri.h"
#ifdef LOSCFG_KERNEL_SCHED_PLIMIT
STATIC ProcSchedLimiter *g_procSchedLimit = NULL;
VOID OsSchedLimitInit(UINTPTR limit)
{
ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)limit;
schedLimit->period = 0;
schedLimit->quota = 0;
g_procSchedLimit = schedLimit;
}
VOID *OsSchedLimitAlloc(VOID)
{
ProcSchedLimiter *plimit = (ProcSchedLimiter *)LOS_KernelMalloc(sizeof(ProcSchedLimiter));
if (plimit == NULL) {
return NULL;
}
(VOID)memset_s(plimit, sizeof(ProcSchedLimiter), 0, sizeof(ProcSchedLimiter));
LOS_AtomicSet(&plimit->rc, 1);
return (VOID *)plimit;
}
VOID OsSchedLimitFree(UINTPTR limit)
{
ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)limit;
if (schedLimit == NULL) {
return;
}
LOS_AtomicDec(&schedLimit->rc);
if (LOS_AtomicRead(&schedLimit->rc) <= 0) {
LOS_KernelFree((VOID *)limit);
}
}
VOID OsSchedLimitCopy(UINTPTR dest, UINTPTR src)
{
ProcSchedLimiter *plimitDest = (ProcSchedLimiter *)dest;
ProcSchedLimiter *plimitSrc = (ProcSchedLimiter *)src;
plimitDest->period = plimitSrc->period;
plimitDest->quota = plimitSrc->quota;
return;
}
VOID OsSchedLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process)
{
(VOID)currLimit;
ProcSchedLimiter *parentSchedLimit = (ProcSchedLimiter *)parentLimit;
LosProcessCB *pcb = (LosProcessCB *)process;
if (pcb == NULL) {
LOS_AtomicInc(&parentSchedLimit->rc);
}
}
VOID OsSchedLimitUpdateRuntime(LosTaskCB *runTask, UINT64 currTime, INT32 incTime)
{
LosProcessCB *run = (LosProcessCB *)runTask->processCB;
if ((run == NULL) || (run->plimits == NULL)) {
return;
}
ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)run->plimits->limitsList[PROCESS_LIMITER_ID_SCHED];
run->limitStat.allRuntime += incTime;
if ((schedLimit->period <= 0) || (schedLimit->quota <= 0)) {
return;
}
if ((schedLimit->startTime <= currTime) && (schedLimit->allRuntime < schedLimit->quota)) {
schedLimit->allRuntime += incTime;
return;
}
if (schedLimit->startTime <= currTime) {
schedLimit->startTime = currTime + schedLimit->period;
schedLimit->allRuntime = 0;
}
}
BOOL OsSchedLimitCheckTime(LosTaskCB *task)
{
UINT64 currTime = OsGetCurrSchedTimeCycle();
LosProcessCB *processCB = (LosProcessCB *)task->processCB;
if ((processCB == NULL) || (processCB->plimits == NULL)) {
return TRUE;
}
ProcSchedLimiter *schedLimit = (ProcSchedLimiter *)processCB->plimits->limitsList[PROCESS_LIMITER_ID_SCHED];
if (schedLimit->startTime >= currTime) {
return FALSE;
}
return TRUE;
}
UINT32 OsSchedLimitSetPeriod(ProcSchedLimiter *schedLimit, UINT64 value)
{
UINT32 intSave;
if (schedLimit == NULL) {
return EINVAL;
}
if (schedLimit == g_procSchedLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
schedLimit->period = value;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
UINT32 OsSchedLimitSetQuota(ProcSchedLimiter *schedLimit, UINT64 value)
{
UINT32 intSave;
if (schedLimit == NULL) {
return EINVAL;
}
if (schedLimit == g_procSchedLimit) {
return EPERM;
}
SCHEDULER_LOCK(intSave);
if (value > (UINT64)schedLimit->period) {
SCHEDULER_UNLOCK(intSave);
return EINVAL;
}
schedLimit->quota = value;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;
}
#endif
/*
* 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.
*/
#ifndef _LOS_SCHEDLIMIT_H
#define _LOS_SCHEDLIMIT_H
#include "los_typedef.h"
#include "los_atomic.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define CORE_US_PER_SECOND (1000 * 1000) /* 1000 * 1000 us per second */
typedef struct TagTaskCB LosTaskCB;
typedef struct ProcSchedLimiter {
Atomic rc;
UINT64 startTime;
UINT64 endTime;
UINT64 period;
UINT64 quota;
UINT64 allRuntime;
UINT64 overrunTime;
UINT64 stat;
} ProcSchedLimiter;
VOID OsSchedLimitInit(UINTPTR limit);
VOID *OsSchedLimitAlloc(VOID);
VOID OsSchedLimitFree(UINTPTR limit);
VOID OsSchedLimitCopy(UINTPTR dest, UINTPTR src);
VOID OsSchedLimitMigrate(UINTPTR currLimit, UINTPTR parentLimit, UINTPTR process);
VOID OsSchedLimitUpdateRuntime(LosTaskCB *runTask, UINT64 currTime, INT32 incTime);
UINT32 OsSchedLimitSetPeriod(ProcSchedLimiter *schedLimit, UINT64 value);
UINT32 OsSchedLimitSetQuota(ProcSchedLimiter *schedLimit, UINT64 value);
BOOL OsSchedLimitCheckTime(LosTaskCB *task);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* _LOS_SCHEDLIMIT_H */
......@@ -156,6 +156,12 @@ int SysSchedSetScheduler(int id, int policy, int prio, int flag)
id = (int)LOS_GetCurrProcessID();
}
#ifdef LOSCFG_KERNEL_PLIMITS
if (prio < OsPidLimitGetPriorityLimit()) {
return -EINVAL;
}
#endif
ret = OsPermissionToCheck(id, LOS_GetCurrProcessID());
if (ret < 0) {
return ret;
......@@ -210,6 +216,12 @@ int SysSetProcessPriority(int which, int who, unsigned int prio)
who = (int)LOS_GetCurrProcessID();
}
#ifdef LOSCFG_KERNEL_PLIMITS
if (prio < OsPidLimitGetPriorityLimit()) {
return -EINVAL;
}
#endif
ret = OsPermissionToCheck(who, LOS_GetCurrProcessID());
if (ret < 0) {
return ret;
......@@ -224,6 +236,12 @@ int SysSchedSetParam(int id, unsigned int prio, int flag)
return -OsUserTaskSchedulerSet(id, LOS_SCHED_RR, prio, false);
}
#ifdef LOSCFG_KERNEL_PLIMITS
if (prio < OsPidLimitGetPriorityLimit()) {
return -EINVAL;
}
#endif
return SysSetProcessPriority(LOS_PRIO_PROCESS, id, prio);
}
......
......@@ -194,6 +194,13 @@ ifeq ($(LOSCFG_KERNEL_SYSCALL), y)
LITEOS_BASELIB += -lsyscall
LIB_SUBDIRS += syscall
endif
ifeq ($(LOSCFG_KERNEL_PLIMITS), y)
LITEOS_BASELIB += -lplimit
LIB_SUBDIRS += kernel/extended/plimit
LITEOS_PLIMITS_INCLUDE = -I $(LITEOSTOPDIR)/kernel/extended/plimit
endif
LIB_SUBDIRS += kernel/user
################################### Kernel Option End ################################
......@@ -517,7 +524,7 @@ LITEOS_EXTKERNEL_INCLUDE := $(LITEOS_CPPSUPPORT_INCLUDE) $(LITEOS_DYNLOAD_INCL
$(LITEOS_VDSO_INCLUDE) $(LITEOS_LITEIPC_INCLUDE) \
$(LITEOS_PIPE_INCLUDE) $(LITEOS_CPUP_INCLUDE) \
$(LITEOS_PERF_INCLUDE) $(LITEOS_LMS_INCLUDE) \
$(LITEOS_PM_INCLUDE)
$(LITEOS_PM_INCLUDE) $(LITEOS_PLIMITS_INCLUDE)
LITEOS_COMPAT_INCLUDE := $(LITEOS_POSIX_INCLUDE) $(LITEOS_LINUX_INCLUDE) \
$(LITEOS_BSD_INCLUDE)
LITEOS_FS_INCLUDE := $(LITEOS_VFS_INCLUDE) $(LITEOS_FAT_CACHE_INCLUDE) \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册