• 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 "test-malloc-stats-common.h"
17 
stats_from_mallinfo(malloc_thread_stats_t * stats,long long * total_free_heap_space,int use_mallinfo2)18 static int stats_from_mallinfo(malloc_thread_stats_t *stats, long long *total_free_heap_space, int use_mallinfo2)
19 {
20 	if (use_mallinfo2) {
21 		struct mallinfo2 info = mallinfo2();
22 		*stats = (malloc_thread_stats_t) {info.hblks, info.hblkhd, info.uordblks};
23 		*total_free_heap_space = info.fordblks;
24 		return 1;
25 	}
26 	struct mallinfo info = mallinfo();
27 	if (info.hblks < 0 || info.hblkhd < 0 || info.uordblks < 0 || info.fordblks < 0) {
28 		t_error("struct mallinfo contains negative numbers\n");
29 		return 0;
30 	}
31 	*stats = (malloc_thread_stats_t) {info.hblks, info.hblkhd, info.uordblks};
32 	*total_free_heap_space = info.fordblks;
33 	return 1;
34 }
35 
test_main_thread(int use_mallinfo2)36 static int test_main_thread(int use_mallinfo2)
37 {
38 	malloc_thread_stats_t total_stats = {0};
39 
40 	malloc_thread_stats_t total_stats_before_test = {0};
41 	long long free_heap_space_before_test = 0;
42 	int result = stats_from_mallinfo(&total_stats_before_test, &free_heap_space_before_test, use_mallinfo2);
43 
44 	void *ptrs[SIZES_COUNT];
45 
46 	for (size_t i = 0; i < SIZES_COUNT; i++) {
47 		ptrs[i] = malloc(sizes[i]);
48 	}
49 	long long free_heap_space_after_allocations = 0;
50 	result &= stats_from_mallinfo(&total_stats, &free_heap_space_after_allocations, use_mallinfo2);
51 	result &= validate_total_allocated(&total_stats);
52 	for (size_t i = 0; i < SIZES_COUNT; i++) {
53 		free(ptrs[i]);
54 	}
55 	long long free_heap_space_after_free = 0;
56 	result &= stats_from_mallinfo(&total_stats, &free_heap_space_after_free, use_mallinfo2);
57 	total_stats.mmapped_regions -= total_stats_before_test.mmapped_regions;
58 	total_stats.total_allocated_memory -= total_stats_before_test.total_allocated_memory;
59 	total_stats.total_mmapped_memory -= total_stats_before_test.total_mmapped_memory;
60 	result &= validate_all_freed(&total_stats);
61 	result &= expect_greater_equal(
62 		free_heap_space_after_free,
63 		free_heap_space_after_allocations,
64 		"free heap space after free",
65 		"free heap space after allocations");
66 	return result;
67 }
68 
test_different_threads(int use_mallinfo2)69 static int test_different_threads(int use_mallinfo2)
70 {
71 	malloc_thread_stats_t total_stats = {0};
72 	malloc_thread_stats_t total_stats_before_test = {0};
73 	long long free_heap_space_before_test = 0;
74 
75 	int result = stats_from_mallinfo(&total_stats_before_test, &free_heap_space_before_test, use_mallinfo2);
76 
77 	pthread_barrier_t alloc_barrier, free_barrier;
78 	if (pthread_barrier_init(&alloc_barrier, NULL, SIZES_COUNT + 1)) {
79 		return 0;
80 	}
81 	if (pthread_barrier_init(&free_barrier, NULL, SIZES_COUNT + 1)) {
82 		return 0;
83 	}
84 
85 	thread_data_t thread_data[SIZES_COUNT];
86 	for (size_t i = 0; i < SIZES_COUNT; i++) {
87 		thread_data[i] = (thread_data_t) {sizes[i], &alloc_barrier, &free_barrier, 0};
88 	}
89 	pthread_t threads[SIZES_COUNT];
90 	for (size_t i = 0; i < SIZES_COUNT; i++) {
91 		pthread_create(&threads[i], NULL, allocate_wait_free, &thread_data[i]);
92 	}
93 	pthread_barrier_wait(&alloc_barrier);
94 	long long free_heap_space_after_allocations = 0;
95 	result &= stats_from_mallinfo(&total_stats, &free_heap_space_after_allocations, use_mallinfo2);
96 	result &= validate_total_allocated(&total_stats);
97 
98 	pthread_barrier_wait(&free_barrier);
99 	for (size_t i = 0; i < SIZES_COUNT; i++) {
100 		pthread_join(threads[i], NULL);
101 	}
102 	long long free_heap_space_after_free = 0;
103 	result &= stats_from_mallinfo(&total_stats, &free_heap_space_after_free, use_mallinfo2);
104 	total_stats.mmapped_regions -= total_stats_before_test.mmapped_regions;
105 	total_stats.total_allocated_memory -= total_stats_before_test.total_allocated_memory;
106 	total_stats.total_mmapped_memory -= total_stats_before_test.total_mmapped_memory;
107 	result &= validate_all_freed(&total_stats);
108 	result &= expect_greater_equal(
109 		free_heap_space_after_free,
110 		free_heap_space_after_allocations,
111 		"free heap space after free",
112 		"free heap space after allocations");
113 	return result;
114 }
115 
test_and_report(int (* test_func)(int),int test_func_arg,const char * message)116 static int test_and_report(
117 	int (*test_func)(int),
118 	int test_func_arg,
119 	const char *message)
120 {
121 	t_printf("%s...", message);
122 	if (!test_func(test_func_arg)) {
123 		t_error("Failed!\n");
124 		return 0;
125 	}
126 	t_printf("Success\n");
127 	return 1;
128 }
129 
main(void)130 int main(void)
131 {
132 	int result = test_and_report(test_main_thread, 0, "Testing mallinfo main thread");
133 	result &= test_and_report(test_main_thread, 1, "Testing mallinfo2 main thread");
134 	result &= test_and_report(test_different_threads, 0, "Testing mallinfo different threads");
135 	result &= test_and_report(test_different_threads, 1, "Testing mallinfo2 different threads");
136 	return result == 0;
137 }