xref: /drivers/hdf_core/adapter/uhdf2/host/devhost.c (revision c1d0c72a)
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <errno.h>
17#include <limits.h>
18#include <sched.h>
19#include <signal.h>
20#include <stdlib.h>
21#include <sys/prctl.h>
22#include <sys/resource.h>
23#include <unistd.h>
24
25#include "securec.h"
26#include "parameter.h"
27#include "malloc.h"
28#include "devhost_dump.h"
29#include "devhost_service.h"
30#include "devhost_service_full.h"
31#include "hdf_base.h"
32#include "hdf_core_log.h"
33#include "hdf_power_manager.h"
34
35#define HDF_LOG_TAG                    hdf_device_host
36#define DEVHOST_MIN_INPUT_PARAM_NUM    5
37#define DEVHOST_INPUT_PARAM_HOSTID_POS 1
38#define DEVHOST_HOST_NAME_POS          2
39#define DEVHOST_PROCESS_PRI_POS        3
40#define DEVHOST_THREAD_PRI_POS         4
41#define PARAM_BUF_LEN 128
42#define MALLOPT_PARA_CNT 2
43#define INVALID_PRIORITY "0"
44
45static void StartMemoryHook(const char* processName)
46{
47    const char defaultValue[PARAM_BUF_LEN] = { 0 };
48    const char targetPrefix[] = "startup:";
49    const int targetPrefixLen = strlen(targetPrefix);
50    char paramValue[PARAM_BUF_LEN] = { 0 };
51    int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
52    if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
53        return;
54    }
55    if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
56        const int hookSignal = 36; // 36: native memory hooked signal
57        HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
58        raise(hookSignal);
59    }
60}
61
62bool HdfStringToInt(const char *str, int *value)
63{
64    if (str == NULL || value == NULL) {
65        return false;
66    }
67
68    char *end = NULL;
69    errno = 0;
70    const int base = 10;
71    long result = strtol(str, &end, base);
72    if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
73        return false;
74    }
75
76    *value = (int)result;
77    return true;
78}
79
80static void SetProcTitle(char **argv, const char *newTitle)
81{
82    size_t len = strlen(argv[0]);
83    if (strlen(newTitle) > len) {
84        HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle);
85        return;
86    }
87    (void)memset_s(argv[0], len, 0, len);
88    if (strcpy_s(argv[0], len + 1, newTitle) != EOK) {
89        HDF_LOGE("failed to set new process title");
90        return;
91    }
92    prctl(PR_SET_NAME, newTitle);
93}
94
95static void HdfSetProcPriority(char **argv)
96{
97    int32_t schedPriority = 0;
98    int32_t procPriority = 0;
99
100    if (!HdfStringToInt(argv[DEVHOST_PROCESS_PRI_POS], &procPriority)) {
101        HDF_LOGE("procPriority parameter error: %{public}s", argv[DEVHOST_PROCESS_PRI_POS]);
102        return;
103    }
104    if (!HdfStringToInt(argv[DEVHOST_THREAD_PRI_POS], &schedPriority)) {
105        HDF_LOGE("schedPriority parameter error: %{public}s", argv[DEVHOST_THREAD_PRI_POS]);
106        return;
107    }
108
109    if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) {
110        HDF_LOGE("host setpriority failed: %{public}d", errno);
111    }
112
113    struct sched_param param = {0};
114    param.sched_priority = schedPriority;
115    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
116        HDF_LOGE("host sched_setscheduler failed: %{public}d", errno);
117    } else {
118        HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority);
119    }
120}
121
122static void SetMallopt(int argc, char **argv)
123{
124    for (int i = DEVHOST_MIN_INPUT_PARAM_NUM; i < argc - 1; i += MALLOPT_PARA_CNT) {
125        int32_t malloptKey = 0;
126        int32_t malloptValue = 0;
127        int ret = 0;
128        if (!HdfStringToInt(argv[i], &malloptKey)) {
129            HDF_LOGE("malloptKey parameter error:%{public}s", argv[i]);
130            continue;
131        }
132        if (!HdfStringToInt(argv[i + 1], &malloptValue)) {
133            HDF_LOGE("malloptValue parameter error:%{public}s", argv[i + 1]);
134            continue;
135        }
136        ret = mallopt(malloptKey, malloptValue);
137        if (ret != 1) {
138            HDF_LOGE("mallopt failed, malloptKey:%{public}d, malloptValue:%{public}d, ret:%{public}d",
139                malloptKey, malloptValue, ret);
140            continue;
141        }
142        HDF_LOGI("host set mallopt succeed, mallopt:%{public}d %{public}d", malloptKey, malloptValue);
143    }
144    return;
145}
146
147static void SetHostProperties(int argc, char **argv, const char *hostName)
148{
149    SetProcTitle(argv, hostName);
150    StartMemoryHook(hostName);
151    if ((strcmp(argv[DEVHOST_PROCESS_PRI_POS], INVALID_PRIORITY) != 0) &&
152        (strcmp(argv[DEVHOST_THREAD_PRI_POS], INVALID_PRIORITY) != 0)) {
153        HdfSetProcPriority(argv);
154    }
155    if (argc > DEVHOST_MIN_INPUT_PARAM_NUM) {
156        SetMallopt(argc, argv);
157    }
158}
159
160int main(int argc, char **argv)
161{
162    if (argc < DEVHOST_MIN_INPUT_PARAM_NUM) {
163        HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
164        return HDF_ERR_INVALID_PARAM;
165    }
166    prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
167    int hostId = 0;
168    if (!HdfStringToInt(argv[DEVHOST_INPUT_PARAM_HOSTID_POS], &hostId)) {
169        HDF_LOGE("Devhost main parameter error, argv[1]: %{public}s", argv[DEVHOST_INPUT_PARAM_HOSTID_POS]);
170        return HDF_ERR_INVALID_PARAM;
171    }
172    const char *hostName = argv[DEVHOST_HOST_NAME_POS];
173    HDF_LOGI("hdf device host %{public}s %{public}d start", hostName, hostId);
174    SetHostProperties(argc, argv, hostName);
175    struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName);
176    if (instance == NULL || instance->StartService == NULL) {
177        HDF_LOGE("DevHostServiceGetInstance fail");
178        return HDF_ERR_INVALID_OBJECT;
179    }
180    HDF_LOGD("create IDevHostService of %{public}s success", hostName);
181    DevHostDumpInit();
182    HDF_LOGD("%{public}s start device service begin", hostName);
183    int status = instance->StartService(instance);
184    if (status != HDF_SUCCESS) {
185        HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
186        DevHostServiceFreeInstance(instance);
187        DevHostDumpDeInit();
188        return status;
189    }
190    HdfPowerManagerInit();
191    struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
192    struct HdfMessageLooper *looper = &fullService->looper;
193    if ((looper != NULL) && (looper->Start != NULL)) {
194        HDF_LOGI("%{public}s start loop", hostName);
195        looper->Start(looper);
196    }
197    HdfPowerManagerExit();
198    DevHostDumpDeInit();
199    HDF_LOGI("hdf device host %{public}s %{public}d %{public}d exit", hostName, hostId, status);
200    if (strcmp(hostName, "camera_host") == 0) {
201        _exit(status);
202    }
203    return status;
204}
205