test-iterate.c 5.5 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 17 18 19 20 21 22 23 24
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <memory.h>

#include "test-malloc-api-common.h"

25
#define BARRIER_HEIGHT 2
26 27 28 29 30
#define ALLOCATIONS_NUMBER 8
#define MIN(x, y) (((x) < (y)) ? (x) : (y))

typedef struct iterate_arg_s
{
M
Maxim Polyakov 已提交
31 32 33 34
    uintptr_t allocs[ALLOCATIONS_NUMBER];
    size_t allocs_reported_number[ALLOCATIONS_NUMBER];
    size_t allocs_actual_sizes[ALLOCATIONS_NUMBER];
    size_t reported_sizes[ALLOCATIONS_NUMBER];
35 36
} iterate_arg_t;

M
Maxim Polyakov 已提交
37 38 39 40
typedef struct
{
    uintptr_t *base;
    size_t size;
41 42 43 44
} allocations_info_t;

static const size_t allocs_sizes[ALLOCATIONS_NUMBER] = {
    8,
M
Maxim Polyakov 已提交
45 46 47
    2 * 1024,
    64 * 1024,
    512 * 1024,
M
Maxim Polyakov 已提交
48 49 50
    2 * 1024 * 1024,
    8 * 1024 * 1024,
    16 * 1024 * 1024,
M
Maxim Polyakov 已提交
51 52
    32 * 1024 * 1024
};
53

M
Maxim Polyakov 已提交
54 55 56 57 58 59 60 61
void iterate_callback(void *base, size_t size, void *data)
{
    iterate_arg_t *iterate_arg = (iterate_arg_t *)data;
    uintptr_t end;
    if (__builtin_add_overflow((uintptr_t)base, size, &end))
    {
        return;
    }
62

M
Maxim Polyakov 已提交
63 64 65 66 67 68 69 70
    for (size_t i = 0; i < ALLOCATIONS_NUMBER; ++i)
    {
        if (iterate_arg->allocs[i] >= (uintptr_t)base && iterate_arg->allocs[i] < end)
        {
            iterate_arg->allocs_reported_number[i]++;
            uintptr_t max_size = end - iterate_arg->allocs[i];
            iterate_arg->reported_sizes[i] = MIN(size, max_size);
        }
71
    }
M
Maxim Polyakov 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
}

void fill_allocations_info(const iterate_arg_t *iterate_arg, allocations_info_t *allocations_info)
{
    size_t min_idx, max_idx;
    uintptr_t min_val = UINTPTR_MAX, max_val = 0;

    const uintptr_t *allocs = iterate_arg->allocs;

    for (size_t i = 0; i < ALLOCATIONS_NUMBER; ++i)
    {
        if (allocs[i] > max_val)
        {
            max_val = allocs[i];
            max_idx = i;
        }
        if (allocs[i] < min_val)
        {
            min_val = allocs[i];
            min_idx = i;
        }
93 94
    }

M
Maxim Polyakov 已提交
95 96
    allocations_info->base = (void *)allocs[min_idx];
    allocations_info->size = allocs[max_idx] - allocs[min_idx] + allocs_sizes[max_idx];
97 98
}

M
Maxim Polyakov 已提交
99 100 101 102 103 104 105 106 107 108
void make_allocations(iterate_arg_t *iterate_arg)
{
    uintptr_t *allocs = iterate_arg->allocs;
    size_t *allocs_actual_sizes = iterate_arg->allocs_actual_sizes;

    for (size_t i = 0; i < ALLOCATIONS_NUMBER; ++i)
    {
        allocs[i] = (uintptr_t)malloc(allocs_sizes[i]);
        allocs_actual_sizes[i] = malloc_usable_size((void *)allocs[i]);
    }
109 110
}

M
Maxim Polyakov 已提交
111 112 113
void free_allocations(iterate_arg_t *iterate_arg)
{
    uintptr_t *allocs = iterate_arg->allocs;
114

M
Maxim Polyakov 已提交
115 116 117 118
    for (size_t i = 0; i < ALLOCATIONS_NUMBER; ++i)
    {
        free((void *)allocs[i]);
    }
119 120
}

M
Maxim Polyakov 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133
int iterate_wrapper(iterate_arg_t *iterate_arg)
{
    int ret = 0;
    allocations_info_t allocations_info;
    fill_allocations_info(iterate_arg, &allocations_info);
    malloc_iterate(allocations_info.base, allocations_info.size, iterate_callback, iterate_arg);

    for (size_t i = 0; i < ALLOCATIONS_NUMBER; ++i)
    {
        if (iterate_arg->allocs_reported_number[i] != 1)
        {
            ret = -1;
        }
134
    }
M
Maxim Polyakov 已提交
135
    return ret;
136 137 138 139 140
}

pthread_barrier_t routine_allocated;
pthread_barrier_t routine_iterated;

M
Maxim Polyakov 已提交
141 142 143 144 145 146 147
void *allocate_routine(void *vargp)
{
    iterate_arg_t *iterate_arg = (iterate_arg_t *)vargp;
    make_allocations(iterate_arg);
    pthread_barrier_wait(&routine_allocated);
    pthread_barrier_wait(&routine_iterated);
    return NULL;
148 149
}

M
Maxim Polyakov 已提交
150 151 152 153 154
void *abandoned_allocate_routine(void *vargp)
{
    iterate_arg_t *iterate_arg = (iterate_arg_t *)vargp;
    make_allocations(iterate_arg);
    return NULL;
155 156
}

M
Maxim Polyakov 已提交
157 158 159 160 161 162 163 164
int test_iterate_main_thread(void)
{
    int ret;
    iterate_arg_t iterate_arg = {{0}, {0}, {0}, {0}};
    make_allocations(&iterate_arg);
    ret = iterate_wrapper(&iterate_arg);
    free_allocations(&iterate_arg);
    return ret;
165 166
}

M
Maxim Polyakov 已提交
167 168 169 170
int test_iterate_another_thread(void)
{
    int ret;
    iterate_arg_t iterate_arg_routine = {{0}, {0}, {0}, {0}};
171 172
    pthread_barrier_init(&routine_allocated, NULL, BARRIER_HEIGHT);
    pthread_barrier_init(&routine_iterated, NULL, BARRIER_HEIGHT);
M
Maxim Polyakov 已提交
173 174 175 176 177 178 179
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, allocate_routine, (void *)&iterate_arg_routine);
    pthread_barrier_wait(&routine_allocated);
    ret = iterate_wrapper(&iterate_arg_routine);
    free_allocations(&iterate_arg_routine);
    pthread_barrier_wait(&routine_iterated);
    return ret;
180 181
}

M
Maxim Polyakov 已提交
182 183 184 185 186 187 188 189 190 191
int test_iterate_over_abandoned_allocs(void)
{
    int ret;
    iterate_arg_t iterate_arg_routine = {{0}, {0}, {0}, {0}};
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, abandoned_allocate_routine, (void *)&iterate_arg_routine);
    pthread_join(thread_id, NULL);
    ret = iterate_wrapper(&iterate_arg_routine);
    free_allocations(&iterate_arg_routine);
    return ret;
192 193
}

M
Maxim Polyakov 已提交
194 195 196 197 198 199 200
int main()
{
    int ret = 0;

    ret = check_and_report("Testing iterate main thread", test_iterate_main_thread);

    ret = -(ret || check_and_report("Testing iterate another thread", test_iterate_another_thread));
201

M
Maxim Polyakov 已提交
202
    ret = -(ret || check_and_report("Testing iterate over abandoned allocations", test_iterate_over_abandoned_allocs));
203

M
Maxim Polyakov 已提交
204
    return ret;
205
}