hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * Copyright (C) 2018 Philippe Gerum <rpm@xenomai.org>
 *
 * SPDX-License-Identifier: MIT
 */
#include <tlsf/tlsf.h>
#include <stdlib.h>
#include <pthread.h>
#include "memcheck/memcheck.h"
 
smokey_test_plugin(memory_tlsf,
          MEMCHECK_ARGS,
          "Check for the TLSF allocator sanity.\n"
          MEMCHECK_HELP_STRINGS
   );
 
#define MIN_HEAP_SIZE  8192
#define MAX_HEAP_SIZE  (1024 * 1024 * 2)
#define RANDOM_ROUNDS  1024
 
#define PATTERN_HEAP_SIZE  (128*1024)
#define PATTERN_ROUNDS     128
 
static struct memcheck_descriptor tlsf_descriptor;
 
static pthread_mutex_t tlsf_lock = PTHREAD_MUTEX_INITIALIZER;
 
static size_t overhead;
 
static size_t test_pool_size; /* TLSF does not save this information. */
 
static int do_tlsf_init(void *dummy, void *mem, size_t pool_size)
{
   tlsf_descriptor.heap = mem;
   return init_memory_pool(pool_size, mem) == -1L ? -ENOMEM : 0;
}
 
static void do_tlsf_destroy(void *pool)
{
   destroy_memory_pool(pool);
}
 
static void *do_tlsf_alloc(void *pool, size_t size)
{
   void *p;
 
   pthread_mutex_lock(&tlsf_lock);
   p = malloc_ex(size, pool);
   pthread_mutex_unlock(&tlsf_lock);
 
   return p;
}
 
static int do_tlsf_free(void *pool, void *block)
{
   pthread_mutex_lock(&tlsf_lock);
   free_ex(block, pool);
   pthread_mutex_unlock(&tlsf_lock);
 
   return 0;    /* Yeah, well... */
}
 
static size_t do_tlsf_used_size(void *pool)
{
   /* Do not count the overhead memory for the TLSF header. */
   return get_used_size(pool) - overhead;
}
 
static size_t do_tlsf_usable_size(void *pool)
{
   return test_pool_size;
}
 
static size_t do_tlsf_arena_size(size_t pool_size)
{
   size_t available_size;
   void *pool;
 
   /*
    * The area size is the total amount of memory some allocator
    * may need for managing a heap, including its metadata. We
    * need to figure out how much memory overhead TLSF has for a
    * given pool size, which we add to the ideal pool_size for
    * determining the arena size.
    */
   test_pool_size = pool_size;
   pool = __STD(malloc(pool_size));
   available_size = init_memory_pool(pool_size, pool);
   if (available_size == (size_t)-1) {
       __STD(free(pool));
       return 0;
   }
 
   destroy_memory_pool(pool);
   overhead = pool_size - available_size;
   __STD(free(pool));
 
   return pool_size + overhead;
}
 
static struct memcheck_descriptor tlsf_descriptor = {
   .name = "tlsf",
   .init = HEAP_INIT_T(do_tlsf_init),
   .destroy = HEAP_DESTROY_T(do_tlsf_destroy),
   .alloc = HEAP_ALLOC_T(do_tlsf_alloc),
   .free = HEAP_FREE_T(do_tlsf_free),
   .get_usable_size = HEAP_USABLE_T(do_tlsf_usable_size),
   .get_used_size = HEAP_USED_T(do_tlsf_used_size),
   .get_arena_size = do_tlsf_arena_size,
   .seq_min_heap_size = MIN_HEAP_SIZE,
   .seq_max_heap_size = MAX_HEAP_SIZE,
   .random_rounds = RANDOM_ROUNDS,
   .pattern_heap_size = PATTERN_HEAP_SIZE,
   .pattern_rounds = PATTERN_ROUNDS,
   /* TLSF always has overhead, can't check for ZEROOVRD. */
   .valid_flags = MEMCHECK_ALL_FLAGS & ~MEMCHECK_ZEROOVRD,
};
 
static int run_memory_tlsf(struct smokey_test *t,
              int argc, char *const argv[])
{
   return memcheck_run(&tlsf_descriptor, t, argc, argv);
}