1 /* libunwind - a platform-independent unwind library
2 Copyright (C) 2002-2003, 2005 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4 Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
6 This file is part of libunwind.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
27 #include "libunwind_i.h"
29 /* From GCC docs: ``Gcc also provides a target specific macro
30 * __BIGGEST_ALIGNMENT__, which is the largest alignment ever used for any data
31 * type on the target machine you are compiling for.'' */
32 #ifdef __BIGGEST_ALIGNMENT__
33 # define MAX_ALIGN __BIGGEST_ALIGNMENT__
35 /* Crude hack to check that MAX_ALIGN is power-of-two.
36 * sizeof(long double) = 12 on i386. */
37 # define MAX_ALIGN_(n) (n < 8 ? 8 : \
39 # define MAX_ALIGN MAX_ALIGN_(sizeof (long double))
42 static char sos_memory
[SOS_MEMORY_SIZE
] ALIGNED(MAX_ALIGN
);
43 static size_t sos_memory_freepos
;
44 static size_t pg_size
;
47 sos_alloc (size_t size
)
51 size
= UNW_ALIGN(size
, MAX_ALIGN
);
53 #if defined(__GNUC__) && defined(HAVE_FETCH_AND_ADD)
54 /* Assume `sos_memory' is suitably aligned. */
55 assert(((uintptr_t) &sos_memory
[0] & (MAX_ALIGN
-1)) == 0);
57 pos
= fetch_and_add (&sos_memory_freepos
, size
);
59 static define_lock (sos_lock
);
60 intrmask_t saved_mask
;
62 lock_acquire (&sos_lock
, saved_mask
);
64 /* No assumptions about `sos_memory' alignment. */
65 if (sos_memory_freepos
== 0)
67 unsigned align
= UNW_ALIGN((uintptr_t) &sos_memory
[0], MAX_ALIGN
)
68 - (uintptr_t) &sos_memory
[0];
69 sos_memory_freepos
= align
;
71 pos
= sos_memory_freepos
;
72 sos_memory_freepos
+= size
;
74 lock_release (&sos_lock
, saved_mask
);
77 assert (((uintptr_t) &sos_memory
[pos
] & (MAX_ALIGN
-1)) == 0);
78 assert ((pos
+size
) <= SOS_MEMORY_SIZE
);
80 return &sos_memory
[pos
];
83 /* Must be called while holding the mempool lock. */
86 free_object (struct mempool
*pool
, void *object
)
88 struct object
*obj
= object
;
90 obj
->next
= pool
->free_list
;
91 pool
->free_list
= obj
;
96 add_memory (struct mempool
*pool
, char *mem
, size_t size
, size_t obj_size
)
100 for (obj
= mem
; obj
<= mem
+ size
- obj_size
; obj
+= obj_size
)
101 free_object (pool
, obj
);
105 expand (struct mempool
*pool
)
110 size
= pool
->chunk_size
;
111 GET_MEMORY (mem
, size
);
114 size
= UNW_ALIGN(pool
->obj_size
, pg_size
);
115 GET_MEMORY (mem
, size
);
118 /* last chance: try to allocate one object from the SOS memory */
119 size
= pool
->obj_size
;
120 mem
= sos_alloc (size
);
123 add_memory (pool
, mem
, size
, pool
->obj_size
);
127 mempool_init (struct mempool
*pool
, size_t obj_size
, size_t reserve
)
130 pg_size
= getpagesize ();
132 memset (pool
, 0, sizeof (*pool
));
134 lock_init (&pool
->lock
);
136 /* round object-size up to integer multiple of MAX_ALIGN */
137 obj_size
= UNW_ALIGN(obj_size
, MAX_ALIGN
);
141 reserve
= pg_size
/ obj_size
/ 4;
146 pool
->obj_size
= obj_size
;
147 pool
->reserve
= reserve
;
148 pool
->chunk_size
= UNW_ALIGN(2*reserve
*obj_size
, pg_size
);
154 mempool_alloc (struct mempool
*pool
)
156 intrmask_t saved_mask
;
159 lock_acquire (&pool
->lock
, saved_mask
);
161 if (pool
->num_free
<= pool
->reserve
)
164 assert (pool
->num_free
> 0);
167 obj
= pool
->free_list
;
168 pool
->free_list
= obj
->next
;
170 lock_release (&pool
->lock
, saved_mask
);
175 mempool_free (struct mempool
*pool
, void *object
)
177 intrmask_t saved_mask
;
179 lock_acquire (&pool
->lock
, saved_mask
);
181 free_object (pool
, object
);
183 lock_release (&pool
->lock
, saved_mask
);