1// Copyright (c) 2013 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
11namespace {
12
13static pthread_key_t s_thread_key;
14static pthread_once_t s_once = PTHREAD_ONCE_INIT;
15
16static void ThreadDataDestroy(void* data) { free(data); }
17
18static void InitThreadKey() {
19  pthread_key_create(&s_thread_key, ThreadDataDestroy);
20}
21
22}  // namespace
23
24namespace crazy {
25
26void ThreadData::Init() {
27  dlerror_ = dlerror_buffers_[0];
28  dlerror_[0] = '\0';
29}
30
31void 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
39void 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
47void 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
54ThreadData* GetThreadDataFast() {
55  return reinterpret_cast<ThreadData*>(pthread_getspecific(s_thread_key));
56}
57
58ThreadData* 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.
70void SetLinkerErrorString(const char* str) { GetThreadData()->SetError(str); }
71
72// Set the formatted linker error for the current thread.
73void 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
81