1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#ifndef _BIONIC_THREAD_LOCAL_BUFFER_H_included 30#define _BIONIC_THREAD_LOCAL_BUFFER_H_included 31 32#include <malloc.h> 33#include <pthread.h> 34 35// libstdc++ currently contains __cxa_guard_acquire and __cxa_guard_release, 36// so we make do with macros instead of a C++ class. 37// TODO: move __cxa_guard_acquire and __cxa_guard_release into libc. 38 39// We used to use pthread_once to initialize the keys, but life is more predictable 40// if we allocate them all up front when the C library starts up, via __constructor__. 41 42#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \ 43 static pthread_key_t __bionic_tls_ ## name ## _key; \ 44 static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \ 45 free(buffer); \ 46 } \ 47 __attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \ 48 pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \ 49 } 50 51// Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized. 52#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \ 53 type name ## _tls_buffer = \ 54 reinterpret_cast<type>(pthread_getspecific(__bionic_tls_ ## name ## _key)); \ 55 if (name ## _tls_buffer == NULL) { \ 56 name ## _tls_buffer = reinterpret_cast<type>(calloc(1, byte_count)); \ 57 pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \ 58 } \ 59 const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count 60 61#endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included 62