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 | |