165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm/* libunwind - a platform-independent unwind library 2b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm Copyright (C) 2002-2003, 2005 Hewlett-Packard Co 365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 426fc1563fba945d0356e4a7dd935a6a57b3c03dbTommi Rantala Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com> 565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmThis file is part of libunwind. 765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmPermission is hereby granted, free of charge, to any person obtaining 965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidma copy of this software and associated documentation files (the 1065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm"Software"), to deal in the Software without restriction, including 1165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish, 1265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to 1365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmpermit persons to whom the Software is furnished to do so, subject to 1465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmthe following conditions: 1565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 1665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmThe above copyright notice and this permission notice shall be 1765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmincluded in all copies or substantial portions of the Software. 1865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 1965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 2365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 2665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 27670dd57e827a3583a9284634cf1244eb8cab4795hp.com!davidm#include "libunwind_i.h" 2865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 29e6edad069c95127383a8122608a6bd3785413204Tommi Rantala/* From GCC docs: ``Gcc also provides a target specific macro 30e6edad069c95127383a8122608a6bd3785413204Tommi Rantala * __BIGGEST_ALIGNMENT__, which is the largest alignment ever used for any data 31e6edad069c95127383a8122608a6bd3785413204Tommi Rantala * type on the target machine you are compiling for.'' */ 32e6edad069c95127383a8122608a6bd3785413204Tommi Rantala#ifdef __BIGGEST_ALIGNMENT__ 33e6edad069c95127383a8122608a6bd3785413204Tommi Rantala# define MAX_ALIGN __BIGGEST_ALIGNMENT__ 34e6edad069c95127383a8122608a6bd3785413204Tommi Rantala#else 35c36a14f24507a3fd988430eba872ded895ed6913Tommi Rantala/* Crude hack to check that MAX_ALIGN is power-of-two. 36c36a14f24507a3fd988430eba872ded895ed6913Tommi Rantala * sizeof(long double) = 12 on i386. */ 37c36a14f24507a3fd988430eba872ded895ed6913Tommi Rantala# define MAX_ALIGN_(n) (n < 8 ? 8 : \ 38c36a14f24507a3fd988430eba872ded895ed6913Tommi Rantala n < 16 ? 16 : n) 39c36a14f24507a3fd988430eba872ded895ed6913Tommi Rantala# define MAX_ALIGN MAX_ALIGN_(sizeof (long double)) 40e6edad069c95127383a8122608a6bd3785413204Tommi Rantala#endif 4165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 4226fc1563fba945d0356e4a7dd935a6a57b3c03dbTommi Rantalastatic char sos_memory[SOS_MEMORY_SIZE] ALIGNED(MAX_ALIGN); 439a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantalastatic size_t sos_memory_freepos; 4465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic size_t pg_size; 4565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 4665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void * 4765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmsos_alloc (size_t size) 4865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 499a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala size_t pos; 5065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 51c2f7574187cfbb36dbcdc85bc61a027a4025f394Tommi Rantala size = UNW_ALIGN(size, MAX_ALIGN); 5265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 53cb3fbbb1729254e9a49e3f8fbe1cadbd519ece52Arun Sharma#if defined(__GNUC__) && defined(HAVE_FETCH_AND_ADD) 549a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala /* Assume `sos_memory' is suitably aligned. */ 559a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala assert(((uintptr_t) &sos_memory[0] & (MAX_ALIGN-1)) == 0); 569a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala 579a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala pos = fetch_and_add (&sos_memory_freepos, size); 5865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#else 59b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm static define_lock (sos_lock); 60b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm intrmask_t saved_mask; 6165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 62b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm lock_acquire (&sos_lock, saved_mask); 6365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 649a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala /* No assumptions about `sos_memory' alignment. */ 659a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala if (sos_memory_freepos == 0) 669a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala { 679a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala unsigned align = UNW_ALIGN((uintptr_t) &sos_memory[0], MAX_ALIGN) 689a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala - (uintptr_t) &sos_memory[0]; 699a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala sos_memory_freepos = align; 709a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala } 719a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala pos = sos_memory_freepos; 729a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala sos_memory_freepos += size; 7365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 74670dd57e827a3583a9284634cf1244eb8cab4795hp.com!davidm lock_release (&sos_lock, saved_mask); 7565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm#endif 769a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala 779a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala assert (((uintptr_t) &sos_memory[pos] & (MAX_ALIGN-1)) == 0); 789a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala assert ((pos+size) <= SOS_MEMORY_SIZE); 799a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala 809a3565ddc1e956ef1f52806093e949c7809f6e79Tommi Rantala return &sos_memory[pos]; 8165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 8265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 8365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm/* Must be called while holding the mempool lock. */ 8465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 8565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void 8665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmfree_object (struct mempool *pool, void *object) 8765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 8865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm struct object *obj = object; 8965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 9065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm obj->next = pool->free_list; 9165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm pool->free_list = obj; 9265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm ++pool->num_free; 9365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 9465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 9565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void 9665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmadd_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size) 9765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 9865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm char *obj; 9965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 10058badbb3393efc20f87a0ca462c5ba463eb3e8bamostang.com!davidm for (obj = mem; obj <= mem + size - obj_size; obj += obj_size) 10165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm free_object (pool, obj); 10265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 10365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 10465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmstatic void 10565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmexpand (struct mempool *pool) 10665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 10765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm size_t size; 10865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm char *mem; 10965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 11065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm size = pool->chunk_size; 111b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm GET_MEMORY (mem, size); 11265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (!mem) 11365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 114b4bde18112016cb720f3df2c0f23f5897f85f7b3Tommi Rantala size = UNW_ALIGN(pool->obj_size, pg_size); 115b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm GET_MEMORY (mem, size); 11665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (!mem) 11765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 11865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm /* last chance: try to allocate one object from the SOS memory */ 11965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm size = pool->obj_size; 12065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm mem = sos_alloc (size); 12165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 12265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 12365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm add_memory (pool, mem, size, pool->obj_size); 12465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 12565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 12665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void 12765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_init (struct mempool *pool, size_t obj_size, size_t reserve) 12865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 12965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (pg_size == 0) 13065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm pg_size = getpagesize (); 13165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 13265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm memset (pool, 0, sizeof (*pool)); 13365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 134b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm lock_init (&pool->lock); 13565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 13665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm /* round object-size up to integer multiple of MAX_ALIGN */ 137c2f7574187cfbb36dbcdc85bc61a027a4025f394Tommi Rantala obj_size = UNW_ALIGN(obj_size, MAX_ALIGN); 13865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 13965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (!reserve) 14065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 141b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm reserve = pg_size / obj_size / 4; 14265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (!reserve) 14365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm reserve = 16; 14465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 14565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 14665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm pool->obj_size = obj_size; 14765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm pool->reserve = reserve; 148b4bde18112016cb720f3df2c0f23f5897f85f7b3Tommi Rantala pool->chunk_size = UNW_ALIGN(2*reserve*obj_size, pg_size); 14965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 15065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm expand (pool); 15165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 15265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 15365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void * 15465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_alloc (struct mempool *pool) 15565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 156b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm intrmask_t saved_mask; 15765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm struct object *obj; 15865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 159b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm lock_acquire (&pool->lock, saved_mask); 16065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 16165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm if (pool->num_free <= pool->reserve) 16265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm expand (pool); 16365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 16465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm assert (pool->num_free > 0); 16565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 16665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm --pool->num_free; 16765a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm obj = pool->free_list; 16865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm pool->free_list = obj->next; 16965a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 170670dd57e827a3583a9284634cf1244eb8cab4795hp.com!davidm lock_release (&pool->lock, saved_mask); 17165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm return obj; 17265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 17365a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 17465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmHIDDEN void 17565a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidmmempool_free (struct mempool *pool, void *object) 17665a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm{ 177b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm intrmask_t saved_mask; 17865a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm 179b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm lock_acquire (&pool->lock, saved_mask); 18065a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm { 18165a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm free_object (pool, object); 18265a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm } 183b38691980f4e0c1cf0e2309aa6cc35decc6b9cb7hp.com!davidm lock_release (&pool->lock, saved_mask); 18465a70e7f88f0bc0b428605a68f21e6eeb5c28804hp.com!davidm} 185