test-malloc-stats-print.c 3.0 KB
Newer Older
M
Maxim Polyakov 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (C) 2022 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.
 */

16
#include <regex.h>
17 18
#include "test-malloc-info-stats-print.h"

19 20 21
#define THREAD_DATA_REGEX_LEN (MAX_TID_LEN + 43)
#define REGEX_NMATCH 1

22 23 24 25 26
static void stderr_stats_cb(void)
{
    malloc_stats_print(print_to_file, stderr, "");
}

27
static int parse_amount(const char **s, long long *destination)
28 29 30 31 32 33 34 35 36 37 38 39 40 41
{
    char *end_ptr = NULL;
    long long result = strtoll(*s, &end_ptr, 10);
    if (end_ptr == *s) {
        return 0;
    }
    *s = end_ptr;
    if ((!isspace(*end_ptr) && *end_ptr != '\n' && *end_ptr != '\0') || result < 0) {
        return 0;
    }
    *destination = result;
    return 1;
}

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
static const char * find_thread_in_output(const char *output, const char *thread_id) 
{
    char thread_data_regex_s[THREAD_DATA_REGEX_LEN + 1];
    snprintf(thread_data_regex_s, THREAD_DATA_REGEX_LEN, "^%s([[:space:]]+[[:digit:]]+){3}[[:space:]]*$", thread_id);
    regex_t thread_data_regex;
    if (regcomp(&thread_data_regex, thread_data_regex_s, REG_EXTENDED | REG_NEWLINE) != 0) {
        t_error("Failed to compile regex %s", thread_data_regex_s);
        return NULL;
    }

    regmatch_t pmatch[REGEX_NMATCH];
    int match_result = regexec(&thread_data_regex, output, REGEX_NMATCH, pmatch, 0);
    regfree(&thread_data_regex);
    if (match_result != 0) {
        return NULL;
    }
    return output + pmatch[0].rm_so;
}

static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
62
{
63 64 65
    const char *thread_data_start = find_thread_in_output(output, thread_id);
    if (thread_data_start == NULL) {
        t_error("Failed to find thread id %s in output", thread_id);
66 67
        return 0;
    }
68 69

    thread_data_start += strlen(thread_id);
70
    int result = 1;
71 72 73
    result &= parse_amount(&thread_data_start, &stats->total_allocated_memory);
    result &= parse_amount(&thread_data_start, &stats->total_mmapped_memory);
    result &= parse_amount(&thread_data_start, &stats->mmapped_regions);
74 75 76 77

    return result;
}

78
static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space)
79
{
80
    const char *free_heap_space_start = strstr(output, "total free heap space:");
81 82 83 84 85 86
    if (free_heap_space_start == NULL) {
        return 0;
    }
    free_heap_space_start += strlen("total free heap space:");
    return parse_amount(&free_heap_space_start, total_free_heap_space);
}
87 88 89 90 91

static int is_thread_in_output(const char *output, const char *thread_id) 
{
    return find_thread_in_output(output, thread_id) != NULL;
}