• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 <regex.h>
17 #include "test-malloc-info-stats-print.h"
18 
19 #define THREAD_DATA_REGEX_LEN (MAX_TID_LEN + 43)
20 #define REGEX_NMATCH 1
21 
stderr_stats_cb(void)22 static void stderr_stats_cb(void)
23 {
24 	malloc_stats_print(print_to_file, stderr, "");
25 }
26 
parse_amount(const char ** s,long long * destination)27 static int parse_amount(const char **s, long long *destination)
28 {
29 	char *end_ptr = NULL;
30 	long long result = strtoll(*s, &end_ptr, 10);
31 	if (end_ptr == *s) {
32 		return 0;
33 	}
34 	*s = end_ptr;
35 	if ((!isspace(*end_ptr) && *end_ptr != '\n' && *end_ptr != '\0') || result < 0) {
36 		return 0;
37 	}
38 	*destination = result;
39 	return 1;
40 }
41 
find_thread_in_output(const char * output,const char * thread_id)42 static const char *find_thread_in_output(const char *output, const char *thread_id)
43 {
44 	char thread_data_regex_s[THREAD_DATA_REGEX_LEN + 1];
45 	snprintf(thread_data_regex_s, THREAD_DATA_REGEX_LEN, "^%s([[:space:]]+[[:digit:]]+){3}[[:space:]]*$", thread_id);
46 	regex_t thread_data_regex;
47 	if (regcomp(&thread_data_regex, thread_data_regex_s, REG_EXTENDED | REG_NEWLINE) != 0) {
48 		t_error("Failed to compile regex %s", thread_data_regex_s);
49 		return NULL;
50 	}
51 
52 	regmatch_t pmatch[REGEX_NMATCH];
53 	int match_result = regexec(&thread_data_regex, output, REGEX_NMATCH, pmatch, 0);
54 	regfree(&thread_data_regex);
55 	if (match_result != 0) {
56 		return NULL;
57 	}
58 	return output + pmatch[0].rm_so;
59 }
60 
populate_thread_stats(const char * output,const char * thread_id,malloc_thread_stats_t * stats)61 static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
62 {
63 	const char *thread_data_start = find_thread_in_output(output, thread_id);
64 	if (thread_data_start == NULL) {
65 		t_error("Failed to find thread id %s in output", thread_id);
66 		return 0;
67 	}
68 
69 	thread_data_start += strlen(thread_id);
70 	int result = 1;
71 	result &= parse_amount(&thread_data_start, &stats->total_allocated_memory);
72 	result &= parse_amount(&thread_data_start, &stats->total_mmapped_memory);
73 	result &= parse_amount(&thread_data_start, &stats->mmapped_regions);
74 
75 	return result;
76 }
77 
populate_total_free_heap_space(const char * output,long long * total_free_heap_space)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 	if (free_heap_space_start == NULL) {
82 		return 0;
83 	}
84 	free_heap_space_start += strlen("total free heap space:");
85 	return parse_amount(&free_heap_space_start, total_free_heap_space);
86 }
87 
is_thread_in_output(const char * output,const char * thread_id)88 static int is_thread_in_output(const char *output, const char *thread_id)
89 {
90 	return find_thread_in_output(output, thread_id) != NULL;
91 }