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

!281 Add 支持在配置文件中配置服务进程的绑核

Merge pull request !281 from 熊磊/01288
......@@ -78,6 +78,11 @@ typedef enum {
END_RECV_READY,
} ServiceEndMode;
typedef struct {
int *cpus;
int cpuNum;
} CpuArgs;
typedef struct {
uid_t uID;
gid_t *gIDArray;
......@@ -130,6 +135,7 @@ typedef struct Service_ {
int *fds;
size_t fdCount;
ServiceJobs serviceJobs;
CpuArgs cpuInfo;
} Service;
int ServiceStart(Service *service);
......
......@@ -35,6 +35,7 @@ extern "C" {
#define CONSOLE_STR_IN_CFG "console"
#define D_CAPS_STR_IN_CFG "d-caps"
#define APL_STR_IN_CFG "apl"
#define CPU_CORE_STR_IN_CFG "cpucore"
#define MAX_SERVICES_CNT_IN_FILE 100
......
......@@ -18,6 +18,8 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <stdio.h>
#ifdef __MUSL__
#include <stropts.h>
#endif
......@@ -225,6 +227,41 @@ static void PublishHoldFds(Service *service)
}
}
static int SetAffinityBetweenProcAndCore(pid_t pid, int cpuIndex)
{
cpu_set_t setMask;
CPU_ZERO(&setMask);
CPU_SET(cpuIndex, &setMask);
int ret = sched_setaffinity(pid, sizeof(cpu_set_t), &setMask);
if (ret != 0) {
INIT_LOGI("Set affinity between process(pid=%d) with CPU's core %d failed", pid, cpuIndex);
return SERVICE_FAILURE;
} else {
INIT_LOGE("Set affinity between process(pid=%d) with CPU's core %d successfully", pid, cpuIndex);
}
return SERVICE_SUCCESS;
}
static int BindCpuCore(Service *service)
{
if (service == NULL || service->cpuInfo.cpuNum <= 0) {
return SERVICE_SUCCESS;
}
long cpuNum = sysconf(_SC_NPROCESSORS_CONF);
INIT_ERROR_CHECK(service->cpuInfo.cpuNum <= cpuNum, return SERVICE_FAILURE,
"%s cpus cores exceeds total number of device cores", service->name);
int index = 0;
for (int i = 0; i < service->cpuInfo.cpuNum; i++) {
index = (int)service->cpuInfo.cpus[i];
if ((int)cpuNum <= index) {
INIT_LOGW("%s core number %d of CPU cores does not exist", service->name, index);
continue;
}
(void)SetAffinityBetweenProcAndCore(getpid(), index);
}
return SERVICE_SUCCESS;
}
int ServiceStart(Service *service)
{
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr.");
......@@ -263,6 +300,8 @@ int ServiceStart(Service *service)
OpenConsole();
}
PublishHoldFds(service);
INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS,
"binding core number failed for service %s", service->name);
// permissions
INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(PROCESS_EXIT_CODE),
"service %s exit! set perms failed! err %d.", service->name, errno);
......
......@@ -170,6 +170,11 @@ void ReleaseService(Service *service)
FreeServiceArg(&service->writePidArgs);
FreeServiceArg(&service->capsArgs);
if (service->cpuInfo.cpus != NULL) {
free(service->cpuInfo.cpus);
service->cpuInfo.cpus = NULL;
}
service->cpuInfo.cpuNum = 0;
if (service->servPerm.caps != NULL) {
free(service->servPerm.caps);
service->servPerm.caps = NULL;
......@@ -602,7 +607,7 @@ static int CheckServiceKeyName(const cJSON *curService)
char *cfgServiceKeyList[] = {
"name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
"writepid", "critical", "socket", "console", "dynamic", "file", "ondemand",
"d-caps", "apl", "jobs", "start-mode", "end-mode",
"d-caps", "apl", "jobs", "start-mode", "end-mode", "cpucore",
#ifdef WITH_SELINUX
SECON_STR_IN_CFG,
#endif // WITH_SELINUX
......@@ -723,6 +728,49 @@ int GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName
return SERVICE_SUCCESS;
}
static int Comparefunc(const void *before, const void *after)
{
return (*(int*)before - *(int*)after);
}
static int GetCpuArgs(const cJSON *argJson, const char *name, CpuArgs *args)
{
INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
cJSON *obj = cJSON_GetObjectItem(argJson, name);
INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
int ret = cJSON_IsArray(obj);
INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
int count = cJSON_GetArraySize(obj);
int tmpArray[count];
for (int i = 0; i < count; ++i) {
cJSON *item = cJSON_GetArrayItem(obj, i);
INIT_ERROR_CHECK(item != NULL, return SERVICE_FAILURE, "prase invalid");
tmpArray[i] = (int)cJSON_GetNumberValue(item);
}
qsort(tmpArray, count, sizeof(int), Comparefunc);
int cpuCount = 0;
for (int j = 0; j < count; j++) {
if (j == 0 && tmpArray[0] == 0) {
tmpArray[cpuCount++] = 0;
continue;
}
if (tmpArray[j] != tmpArray[j-1]) {
tmpArray[cpuCount++] = tmpArray[j];
}
}
args->cpus=(int*)malloc(cpuCount * sizeof(int));
INIT_ERROR_CHECK(args->cpus != NULL, return SERVICE_FAILURE, "Failed to malloc for argv");
for (int i = 0; i < cpuCount; ++i) {
args->cpus[i] = -1;
}
args->cpuNum = cpuCount;
for (int i = 0; i < count; ++i) {
args->cpus[i] = tmpArray[i];
}
return SERVICE_SUCCESS;
}
int ParseOneService(const cJSON *curItem, Service *service)
{
INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE);
......@@ -756,6 +804,7 @@ int ParseOneService(const cJSON *curItem, Service *service)
(void)GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs);
(void)GetServiceArgs(curItem, D_CAPS_STR_IN_CFG, MAX_WRITEPID_FILES, &service->capsArgs);
(void)GetStringItem(curItem, APL_STR_IN_CFG, service->apl, MAX_APL_NAME);
(void)GetCpuArgs(curItem, CPU_CORE_STR_IN_CFG, &service->cpuInfo);
ret = GetServiceCaps(curItem, service);
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
ret = GetDynamicService(curItem, service);
......
......@@ -183,6 +183,7 @@ ohos_unittest("init_ut") {
"STARTUP_INIT_TEST",
"PARAM_SUPPORT_SAVE_PERSIST",
"PARAM_SUPPORT_DAC",
"_GNU_SOURCE",
]
defines += [ "_GNU_SOURCE" ]
......
......@@ -25,6 +25,7 @@ if (defined(ohos_lite)) {
defines = [
"OHOS_LITE",
"__MUSL__",
"_GNU_SOURCE",
]
if (storage_type == "emmc") {
defines += [ "USE_EMMC_STORAGE" ]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册