forked from embench/embench-iot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
beebsc.c
189 lines (129 loc) · 4.41 KB
/
beebsc.c
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* BEEBS local library variants
Copyright (C) 2019 Embecosm Limited.
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
This file is part of Embench and was formerly part of the Bristol/Embecosm
Embedded Benchmark Suite.
SPDX-License-Identifier: GPL-3.0-or-later */
/* These are very simple local versions of library routines, to ensure the
code is compiled with the flags used for the benchmark. Not all library
routines are here, just ones that cause a lot of unecessary load, or where
there is variation between platforms and architectures. */
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "beebsc.h"
/* Seed for the random number generator */
static long int seed = 0;
/* Heap records and sane initial values */
static void *heap_ptr = NULL;
static void *heap_end = NULL;
static size_t heap_requested = 0;
/* Yield a sequence of random numbers in the range [0, 2^15-1].
long int is guaranteed to be at least 32 bits. The seed only ever uses 31
bits (so is positive).
For BEEBS this gets round different operating systems using different
multipliers and offsets and RAND_MAX variations. */
int
rand_beebs (void)
{
seed = (seed * 1103515245L + 12345) & ((1UL << 31) - 1);
return (int) (seed >> 16);
}
/* Initialize the random number generator */
void
srand_beebs (unsigned int new_seed)
{
seed = (long int) new_seed;
}
/* Initialize the BEEBS heap pointers. Note that the actual memory block is
in the caller code. */
void
init_heap_beebs (void *heap, size_t heap_size)
{
assert(heap_size % sizeof(void *) == 0); /* see #138 */
heap_ptr = (void *) heap;
heap_end = (void *) ((char *) heap_ptr + heap_size);
heap_requested = 0;
}
/* Report if malloc ever failed.
Return non-zero (TRUE) if malloc did not reqest more than was available
since the last call to init_heap_beebs, zero (FALSE) otherwise. */
int
check_heap_beebs (void *heap)
{
return ((void *) ((char *) heap + heap_requested) <= heap_end);
}
/* BEEBS version of malloc.
This is primarily to reduce library and OS dependencies. Malloc is
generally not used in embedded code, or if it is, only in well defined
contexts to pre-allocate a fixed amount of memory. So this simplistic
implementation is just fine.
Note in particular the assumption that memory will never be freed! */
void *
malloc_beebs (size_t size)
{
if (size == 0)
return NULL;
void *next_heap_ptr = (char *)heap_ptr + size;
heap_requested += size;
const size_t alignment = sizeof (void *);
/* Check if the next heap pointer is aligned, otherwise add some padding */
if (((uintptr_t)next_heap_ptr % alignment) != 0)
{
size_t padding = alignment - ((uintptr_t)next_heap_ptr % alignment);
next_heap_ptr = (char *)next_heap_ptr + padding;
/* padding is added to heap_requested because otherwise it will break
check_heap_beebs() */
heap_requested += padding;
}
/* Check if we can "allocate" enough space */
if (next_heap_ptr > heap_end)
return NULL;
void *new_ptr = heap_ptr;
heap_ptr = next_heap_ptr;
return new_ptr;
}
/* BEEBS version of calloc.
Implement as wrapper for malloc */
void *
calloc_beebs (size_t nmemb, size_t size)
{
void *new_ptr = malloc_beebs (nmemb * size);
/* Calloc is defined to zero the memory. OK to use a function here, because
it will be handled specially by the compiler anyway. */
if (NULL != new_ptr)
memset (new_ptr, 0, nmemb * size);
return new_ptr;
}
/* BEEBS version of realloc.
This is primarily to reduce library and OS dependencies. We just have to
allocate new memory and copy stuff across. */
void *
realloc_beebs (void *ptr, size_t size)
{
if (ptr == NULL)
return NULL;
/* Get a new aligned pointer */
void *new_ptr = malloc_beebs (size);
/* This is clunky, since we don't know the size of the original pointer.
However it is a read only action and we know it must be big enough if we
right off the end, or we couldn't have allocated here. If the size is
smaller, it doesn't matter. */
if (new_ptr != NULL)
for (size_t i = 0; i < size; i++)
((char *)new_ptr)[i] = ((char *)ptr)[i];
return new_ptr;
}
/* BEEBS version of free.
For our simplified version of memory handling, free can just do nothing. */
void
free_beebs (void *ptr __attribute__ ((unused)))
{
}
/*
Local Variables:
mode: C
c-file-style: "gnu"
End:
*/