1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_thread.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <pthread.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdio.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdlib.h> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static pthread_key_t s_thread_key; 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static pthread_once_t s_once = PTHREAD_ONCE_INIT; 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static void ThreadDataDestroy(void* data) { free(data); } 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static void InitThreadKey() { 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pthread_key_create(&s_thread_key, ThreadDataDestroy); 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy { 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ThreadData::Init() { 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_ = dlerror_buffers_[0]; 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_[0] = '\0'; 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ThreadData::SwapErrorBuffers() { 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dlerror_ == dlerror_buffers_[0]) 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_ = dlerror_buffers_[1]; 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_ = dlerror_buffers_[0]; 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_[0] = '\0'; 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ThreadData::SetErrorArgs(const char* fmt, va_list args) { 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (fmt == NULL) { 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dlerror_[0] = '\0'; 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vsnprintf(dlerror_, kBufferSize, fmt, args); 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ThreadData::AppendErrorArgs(const char* fmt, va_list args) { 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (fmt == NULL) 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t len = strlen(dlerror_); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) vsnprintf(dlerror_ + len, kBufferSize - len, fmt, args); 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ThreadData* GetThreadDataFast() { 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return reinterpret_cast<ThreadData*>(pthread_getspecific(s_thread_key)); 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ThreadData* GetThreadData() { 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pthread_once(&s_once, InitThreadKey); 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ThreadData* data = GetThreadDataFast(); 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!data) { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data = reinterpret_cast<ThreadData*>(calloc(sizeof(*data), 1)); 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) data->Init(); 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pthread_setspecific(s_thread_key, data); 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return data; 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Set the linker error string for the current thread. 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SetLinkerErrorString(const char* str) { GetThreadData()->SetError(str); } 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Set the formatted linker error for the current thread. 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SetLinkerError(const char* fmt, ...) { 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_list args; 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_start(args, fmt); 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetThreadData()->SetErrorArgs(fmt, args); 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_end(args); 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace crazy 81