vcpe/srcs/libs/hardware/memory.c

180 lines
4.9 KiB
C
Raw Normal View History

2022-05-10 06:43:27 +00:00
//
// Created by xajhu on 2021/7/6 0006.
//
#include <stdlib.h>
#include <uv.h>
#include <string.h>
#include <sds.h>
#include "hardware.h"
#include "task_manager.h"
#include "user_errno.h"
#include "uthash/uthash.h"
#include "misc.h"
#include "config.h"
#define CMD_MEMORY_INFO ("cat /proc/meminfo | awk \'{print $1\"|\"$2\"|\"$3}\'")
#define M_SIZE (1024 * 1024)
#define KEY_NAME (32)
#define KEY_VALUE (32)
#define VALUE_UNIT (8)
typedef struct {
char itemName[KEY_NAME];
char itemValue[KEY_VALUE];
char valUnit[VALUE_UNIT];
unsigned long timestamp;
UT_hash_handle hh;
} KERNEL_MEM_INFO, *PKERNEL_MEM_INFO;
static uv_rwlock_t g_uvLock;
static PKERNEL_MEM_INFO g_pMemInfo = NULL;
static const char *g_memKeyName[] = {"MemTotal", "MemFree", "MemAvailable", "Buffers", "Cached"};
unsigned int get_sys_free_memory() {
return uv_get_free_memory() / M_SIZE;
}
unsigned int get_sys_total_memory() {
return uv_get_total_memory() / M_SIZE;
}
static int memory_info_refresh() {
int errCode = ERR_SUCCESS;
2022-05-10 06:43:27 +00:00
FILE *fp;
char buf[MAX_PATH];
fp = popen(CMD_MEMORY_INFO, "r");
if (fp == NULL) {
return -ERR_OPEN_FILE;
}
while (fgets(buf, 1024, fp) != NULL) {
int nItems;
sds tmpStr = sdsnew(buf);
sds *pToken = sdssplitlen(tmpStr, (int)sdslen(tmpStr), "|", 1, &nItems);
if (nItems == 3) {
PKERNEL_MEM_INFO pTmp = NULL;
HASH_FIND_STR(g_pMemInfo, pToken[0], pTmp);
if (pTmp) {
uv_rwlock_wrlock(&g_uvLock);
strcpy(pTmp->itemName, sdstrim(pToken[0], ": \n"));
strcpy(pTmp->itemValue, sdstrim(pToken[1], " \n"));
strcpy(pTmp->valUnit, sdstrim(pToken[2], " \n"));
pTmp->timestamp = time(NULL);
uv_rwlock_wrunlock(&g_uvLock);
} else {
pTmp = (PKERNEL_MEM_INFO)malloc(sizeof(KERNEL_MEM_INFO));
if (pTmp) {
uv_rwlock_wrlock(&g_uvLock);
strcpy(pTmp->itemName, sdstrim(pToken[0], ": \n"));
strcpy(pTmp->itemValue, sdstrim(pToken[1], " \n"));
strcpy(pTmp->valUnit, sdstrim(pToken[2], " \n"));
pTmp->timestamp = time(NULL);
HASH_ADD_STR(g_pMemInfo, itemName, pTmp);
uv_rwlock_wrunlock(&g_uvLock);
} else {
errCode = -ERR_MALLOC_MEMORY;
}
}
}
sdsfreesplitres(pToken, nItems);
sdsfree(tmpStr);
}
return errCode;
}
_Noreturn void memRefreshCb(void *UNUSED(pArg)) {
do {
unsigned int period = cfg_get_mem_refresh_period();
if (cfg_get_watch_memory()) {
memory_info_refresh();
}
if (period < REFRESH_MAX_PERIOD && period >= 1) {
uv_sleep(1000 * period);
} else {
uv_sleep(1000);
}
} while (TRUE);
}
int memory_watch_init() {
static uv_thread_t uvThread;
uv_rwlock_init(&g_uvLock);
if (memory_info_refresh() != ERR_SUCCESS) {
2022-05-10 06:43:27 +00:00
return -ERR_SYS_DISK_GET_INFO;
}
uv_thread_create(&uvThread, memRefreshCb, NULL);
return ERR_SUCCESS;
2022-05-10 06:43:27 +00:00
}
#define MEM_VALUE_SET(dst, src) \
do { \
if ((src) == NULL) \
continue; \
if ((src)->valUnit && strlen((src)->valUnit) > 0) { \
sprintf(dst, "%s %s", (src)->itemValue, (src)->valUnit); \
} else { \
sprintf(dst, "%s", (src)->itemValue); \
} \
} while (0)
int get_memory_info(PMEMORY_INFO pInfo) {
int i, n = ARRAY_SIZE(g_memKeyName);
if (pInfo == NULL) {
return -ERR_INPUT_PARAMS;
}
uv_rwlock_rdlock(&g_uvLock);
for (i = 0; i < n; i++) {
PKERNEL_MEM_INFO pTmp = NULL;
HASH_FIND_STR(g_pMemInfo, g_memKeyName[i], pTmp);
if (pTmp) {
switch (i) {
case 0:
MEM_VALUE_SET(pInfo->totalMemSize, pTmp);
break;
case 1:
MEM_VALUE_SET(pInfo->freeMemSize, pTmp);
break;
case 2:
MEM_VALUE_SET(pInfo->availMemSize, pTmp);
break;
case 3:
MEM_VALUE_SET(pInfo->bufferMemSize, pTmp);
break;
case 4:
MEM_VALUE_SET(pInfo->cachedMemSize, pTmp);
break;
default:
continue;
}
}
}
uv_rwlock_rdunlock(&g_uvLock);
pInfo->timestamp = time(NULL);
return ERR_SUCCESS;
2022-05-10 06:43:27 +00:00
}