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 }