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#ifndef TEST_MALLOC_STATS_COMMON_H 17#define TEST_MALLOC_STATS_COMMON_H 18 19#define _GNU_SOURCE 20 21#include <unistd.h> 22#include <sys/syscall.h> 23#include <stddef.h> 24#include <pthread.h> 25#include <malloc.h> 26#include "test.h" 27 28#define SIZES_COUNT 10 29#define SIZE_ALIGN (8 * sizeof(size_t)) 30#define MMAP_THRESHOLD ((0x1c00 * SIZE_ALIGN) - OVERHEAD) 31#define LIST_OVERHEAD (2 * sizeof(void *)) 32#define OVERHEAD (sizeof(size_t) + LIST_OVERHEAD) 33 34static size_t sizes[SIZES_COUNT] = { 35 23, 36 32, 37 256, 38 3072, 39 3584, 40 262144, 41 327680, 42 8 * 1024 * 1024, 43 16 * 1024 * 1024, 44 32 * 1024 * 1024 45}; 46 47typedef struct { 48 long long mmapped_regions; 49 long long total_mmapped_memory; 50 long long total_allocated_memory; 51} malloc_thread_stats_t; 52 53typedef struct { 54 size_t alloc_size; 55 pthread_barrier_t *alloc_barrier; 56 pthread_barrier_t *free_barrier; 57 pid_t self_id; 58} thread_data_t; 59 60static malloc_thread_stats_t get_total_from_test_sizes() 61{ 62 malloc_thread_stats_t total_stats = {0}; 63 for (size_t i = 0; i < SIZES_COUNT; i++) { 64 if (sizes[i] > MMAP_THRESHOLD) { 65 total_stats.total_mmapped_memory += sizes[i]; 66 total_stats.mmapped_regions++; 67 } 68 total_stats.total_allocated_memory += sizes[i]; 69 } 70 return total_stats; 71} 72 73static int expect_greater_equal(long long amt1, long long amt2, const char *amt1_name, const char *amt2_name) 74{ 75 if (amt1 >= amt2) { 76 return 1; 77 } 78 t_error("Expected %s(value: %lld) to be >= %s(value: %lld)\n", amt1_name, amt1, amt2_name, amt2); 79 return 0; 80} 81 82static int expect_equal(long long amt, long long value, const char *amt_name) 83{ 84 if (amt == value) { 85 return 1; 86 } 87 t_error("Expected %s(value: %lld) to be %lld\n", amt_name, amt, value); 88 return 0; 89} 90 91static int validate_total_allocated(malloc_thread_stats_t *total_stats) 92{ 93 malloc_thread_stats_t total_from_test_sizes = get_total_from_test_sizes(); 94 95 int result = expect_greater_equal( 96 total_stats->total_allocated_memory, 97 total_from_test_sizes.total_allocated_memory, 98 "allocated memory", 99 "total memory from test sizes"); 100 result &= expect_greater_equal( 101 total_stats->total_mmapped_memory, 102 total_from_test_sizes.total_mmapped_memory, 103 "mmapped memory", 104 "total large memory from test sizes"); 105 result &= expect_equal( 106 total_stats->mmapped_regions, 107 total_from_test_sizes.mmapped_regions, 108 "mmapped regions"); 109 return result; 110} 111 112static int validate_all_freed(malloc_thread_stats_t *total_stats) 113{ 114 int result = expect_equal(total_stats->total_allocated_memory, 0, "allocated memory"); 115 result &= expect_equal(total_stats->total_mmapped_memory, 0, "mmapped memory"); 116 result &= expect_equal(total_stats->mmapped_regions, 0, "mmapped regions"); 117 return result; 118} 119 120static void *allocate_wait_free(void *arg) 121{ 122 thread_data_t *thread_data = arg; 123 thread_data->self_id = syscall(__NR_gettid); 124 void *alloc = malloc(thread_data->alloc_size); 125 pthread_barrier_wait(thread_data->alloc_barrier); 126 pthread_barrier_wait(thread_data->free_barrier); 127 free(alloc); 128 return NULL; 129} 130 131#endif // TEST_MALLOC_STATS_COMMON_H 132