| 1 | /* |
| 2 | * Copyright (C) 2018 Igalia S.L |
| 3 | * Copyright (C) 2018 Metrological Group B.V. |
| 4 | * |
| 5 | * This library is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU Lesser General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the License, or (at your option) any later version. |
| 9 | * |
| 10 | * This library is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * Lesser General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU Lesser General Public |
| 16 | * License along with this library; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ |
| 19 | |
| 20 | #include "config.h" |
| 21 | #include "GstAllocatorFastMalloc.h" |
| 22 | |
| 23 | #include <gst/gst.h> |
| 24 | #include <wtf/FastMalloc.h> |
| 25 | |
| 26 | typedef struct { |
| 27 | GstMemory base; |
| 28 | |
| 29 | uint8_t* data; |
| 30 | } GstMemoryFastMalloc; |
| 31 | |
| 32 | typedef struct { |
| 33 | GstAllocator parent; |
| 34 | } GstAllocatorFastMalloc; |
| 35 | |
| 36 | typedef struct { |
| 37 | GstAllocatorClass parent; |
| 38 | } GstAllocatorFastMallocClass; |
| 39 | |
| 40 | G_DEFINE_TYPE(GstAllocatorFastMalloc, gst_allocator_fast_malloc, GST_TYPE_ALLOCATOR) |
| 41 | |
| 42 | static GstMemoryFastMalloc* gstMemoryFastMallocNew(GstAllocator* allocator, gsize size, gsize alignment, gsize offset, gsize padding, GstMemoryFlags flags) |
| 43 | { |
| 44 | // alignment should be a (power-of-two - 1). |
| 45 | alignment |= gst_memory_alignment; |
| 46 | ASSERT(!((alignment + 1) & alignment)); |
| 47 | |
| 48 | gsize = (sizeof(GstMemoryFastMalloc) + alignment) & ~alignment; |
| 49 | gsize allocationSize = offset + size + padding; |
| 50 | auto* memory = static_cast<GstMemoryFastMalloc*>(tryFastAlignedMalloc(alignment + 1, headerSize + allocationSize)); |
| 51 | if (!memory) |
| 52 | return nullptr; |
| 53 | |
| 54 | memory->data = reinterpret_cast<uint8_t*>(memory) + headerSize; |
| 55 | |
| 56 | if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED)) |
| 57 | std::memset(memory->data, 0, offset); |
| 58 | if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED)) |
| 59 | std::memset(memory->data + offset + size, 0, padding); |
| 60 | |
| 61 | gst_memory_init(GST_MEMORY_CAST(memory), flags, allocator, nullptr, allocationSize, alignment, offset, size); |
| 62 | |
| 63 | return memory; |
| 64 | } |
| 65 | |
| 66 | static GstMemory* gstAllocatorFastMallocAlloc(GstAllocator* allocator, gsize size, GstAllocationParams* params) |
| 67 | { |
| 68 | ASSERT(G_TYPE_CHECK_INSTANCE_TYPE(allocator, gst_allocator_fast_malloc_get_type())); |
| 69 | |
| 70 | return GST_MEMORY_CAST(gstMemoryFastMallocNew(allocator, size, params->align, params->prefix, params->padding, params->flags)); |
| 71 | } |
| 72 | |
| 73 | static void gstAllocatorFastMallocFree(GstAllocator* allocator, GstMemory* memory) |
| 74 | { |
| 75 | #if !ASSERT_DISABLED |
| 76 | ASSERT(G_TYPE_CHECK_INSTANCE_TYPE(allocator, gst_allocator_fast_malloc_get_type())); |
| 77 | #else |
| 78 | UNUSED_PARAM(allocator); |
| 79 | #endif |
| 80 | |
| 81 | fastAlignedFree(memory); |
| 82 | } |
| 83 | |
| 84 | static gpointer gstAllocatorFastMallocMemMap(GstMemoryFastMalloc* memory, gsize, GstMapFlags) |
| 85 | { |
| 86 | return memory->data; |
| 87 | } |
| 88 | |
| 89 | static void gstAllocatorFastMallocMemUnmap(GstMemoryFastMalloc*) |
| 90 | { |
| 91 | } |
| 92 | |
| 93 | static GstMemoryFastMalloc* gstAllocatorFastMallocMemCopy(GstMemoryFastMalloc* memory, gssize offset, gsize size) |
| 94 | { |
| 95 | if (size == static_cast<gsize>(-1)) |
| 96 | size = memory->base.size > static_cast<gsize>(offset) ? memory->base.size - offset : 0; |
| 97 | |
| 98 | auto* copy = gstMemoryFastMallocNew(memory->base.allocator, size, memory->base.align, 0, 0, static_cast<GstMemoryFlags>(0)); |
| 99 | if (!copy) |
| 100 | return nullptr; |
| 101 | |
| 102 | std::memcpy(copy->data, memory->data + memory->base.offset + offset, size); |
| 103 | return copy; |
| 104 | } |
| 105 | |
| 106 | static GstMemoryFastMalloc* gstAllocatorFastMallocMemShare(GstMemoryFastMalloc* memory, gssize offset, gsize size) |
| 107 | { |
| 108 | GstMemoryFastMalloc* sharedMemory; |
| 109 | if (!tryFastMalloc(sizeof(GstMemoryFastMalloc)).getValue(sharedMemory)) |
| 110 | return nullptr; |
| 111 | |
| 112 | sharedMemory->data = memory->data; |
| 113 | |
| 114 | if (size == static_cast<gsize>(-1)) |
| 115 | size = memory->base.size - offset; |
| 116 | |
| 117 | auto* parent = memory->base.parent ? memory->base.parent : GST_MEMORY_CAST(memory); |
| 118 | gst_memory_init(GST_MEMORY_CAST(sharedMemory), |
| 119 | static_cast<GstMemoryFlags>(GST_MINI_OBJECT_FLAGS(parent) | GST_MINI_OBJECT_FLAG_LOCK_READONLY), |
| 120 | memory->base.allocator, parent, memory->base.maxsize, memory->base.align, |
| 121 | memory->base.offset + offset, size); |
| 122 | |
| 123 | return sharedMemory; |
| 124 | } |
| 125 | |
| 126 | static gboolean gstAllocatorFastMallocMemIsSpan(GstMemoryFastMalloc* memory, GstMemoryFastMalloc* other, gsize* offset) |
| 127 | { |
| 128 | if (offset) { |
| 129 | auto* parent = reinterpret_cast<GstMemoryFastMalloc*>(memory->base.parent); |
| 130 | ASSERT(parent); |
| 131 | *offset = memory->base.offset - parent->base.offset; |
| 132 | } |
| 133 | |
| 134 | return memory->data + memory->base.offset + memory->base.size == other->data + other->base.offset; |
| 135 | } |
| 136 | |
| 137 | static void gst_allocator_fast_malloc_class_init(GstAllocatorFastMallocClass* klass) |
| 138 | { |
| 139 | auto* gstAllocatorClass = GST_ALLOCATOR_CLASS(klass); |
| 140 | gstAllocatorClass->alloc = gstAllocatorFastMallocAlloc; |
| 141 | gstAllocatorClass->free = gstAllocatorFastMallocFree; |
| 142 | } |
| 143 | |
| 144 | static void gst_allocator_fast_malloc_init(GstAllocatorFastMalloc* allocator) |
| 145 | { |
| 146 | auto* baseAllocator = GST_ALLOCATOR_CAST(allocator); |
| 147 | |
| 148 | baseAllocator->mem_type = "FastMalloc" ; |
| 149 | baseAllocator->mem_map = reinterpret_cast<GstMemoryMapFunction>(gstAllocatorFastMallocMemMap); |
| 150 | baseAllocator->mem_unmap = reinterpret_cast<GstMemoryUnmapFunction>(gstAllocatorFastMallocMemUnmap); |
| 151 | baseAllocator->mem_copy = reinterpret_cast<GstMemoryCopyFunction>(gstAllocatorFastMallocMemCopy); |
| 152 | baseAllocator->mem_share = reinterpret_cast<GstMemoryShareFunction>(gstAllocatorFastMallocMemShare); |
| 153 | baseAllocator->mem_is_span = reinterpret_cast<GstMemoryIsSpanFunction>(gstAllocatorFastMallocMemIsSpan); |
| 154 | } |
| 155 | |