ATLAS Offline Software
ArenaBlock.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
16 #include <cstdlib>
17 #include <unistd.h>
18 #include <cassert>
19 #include <new>
20 #include <sys/mman.h>
21 
22 
23 namespace SG {
24 
25 
27 std::atomic<size_t> ArenaBlock::s_nactive;
28 
29 
41 ArenaBlock*
42 ArenaBlock::newBlock (size_t n, size_t elt_size, func_t* ctor)
43 {
44  static const size_t pageSize = sysconf (_SC_PAGESIZE);
45  size_t tot_size = n*elt_size + ArenaBlockBodyOffset;
46  // Round up to a multiple of pageSize.
47  size_t tot_size_rounded = (tot_size + (pageSize-1)) & ~(pageSize-1);
48  // Number of elements after rounding up.
49  size_t n_rounded = (tot_size_rounded - ArenaBlockBodyOffset) / elt_size;
50  assert (n_rounded >= n);
51  ArenaBlock* p = reinterpret_cast<ArenaBlock*>
52  (std::aligned_alloc (pageSize, tot_size_rounded));
53  if (!p) throw std::bad_alloc();
54  ++s_nactive;
55  p->m_link = nullptr;
56  p->m_elt_size = elt_size;
57  p->m_size = n_rounded;
58  if (ctor) {
59  for (size_t i = 0; i < n_rounded; i++)
60  ctor (p->index (i, elt_size));
61  }
62  return p;
63 }
64 
65 
71 void ArenaBlock::destroy (ArenaBlock* p, func_t* dtor)
72 {
73  if (dtor) {
74  size_t elt_size = p->eltSize();
75  size_t n = p->size();
76  for (size_t i = 0; i < n; i++) {
77  dtor (p->index (i, elt_size));
78  }
79  }
80  --s_nactive;
81  std::free (p);
82 }
83 
84 
92 void
94 {
95  while (p) {
96  ArenaBlock* next = p->link();
97  destroy (p, dtor);
98  p = next;
99  }
100 }
101 
102 
113 {
114  while (*link) {
115  link = &(*link)->link();
116  }
117  *link = tail;
118 }
119 
120 
134  func_t* func,
135  size_t n)
136 {
137  if (!p) return;
138  size_t elt_size = p->eltSize();
139  if (n > p->size()) {
140  n = p->size();
141  }
142  while (1) {
143  for (size_t i = 0; i < n; i++) {
144  func (p->index (i, elt_size));
145  }
146  p = p->link();
147  if (!p) break;
148  n = p->size();
149  }
150 }
151 
152 
160 {
161  // The extra size_t is a guesstimate of malloc overhead.
162  return ArenaBlockBodyOffset + sizeof (size_t);
163 }
164 
165 
173 {
174  int stat = mprotect (this, m_size*m_elt_size+ArenaBlockBodyOffset,
175  PROT_READ);
176  if (stat) {
177  throw SG::ExcProtection (errno);
178  }
179 }
180 
181 
189 {
190  int stat = mprotect (this, m_size*m_elt_size+ArenaBlockBodyOffset,
191  PROT_READ + PROT_WRITE);
192  if (stat) {
193  throw SG::ExcProtection (errno);
194  }
195 }
196 
197 
206 {
207  for (; p; p = p->link()) {
208  p->protect();
209  }
210 }
211 
212 
221 {
222  for (; p; p = p->link()) {
223  p->unprotect();
224  }
225 }
226 
227 
228 } // namespace SG
SG::ExcProtection
Exception — Attempt to change memory protection failed.
Definition: Control/AthAllocators/AthAllocators/exceptions.h:43
SG::ArenaBlock::unprotect
void unprotect()
Write-enable this block.
Definition: ArenaBlock.cxx:188
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::ArenaBlock::destroy
static void destroy(ArenaBlock *p, func_t *dtor)
Destroy a block.
Definition: ArenaBlock.cxx:71
tail
std::string tail(std::string s, const std::string &pattern)
tail of a string
Definition: computils.cxx:302
SG::ArenaBlock::applyList
static void applyList(ArenaBlock *p, func_t *func, size_t n)
Call a function on elements in a list of blocks.
Definition: ArenaBlock.cxx:133
SG::ArenaBlock::overhead
static size_t overhead()
Return the per-block memory overhead, in bytes.
Definition: ArenaBlock.cxx:159
SG::ArenaBlock::newBlock
static ArenaBlock * newBlock(size_t n, size_t elt_size, func_t *ctor)
Create a new block.
Definition: ArenaBlock.cxx:42
SG::ArenaBlock::appendList
static void appendList(ArenaBlock **headp, ArenaBlock *tail)
Concatenate two lists of blocks.
Definition: ArenaBlock.cxx:112
SG::ArenaBlock::unprotectList
static void unprotectList(ArenaBlock *p)
Write-enable all blocks in a list.
Definition: ArenaBlock.cxx:220
SG::ArenaBlock::link
ArenaBlock *& link()
Return the link pointer of the block.
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:729
SG::ArenaBlock::m_size
size_t m_size
Number of elements in this block.
Definition: ArenaBlock.h:239
beamspotman.stat
stat
Definition: beamspotman.py:264
SG::ArenaBlock
A large memory block that gets carved into smaller uniform elements.
Definition: ArenaBlock.h:43
SG::ArenaBlock::s_nactive
static std::atomic< size_t > s_nactive
Global count of the number of blocks in use.
Definition: ArenaBlock.h:249
SG::ArenaBlock::m_elt_size
size_t m_elt_size
Size, in bytes, of each element in this block.
Definition: ArenaBlock.h:242
SG::ArenaBlock::protectList
static void protectList(ArenaBlock *p)
Write-protect all blocks in a list.
Definition: ArenaBlock.cxx:205
SG::ArenaBlock::protect
void protect()
Write-protect this block.
Definition: ArenaBlock.cxx:172
SG::ArenaBlock::destroyList
static void destroyList(ArenaBlock *p, func_t *dtor)
Destroy all blocks in a list.
Definition: ArenaBlock.cxx:93
exceptions.h
Exceptions that can be thrown from AthAllocators.
ArenaBlock.h
A large memory block that gets carved into smaller uniform elements. See Arena.h for an overview of t...