1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <sys.h>
8 #include <bsp.h>
9 
10 #ifndef CACHE_LINE_SIZE
11 #error bsp.h must define CACHE_LINE_SIZE
12 #endif
13 
14 // Free allocated memory and clear pointer to it.
15 //
16 // Input: alloc_ptr_ptr = ptr to variable holding allocated address.
free_clear(void * alloc_ptr_ptr)17 void free_clear(void* alloc_ptr_ptr) {
18     void** allocpp = alloc_ptr_ptr;
19 
20     // Free the allocated memory.
21     assert(*allocpp);
22     free(*allocpp);
23 
24     // Clear the allocation pointer/flag.
25     *allocpp = NULL;
26 }
27 
28 // Allocate cache line size aligned memory.
29 //
30 // Input: size = amount of memory to allocate in bytes.
31 // Returns: Pointer to aligned memory block on success, else NULL.
aalloc(size_t size)32 void* aalloc(size_t size) {
33 #if CACHE_LINE_SIZE <= 8
34     return malloc(size);
35 #else
36     ui64 malloc_addr, fs_alloc_addr;
37 
38     // Increase size for malloc request to allow for alignment and for
39     // storage of start of malloc-ed memory.
40     size += sizeof(ui64) + CACHE_LINE_SIZE - 1;
41 
42     // Allocate memory.
43     malloc_addr = (ui64)calloc(size, sizeof(ui8));
44     if (malloc_addr == 0)
45         return NULL;
46 
47     // Compute start of aligned memory block.
48     fs_alloc_addr = (malloc_addr + sizeof(ui64) + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
49 
50     // Store start address immediately prior to aligned memory.
51     *(ui64*)(fs_alloc_addr - sizeof(ui64)) = malloc_addr;
52 
53     // Return start of aligned memory.
54     return (void*)fs_alloc_addr;
55 #endif
56 }
57 
58 // Free allocated aligned memory and clear pointer to it.
59 //
60 // Input: aligned_ptr_addr = pointer to variable holding line-size aligned allocation address.
afree_clear(void * aligned_ptr_addr)61 void afree_clear(void* aligned_ptr_addr) {
62 #if CACHE_LINE_SIZE <= 8
63     free_clear(aligned_ptr_addr);
64 #else
65     void*** aptr = aligned_ptr_addr;
66 
67     // Free allocated memory.
68     free(*(*aptr - 1));
69 
70     // Clear input pointer.
71     *aptr = 0;
72 #endif
73 }
74