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