106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include <cstdio>
1706f6ba60Sopenharmony_ci#include <cstring>
1806f6ba60Sopenharmony_ci#include <unistd.h>
1906f6ba60Sopenharmony_ci#include <cstdlib>
2006f6ba60Sopenharmony_ci#include <pthread.h>
2106f6ba60Sopenharmony_ci#include <vector>
2206f6ba60Sopenharmony_ci#include <ctime>
2306f6ba60Sopenharmony_ci#include <csignal>
2406f6ba60Sopenharmony_ci#include <atomic>
2506f6ba60Sopenharmony_ci#include <memory>
2606f6ba60Sopenharmony_ci
2706f6ba60Sopenharmony_cinamespace {
2806f6ba60Sopenharmony_cistatic int g_duration;
2906f6ba60Sopenharmony_cistatic int g_memSize;
3006f6ba60Sopenharmony_cistatic std::atomic<long long> g_times;
3106f6ba60Sopenharmony_cistatic std::atomic<long long> g_mallocTotalTime;
3206f6ba60Sopenharmony_cistatic std::atomic<long long> g_freeTotalTime;
3306f6ba60Sopenharmony_cistatic constexpr int N_INSTALL_MALLOC_HOOK_SIGNAL = 36;
3406f6ba60Sopenharmony_cistatic constexpr int DURATION_TIME = 30 * 60;
3506f6ba60Sopenharmony_cistatic constexpr int MEMORY_BUFFER_SIZE = 19;
3606f6ba60Sopenharmony_ci
3706f6ba60Sopenharmony_civoid* UserThread(void* param)
3806f6ba60Sopenharmony_ci{
3906f6ba60Sopenharmony_ci    int idx = *static_cast<int*>(param);
4006f6ba60Sopenharmony_ci    struct timespec beginTime;
4106f6ba60Sopenharmony_ci    struct timespec endTime;
4206f6ba60Sopenharmony_ci    struct timespec beginTimeMalloc;
4306f6ba60Sopenharmony_ci    struct timespec endTimeMalloc;
4406f6ba60Sopenharmony_ci    struct timespec beginTimeFree;
4506f6ba60Sopenharmony_ci    struct timespec endTimeFree;
4606f6ba60Sopenharmony_ci
4706f6ba60Sopenharmony_ci    clock_gettime(CLOCK_REALTIME, &beginTime);
4806f6ba60Sopenharmony_ci    int displaySize = g_memSize > 5 ? 5 : g_memSize;
4906f6ba60Sopenharmony_ci    do {
5006f6ba60Sopenharmony_ci        clock_gettime(CLOCK_REALTIME, &endTime);
5106f6ba60Sopenharmony_ci        if (endTime.tv_sec - beginTime.tv_sec >= g_duration) {
5206f6ba60Sopenharmony_ci            break;
5306f6ba60Sopenharmony_ci        }
5406f6ba60Sopenharmony_ci        clock_gettime(CLOCK_REALTIME, &beginTimeMalloc);
5506f6ba60Sopenharmony_ci        char* mem = static_cast<char *>(malloc(g_memSize));
5606f6ba60Sopenharmony_ci        if (mem == nullptr) {
5706f6ba60Sopenharmony_ci            printf("Error: malloc mem memory failed.\n");
5806f6ba60Sopenharmony_ci            return nullptr;
5906f6ba60Sopenharmony_ci        }
6006f6ba60Sopenharmony_ci        clock_gettime(CLOCK_REALTIME, &endTimeMalloc);
6106f6ba60Sopenharmony_ci        std::atomic_fetch_add_explicit(
6206f6ba60Sopenharmony_ci            &g_mallocTotalTime,
6306f6ba60Sopenharmony_ci            static_cast<long long>((endTimeMalloc.tv_sec - beginTimeMalloc.tv_sec) * 1000000000L +
6406f6ba60Sopenharmony_ci                                   (endTimeMalloc.tv_nsec - beginTimeMalloc.tv_nsec)),
6506f6ba60Sopenharmony_ci            std::memory_order_relaxed);
6606f6ba60Sopenharmony_ci        long long currentTimes = ++g_times;
6706f6ba60Sopenharmony_ci        long long timeBase = 10000;
6806f6ba60Sopenharmony_ci        if (currentTimes % timeBase == 0) {
6906f6ba60Sopenharmony_ci            printf("Thread %d, %lld: ", idx + 1, currentTimes);
7006f6ba60Sopenharmony_ci            for (int i = 0 ; i < displaySize ; i++) {
7106f6ba60Sopenharmony_ci                printf("%d ", mem[i]);
7206f6ba60Sopenharmony_ci            }
7306f6ba60Sopenharmony_ci            printf("\n");
7406f6ba60Sopenharmony_ci        }
7506f6ba60Sopenharmony_ci        clock_gettime(CLOCK_REALTIME, &beginTimeFree);
7606f6ba60Sopenharmony_ci        if (mem != nullptr) {
7706f6ba60Sopenharmony_ci            free(mem);
7806f6ba60Sopenharmony_ci        }
7906f6ba60Sopenharmony_ci        clock_gettime(CLOCK_REALTIME, &endTimeFree);
8006f6ba60Sopenharmony_ci        std::atomic_fetch_add_explicit(
8106f6ba60Sopenharmony_ci            &g_freeTotalTime,
8206f6ba60Sopenharmony_ci            static_cast<long long>((endTimeFree.tv_sec - beginTimeFree.tv_sec) * 1000000000L +
8306f6ba60Sopenharmony_ci                                   (endTimeFree.tv_nsec - beginTimeFree.tv_nsec)),
8406f6ba60Sopenharmony_ci            std::memory_order_relaxed);
8506f6ba60Sopenharmony_ci    }
8606f6ba60Sopenharmony_ci    while (true);
8706f6ba60Sopenharmony_ci    return nullptr;
8806f6ba60Sopenharmony_ci}
8906f6ba60Sopenharmony_ci#define PRINTF_DATA(fileptr, fmt, ...) \
9006f6ba60Sopenharmony_ci{                              \
9106f6ba60Sopenharmony_ci    do { \
9206f6ba60Sopenharmony_ci        fprintf(stderr, fmt, ## __VA_ARGS__); \
9306f6ba60Sopenharmony_ci        fprintf(fileptr, fmt, ## __VA_ARGS__); \
9406f6ba60Sopenharmony_ci        fflush(fileptr); \
9506f6ba60Sopenharmony_ci    } while (0); \
9606f6ba60Sopenharmony_ci}
9706f6ba60Sopenharmony_ci
9806f6ba60Sopenharmony_civoid Usage()
9906f6ba60Sopenharmony_ci{
10006f6ba60Sopenharmony_ci    printf("Usage: perf_test_data <-o output_file_name> [-t threadNum[] [-d g_duration] [-s g_memSize]\n");
10106f6ba60Sopenharmony_ci}
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_civoid FileClose(FILE* fp)
10406f6ba60Sopenharmony_ci{
10506f6ba60Sopenharmony_ci    if (fp != nullptr) {
10606f6ba60Sopenharmony_ci        fclose(fp);
10706f6ba60Sopenharmony_ci    }
10806f6ba60Sopenharmony_ci}
10906f6ba60Sopenharmony_ci
11006f6ba60Sopenharmony_ci} // namespace
11106f6ba60Sopenharmony_ci
11206f6ba60Sopenharmony_ciint main(int argc, char *argv[])
11306f6ba60Sopenharmony_ci{
11406f6ba60Sopenharmony_ci    int threadNum = 1;
11506f6ba60Sopenharmony_ci    g_duration = DURATION_TIME;
11606f6ba60Sopenharmony_ci    g_memSize = MEMORY_BUFFER_SIZE;
11706f6ba60Sopenharmony_ci    std::unique_ptr<FILE, void (*)(FILE*)> outFp(nullptr, nullptr);
11806f6ba60Sopenharmony_ci    for (int idx = 1; idx < argc; ++idx) {
11906f6ba60Sopenharmony_ci        if (strcmp(argv[idx], "-o") == 0) {
12006f6ba60Sopenharmony_ci            if (idx + 1 >= argc) {
12106f6ba60Sopenharmony_ci                Usage();
12206f6ba60Sopenharmony_ci                return 1;
12306f6ba60Sopenharmony_ci            } else {
12406f6ba60Sopenharmony_ci                ++idx;
12506f6ba60Sopenharmony_ci                outFp = std::unique_ptr<FILE, void (*)(FILE*)>(fopen(argv[idx], "w"), FileClose);
12606f6ba60Sopenharmony_ci                if (outFp == nullptr) {
12706f6ba60Sopenharmony_ci                    printf("File '%s' can't be opened.\n", argv[idx]);
12806f6ba60Sopenharmony_ci                    return 1;
12906f6ba60Sopenharmony_ci                }
13006f6ba60Sopenharmony_ci            }
13106f6ba60Sopenharmony_ci        } else if (strcmp(argv[idx], "-t") == 0) {
13206f6ba60Sopenharmony_ci            if (idx + 1 >= argc) {
13306f6ba60Sopenharmony_ci                Usage();
13406f6ba60Sopenharmony_ci                return 1;
13506f6ba60Sopenharmony_ci            } else {
13606f6ba60Sopenharmony_ci                ++idx;
13706f6ba60Sopenharmony_ci                threadNum = atoi(argv[idx]);
13806f6ba60Sopenharmony_ci                if (threadNum <= 0) {
13906f6ba60Sopenharmony_ci                    printf("Thread number can't be less or equal zero.\n");
14006f6ba60Sopenharmony_ci                    return 1;
14106f6ba60Sopenharmony_ci                }
14206f6ba60Sopenharmony_ci            }
14306f6ba60Sopenharmony_ci        } else if (strcmp(argv[idx], "-d") == 0) {
14406f6ba60Sopenharmony_ci            if (idx + 1 >= argc) {
14506f6ba60Sopenharmony_ci                Usage();
14606f6ba60Sopenharmony_ci                return 1;
14706f6ba60Sopenharmony_ci            } else {
14806f6ba60Sopenharmony_ci                ++idx;
14906f6ba60Sopenharmony_ci                g_duration = atoi(argv[idx]);
15006f6ba60Sopenharmony_ci                if (g_duration <= 0) {
15106f6ba60Sopenharmony_ci                    printf("g_duration can't be less or equal zero.\n");
15206f6ba60Sopenharmony_ci                    return 1;
15306f6ba60Sopenharmony_ci                }
15406f6ba60Sopenharmony_ci            }
15506f6ba60Sopenharmony_ci        } else if (strcmp(argv[idx], "-s") == 0) {
15606f6ba60Sopenharmony_ci            if (idx + 1 >= argc) {
15706f6ba60Sopenharmony_ci                Usage();
15806f6ba60Sopenharmony_ci                return 1;
15906f6ba60Sopenharmony_ci            } else {
16006f6ba60Sopenharmony_ci                ++idx;
16106f6ba60Sopenharmony_ci                g_memSize = atoi(argv[idx]);
16206f6ba60Sopenharmony_ci                if (g_memSize <= 0) {
16306f6ba60Sopenharmony_ci                    printf("memory size can't be less or equal zero.\n");
16406f6ba60Sopenharmony_ci                    return 1;
16506f6ba60Sopenharmony_ci                }
16606f6ba60Sopenharmony_ci            }
16706f6ba60Sopenharmony_ci        }
16806f6ba60Sopenharmony_ci    }
16906f6ba60Sopenharmony_ci    if (outFp == nullptr) {
17006f6ba60Sopenharmony_ci        Usage();
17106f6ba60Sopenharmony_ci        return 1;
17206f6ba60Sopenharmony_ci    }
17306f6ba60Sopenharmony_ci    pthread_t* thrArray = static_cast<pthread_t*>(malloc(sizeof(pthread_t) * threadNum));
17406f6ba60Sopenharmony_ci    if (thrArray == nullptr) {
17506f6ba60Sopenharmony_ci        printf("malloc thrArray memory failed.\n");
17606f6ba60Sopenharmony_ci        return 1;
17706f6ba60Sopenharmony_ci    }
17806f6ba60Sopenharmony_ci    int idxSituation;
17906f6ba60Sopenharmony_ci    int idxSituationMax = 2;
18006f6ba60Sopenharmony_ci    int pid = static_cast<int>(getpid());
18106f6ba60Sopenharmony_ci    PRINTF_DATA(outFp.get(), "PID: %d, file: %d.nativehook\n", pid, pid);
18206f6ba60Sopenharmony_ci    PRINTF_DATA(outFp.get(),
18306f6ba60Sopenharmony_ci        "Thread number: %d, duration: %d seconds, memory size: %d bytes\n",
18406f6ba60Sopenharmony_ci        threadNum,
18506f6ba60Sopenharmony_ci        g_duration,
18606f6ba60Sopenharmony_ci        g_memSize);
18706f6ba60Sopenharmony_ci    for (idxSituation = 0; idxSituation < idxSituationMax; ++idxSituation) {
18806f6ba60Sopenharmony_ci        if (idxSituation == 0) {
18906f6ba60Sopenharmony_ci            PRINTF_DATA(outFp.get(), "No hook situation\n");
19006f6ba60Sopenharmony_ci        } else {
19106f6ba60Sopenharmony_ci            PRINTF_DATA(outFp.get(), "\nWith hook situation\n");
19206f6ba60Sopenharmony_ci            raise(N_INSTALL_MALLOC_HOOK_SIGNAL);
19306f6ba60Sopenharmony_ci        }
19406f6ba60Sopenharmony_ci        int idx;
19506f6ba60Sopenharmony_ci
19606f6ba60Sopenharmony_ci        std::atomic_store_explicit(&g_times, static_cast<long long>(0), std::memory_order_seq_cst);
19706f6ba60Sopenharmony_ci        std::atomic_store_explicit(&g_mallocTotalTime, static_cast<long long>(0), std::memory_order_seq_cst);
19806f6ba60Sopenharmony_ci        std::atomic_store_explicit(&g_freeTotalTime, static_cast<long long>(0), std::memory_order_seq_cst);
19906f6ba60Sopenharmony_ci
20006f6ba60Sopenharmony_ci        for (idx = 0; idx < threadNum; ++idx) {
20106f6ba60Sopenharmony_ci            if (pthread_create(thrArray + idx, nullptr, UserThread, reinterpret_cast<void*>(&idx)) != 0) {
20206f6ba60Sopenharmony_ci                printf("Creating thread failed.\n");
20306f6ba60Sopenharmony_ci            }
20406f6ba60Sopenharmony_ci        }
20506f6ba60Sopenharmony_ci
20606f6ba60Sopenharmony_ci        for (idx = 0; idx < threadNum; ++idx) {
20706f6ba60Sopenharmony_ci            pthread_join(thrArray[idx], nullptr);
20806f6ba60Sopenharmony_ci        }
20906f6ba60Sopenharmony_ci        long long totalTimes = g_times.load(std::memory_order_relaxed);
21006f6ba60Sopenharmony_ci        PRINTF_DATA(outFp.get(), "The total g_times(malloc/free): %lld\n", totalTimes);
21106f6ba60Sopenharmony_ci    }
21206f6ba60Sopenharmony_ci    if (thrArray != nullptr) {
21306f6ba60Sopenharmony_ci        free(thrArray);
21406f6ba60Sopenharmony_ci    }
21506f6ba60Sopenharmony_ci    printf("Exit\n");
21606f6ba60Sopenharmony_ci}
217