• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18 
19 #include "allocator.h"
20 
21 #include <stdlib.h>
22 
23 #include <algorithm>
24 
25 #include <log/log.h>
26 
27 // #define ENABLE_ALLOC_CALLSTACKS 1
28 #if ENABLE_ALLOC_CALLSTACKS
29 #include <utils/CallStack.h>
30 #define ALOGD_CALLSTACK(...)                             \
31     do {                                                 \
32         ALOGD(__VA_ARGS__);                              \
33         android::CallStack callstack;                    \
34         callstack.update();                              \
35         callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, "  "); \
36     } while (false)
37 #else
38 #define ALOGD_CALLSTACK(...) \
39     do {                     \
40     } while (false)
41 #endif
42 
43 namespace vulkan {
44 namespace driver {
45 
46 namespace {
47 
DefaultAllocate(void *,size_t size,size_t alignment,VkSystemAllocationScope)48 VKAPI_ATTR void* DefaultAllocate(void*,
49                                  size_t size,
50                                  size_t alignment,
51                                  VkSystemAllocationScope) {
52     void* ptr = nullptr;
53     // Vulkan requires 'alignment' to be a power of two, but posix_memalign
54     // additionally requires that it be at least sizeof(void*).
55     int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
56     ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
57                     ret, ptr);
58     return ret == 0 ? ptr : nullptr;
59 }
60 
61 // This function is marked `noinline` so that LLVM can't infer an object size
62 // for FORTIFY through it, given that it's abusing malloc_usable_size().
63 __attribute__((__noinline__))
DefaultReallocate(void *,void * ptr,size_t size,size_t alignment,VkSystemAllocationScope)64 VKAPI_ATTR void* DefaultReallocate(void*,
65                                    void* ptr,
66                                    size_t size,
67                                    size_t alignment,
68                                    VkSystemAllocationScope) {
69     if (size == 0) {
70         free(ptr);
71         return nullptr;
72     }
73 
74     // TODO(b/143295633): Right now we never shrink allocations; if the new
75     // request is smaller than the existing chunk, we just continue using it.
76     // Right now the loader never reallocs, so this doesn't matter. If that
77     // changes, or if this code is copied into some other project, this should
78     // probably have a heuristic to allocate-copy-free when doing so will save
79     // "enough" space.
80     size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
81     if (size <= old_size)
82         return ptr;
83 
84     void* new_ptr = nullptr;
85     if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
86         return nullptr;
87     if (ptr) {
88         memcpy(new_ptr, ptr, std::min(old_size, size));
89         free(ptr);
90     }
91     return new_ptr;
92 }
93 
DefaultFree(void *,void * ptr)94 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
95     ALOGD_CALLSTACK("Free: %p", ptr);
96     free(ptr);
97 }
98 
99 }  // anonymous namespace
100 
GetDefaultAllocator()101 const VkAllocationCallbacks& GetDefaultAllocator() {
102     static const VkAllocationCallbacks kDefaultAllocCallbacks = {
103         .pUserData = nullptr,
104         .pfnAllocation = DefaultAllocate,
105         .pfnReallocation = DefaultReallocate,
106         .pfnFree = DefaultFree,
107     };
108 
109     return kDefaultAllocCallbacks;
110 }
111 
112 }  // namespace driver
113 }  // namespace vulkan
114