/src/trafficserver/src/tscore/Arena.cc
Line | Count | Source |
1 | | /** @file |
2 | | |
3 | | A brief file description |
4 | | |
5 | | @section license License |
6 | | |
7 | | Licensed to the Apache Software Foundation (ASF) under one |
8 | | or more contributor license agreements. See the NOTICE file |
9 | | distributed with this work for additional information |
10 | | regarding copyright ownership. The ASF licenses this file |
11 | | to you under the Apache License, Version 2.0 (the |
12 | | "License"); you may not use this file except in compliance |
13 | | with the License. You may obtain a copy of the License at |
14 | | |
15 | | http://www.apache.org/licenses/LICENSE-2.0 |
16 | | |
17 | | Unless required by applicable law or agreed to in writing, software |
18 | | distributed under the License is distributed on an "AS IS" BASIS, |
19 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
20 | | See the License for the specific language governing permissions and |
21 | | limitations under the License. |
22 | | */ |
23 | | |
24 | | #include "tscore/ink_platform.h" |
25 | | #include "tscore/ink_memory.h" |
26 | | #include "tscore/Allocator.h" |
27 | | #include "tscore/Arena.h" |
28 | | #include <cassert> |
29 | | #include <cstring> |
30 | | |
31 | 0 | #define DEFAULT_ALLOC_SIZE 1024 |
32 | 0 | #define DEFAULT_BLOCK_SIZE (DEFAULT_ALLOC_SIZE - (sizeof(ArenaBlock) - 8)) |
33 | | |
34 | | static Allocator defaultSizeArenaBlock("ArenaBlock", DEFAULT_ALLOC_SIZE); |
35 | | |
36 | | /*------------------------------------------------------------------------- |
37 | | -------------------------------------------------------------------------*/ |
38 | | |
39 | | static inline ArenaBlock * |
40 | | blk_alloc(int size) |
41 | 0 | { |
42 | 0 | ArenaBlock *blk; |
43 | |
|
44 | 0 | if (size == DEFAULT_BLOCK_SIZE) { |
45 | 0 | blk = static_cast<ArenaBlock *>(defaultSizeArenaBlock.alloc_void()); |
46 | 0 | } else { |
47 | 0 | blk = static_cast<ArenaBlock *>(ats_malloc(size + sizeof(ArenaBlock) - 8)); |
48 | 0 | } |
49 | |
|
50 | 0 | blk->next = nullptr; |
51 | 0 | blk->m_heap_end = blk->data + size; |
52 | 0 | blk->m_water_level = blk->data; |
53 | |
|
54 | 0 | return blk; |
55 | 0 | } |
56 | | |
57 | | /*------------------------------------------------------------------------- |
58 | | -------------------------------------------------------------------------*/ |
59 | | |
60 | | static inline void |
61 | | blk_free(ArenaBlock *blk) |
62 | 0 | { |
63 | 0 | int size; |
64 | |
|
65 | 0 | size = blk->m_heap_end - &blk->data[0]; |
66 | 0 | if (size == DEFAULT_BLOCK_SIZE) { |
67 | 0 | defaultSizeArenaBlock.free_void(blk); |
68 | 0 | } else { |
69 | 0 | ats_free(blk); |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | /*------------------------------------------------------------------------- |
74 | | -------------------------------------------------------------------------*/ |
75 | | |
76 | | static void * |
77 | | block_alloc(ArenaBlock *block, size_t size, size_t alignment) |
78 | 0 | { |
79 | 0 | char *mem; |
80 | |
|
81 | 0 | mem = block->m_water_level; |
82 | 0 | if (((size_t)mem) & (alignment - 1)) { |
83 | 0 | mem += (alignment - ((size_t)mem)) & (alignment - 1); |
84 | 0 | } |
85 | |
|
86 | 0 | if ((block->m_heap_end >= mem) && (((size_t)block->m_heap_end - (size_t)mem) >= size)) { |
87 | 0 | block->m_water_level = mem + size; |
88 | 0 | return mem; |
89 | 0 | } |
90 | | |
91 | 0 | return nullptr; |
92 | 0 | } |
93 | | |
94 | | void * |
95 | | Arena::alloc(size_t size, size_t alignment) |
96 | 0 | { |
97 | 0 | ArenaBlock *b; |
98 | 0 | unsigned int block_size; |
99 | 0 | void *mem; |
100 | |
|
101 | 0 | ink_assert((alignment & (alignment - 1)) == 0); |
102 | |
|
103 | 0 | b = m_blocks; |
104 | 0 | while (b) { |
105 | 0 | mem = block_alloc(b, size, alignment); |
106 | 0 | if (mem) { |
107 | 0 | return mem; |
108 | 0 | } |
109 | 0 | b = b->next; |
110 | 0 | } |
111 | | |
112 | 0 | block_size = static_cast<unsigned int>(size * 1.5); |
113 | 0 | if (block_size < DEFAULT_BLOCK_SIZE) { |
114 | 0 | block_size = DEFAULT_BLOCK_SIZE; |
115 | 0 | } |
116 | |
|
117 | 0 | b = blk_alloc(block_size); |
118 | 0 | b->next = m_blocks; |
119 | 0 | m_blocks = b; |
120 | |
|
121 | 0 | mem = block_alloc(b, size, alignment); |
122 | 0 | return mem; |
123 | 0 | } |
124 | | |
125 | | /*------------------------------------------------------------------------- |
126 | | -------------------------------------------------------------------------*/ |
127 | | |
128 | | void |
129 | | Arena::free(void *mem, size_t size) |
130 | 0 | { |
131 | 0 | if (m_blocks) { |
132 | 0 | ArenaBlock *b; |
133 | |
|
134 | 0 | b = m_blocks; |
135 | 0 | while (b->next) { |
136 | 0 | if (b->m_water_level == (static_cast<char *>(mem) + size)) { |
137 | 0 | b->m_water_level = static_cast<char *>(mem); |
138 | 0 | return; |
139 | 0 | } |
140 | 0 | b = b->next; |
141 | 0 | } |
142 | 0 | } |
143 | 0 | } |
144 | | |
145 | | /*------------------------------------------------------------------------- |
146 | | -------------------------------------------------------------------------*/ |
147 | | |
148 | | void |
149 | | Arena::reset() |
150 | 0 | { |
151 | 0 | ArenaBlock *b; |
152 | |
|
153 | 0 | while (m_blocks) { |
154 | 0 | b = m_blocks->next; |
155 | 0 | blk_free(m_blocks); |
156 | 0 | m_blocks = b; |
157 | 0 | } |
158 | 0 | ink_assert(m_blocks == nullptr); |
159 | 0 | } |