Files
phs_v1.0.1.0/test/xts/acts/kernel_lite/utils/utils.cpp
2024-09-27 19:21:56 +08:00

292 lines
8.2 KiB
C++

/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "utils.h"
#include <gtest/gtest.h>
#include "log.h"
// init rand seed at startup
__attribute__((constructor)) static void Initialize(void)
{
LOGD("srand(time(0)) is called.");
srand(time(nullptr));
}
int CheckValueClose(double target, double actual, double accuracy)
{
double diff = actual - target;
double pct;
if (diff < 0) {
diff = -diff;
}
if(actual == 0) {
return 0;
}else {
pct = diff / actual;
}
LOGD("diff=%f, pct=%f\n", diff, pct);
return (pct <= accuracy);
}
const int SYS_US_PER_MS = 1000;
void Msleep(int msec)
{
usleep(msec * SYS_US_PER_MS);
}
int KeepRun(int msec)
{
struct timespec time1 = { 0, 0 };
struct timespec time2 = { 0, 0 };
clock_gettime(CLOCK_MONOTONIC, &time1);
LOGD("KeepRun start : tv_sec=%ld, tv_nsec=%ld\n", time1.tv_sec, time1.tv_nsec);
int loop = 0;
int runned = 0;
while (runned < msec) {
++loop;
clock_gettime(CLOCK_MONOTONIC, &time2);
runned = (time2.tv_sec - time1.tv_sec) * 1000 + (time2.tv_nsec - time1.tv_nsec) / 1000000;
}
LOGD("KeepRun end : tv_sec=%ld, tv_nsec=%ld\n", time2.tv_sec, time2.tv_nsec);
return loop;
}
// check process state use 'waitpid'
int CheckProcStatus(pid_t pid, int *code, int flag)
{
int status;
int rt = waitpid(pid, &status, flag);
errno = 0;
if (rt == -1) {
LOGE("waitpid return -1, errno=%d:%s\n", errno, strerror(errno));
return -1;
} else if (rt == 0) {
return 0;
} else if (rt != pid) { // waitpid return error
if (errno) {
LOGE("waitpid return error, rt=%d, errno=%d:%s\n", rt, errno, strerror(errno));
} else {
LOGE("waitpid return error, errno is not set(no more info)\n");
}
return -2;
}
if (code == nullptr) {
return -1;
}
if (WIFEXITED(status)) {
*code = WEXITSTATUS(status);
return 1;
} else if (WIFSIGNALED(status)) {
*code = WTERMSIG(status);
return 2;
} else if (WIFSTOPPED(status)) {
*code = WSTOPSIG(status);
return 3;
}
return 4;
}
// start an elf, only check if execve success or not
static int StartElf(const char *fname, char * const argv[], char * const envp[])
{
int pid = fork();
if (pid == -1) {
LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
return -1;
} else if (pid == 0) { // child
errno = 0;
int rt = execve(fname, argv, envp);
if (rt == -1) {
LOGE("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
exit(EXECVE_RETURN_ERROR);
}
LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
exit(EXECVE_RETURN_OK);
}
return pid;
}
int RunElf(const char *fname, char * const argv[], char * const envp[], int timeoutSec)
{
int isTimeout = 0;
int exitCode;
sigset_t set, orig_mask;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &set, &orig_mask) < 0) {
LOG("sigprocmask");
}
int pid = StartElf(fname, argv, envp);
if (pid == -1) { // fork error
return -1;
}
if (timeoutSec > 0) {
struct timespec time1 = { timeoutSec, 0 };
if (sigtimedwait(&set, nullptr, &time1) == -1) {
if (errno == EAGAIN) {
isTimeout = 1;
} else {
LOGE("ERROR: sigtimedwait FAIL: %s\n", strerror(errno));
return -1;
}
if (kill(pid, SIGKILL) == -1) {
LOGE("ERROR: kill child FAIL: %s\n", strerror(errno));
return -1;
}
}
// else: sigtimedwait return ok, child has exited already, nothing else to do
}
int rt = CheckProcStatus(pid, &exitCode, 0);
if ((rt <= 0) || (exitCode == EXECVE_RETURN_OK) || (exitCode == EXECVE_RETURN_ERROR)) {
return -1;
}
if (isTimeout) {
LOGE("ERROR: child execute timed out!\n");
return -2;
}
return exitCode;
}
int StartExecveError(const char *fname, char * const argv[], char * const envp[])
{
pid_t pid = fork();
if (pid == -1) {
LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
return -1;
} else if (pid == 0) { // child
int rt = execve(fname, argv, envp);
if (rt == -1) {
LOG("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
exit(errno);
}
LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
exit(EXECVE_RETURN_OK);
}
// parent
Msleep(30);
int exitCode;
int procStat = CheckProcStatus(pid, &exitCode);
LOG("procStat=%d, exitCode=%d\n", procStat, exitCode);
if (procStat != 1) {
return -3;
} else if (exitCode == EXECVE_RETURN_OK) {
return -2;
} else {
return exitCode;
}
}
// Get a pid number that currently not exist
// by creat a child process and exit.
pid_t GetNonExistPid()
{
pid_t pid = fork();
if (pid < 0) {
LOG("fork error, wait 5 seconds than try angain...");
sleep(5);
pid = fork();
if (pid < 0) {
LOG("still fork error!");
return -1;
}
}
if (pid > 0) { // parent
Msleep(20);
if (waitpid(pid, nullptr, 0) != pid) {
LOG("waitpid failed, errno = %d", errno);
return -1;
}
} else { // child
exit(0);
}
return pid;
}
// return n: 0 < n <= max
uint32_t GetRandom(uint32_t max)
{
if (max == 0 || max == 1) {
return 1;
}
return (rand() % max) + 1;
}
// get cur-time plus ms
void GetDelayedTime(struct timespec *ts, unsigned int ms)
{
const unsigned int nsecPerSec = 1000000000;
unsigned int setTimeNs = ms * 1000000;
struct timespec tsNow = { 0 };
clock_gettime(CLOCK_REALTIME, &tsNow);
ts->tv_sec = tsNow.tv_sec + (tsNow.tv_nsec + setTimeNs) / nsecPerSec;
ts->tv_nsec = (tsNow.tv_nsec + setTimeNs) % nsecPerSec;
}
// calculate time difference, in ms
int GetTimeDiff(struct timespec ts1, struct timespec ts2)
{
const unsigned int nsecPerSec = 1000000000;
int ms = (ts1.tv_sec - ts2.tv_sec) * nsecPerSec + (ts1.tv_nsec - ts2.tv_nsec);
ms = ms / 1000000;
return ms;
}
int GetCpuCount(void)
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
int temp = sched_getaffinity(getpid(), sizeof(cpu_set_t), &cpuset);
if (temp != 0) {
printf("%s %d Error : %d\n", __FUNCTION__, __LINE__, temp);
}
return CPU_COUNT(&cpuset);
}
int FixCurProcessToOneCpu(int cpuIndex, cpu_set_t *pOldMask)
{
int ret;
cpu_set_t setMask;
CPU_ZERO(pOldMask);
ret = sched_getaffinity(0, sizeof(cpu_set_t), pOldMask);
if (ret != 0) {
LOG("sched_getaffinity failed, ret = %d", ret);
return -1;
}
if (CPU_ISSET(0, pOldMask)) {
LOG("before affinity cpu is 0");
}
if (CPU_ISSET(1, pOldMask)) {
LOG("before affinity cpu is 1");
}
CPU_ZERO(&setMask);
CPU_SET(cpuIndex, &setMask);
LOG("fix cpu to %d", cpuIndex);
ret = sched_setaffinity(0, sizeof(setMask), &setMask);
if (ret != 0) {
LOG("sched_setaffinity failed, ret = %d", ret);
return -1;
}
return 0;
}