blob: 3701b00aec4bee77668ddd3927c7fcdb6ff3ffc1 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/logging/context.h"
Austin Schuh044e18b2015-10-21 20:17:09 -07002
3#include <string.h>
Brian Silvermancb5da1f2015-12-05 22:19:58 -05004#include <sys/prctl.h>
5#include <sys/types.h>
6#include <unistd.h>
7
8#include <string>
9
John Park33858a32018-09-28 23:05:48 -070010#include "aos/die.h"
Brian Silvermancb5da1f2015-12-05 22:19:58 -050011#include "aos/linux_code/complex_thread_local.h"
Austin Schuh044e18b2015-10-21 20:17:09 -070012
13namespace aos {
14namespace logging {
15namespace internal {
Brian Silvermancb5da1f2015-12-05 22:19:58 -050016namespace {
17
18// TODO(brians): Differentiate between threads with the same name in the same
19// process.
20
21::std::string GetMyName() {
22 // The maximum number of characters that can make up a thread name.
23 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
24 // safe by adding our own where necessary.
25 static const size_t kThreadNameLength = 16;
26
27 ::std::string process_name(program_invocation_short_name);
28
29 char thread_name_array[kThreadNameLength + 1];
30 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
31 PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
32 }
33 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
34 ::std::string thread_name(thread_name_array);
35
36 // If the first bunch of characters are the same.
37 // We cut off comparing at the shorter of the 2 strings because one or the
38 // other often ends up cut off.
39 if (strncmp(thread_name.c_str(), process_name.c_str(),
40 ::std::min(thread_name.length(), process_name.length())) == 0) {
41 // This thread doesn't have an actual name.
42 return process_name;
43 }
44
45 return process_name + '.' + thread_name;
46}
47
48::aos::ComplexThreadLocal<Context> my_context;
49
50// True if we're going to delete the current Context object ASAP. The
51// reason for doing this instead of just deleting them is that tsan (at least)
52// doesn't like it when pthread_atfork handlers do complicated stuff and it's
53// not a great idea anyways.
54thread_local bool delete_current_context(false);
55
56} // namespace
Austin Schuh044e18b2015-10-21 20:17:09 -070057
58::std::atomic<LogImplementation *> global_top_implementation(NULL);
59
60Context::Context()
61 : implementation(global_top_implementation.load()),
62 sequence(0) {
63 cork_data.Reset();
64}
65
Brian Silvermancb5da1f2015-12-05 22:19:58 -050066// Used in aos/linux_code/init.cc when a thread's name is changed.
67void ReloadThreadName() {
68 if (my_context.created()) {
69 ::std::string my_name = GetMyName();
70 if (my_name.size() + 1 > sizeof(Context::name)) {
71 Die("logging: process/thread name '%s' is too long\n",
72 my_name.c_str());
73 }
74 strcpy(my_context->name, my_name.c_str());
75 my_context->name_size = my_name.size();
76 }
77}
78
79Context *Context::Get() {
80 if (__builtin_expect(delete_current_context, false)) {
81 my_context.Clear();
82 delete_current_context = false;
83 }
84 if (__builtin_expect(!my_context.created(), false)) {
85 my_context.Create();
86 ReloadThreadName();
87 my_context->source = getpid();
88 }
89 return my_context.get();
90}
91
92void Context::Delete() {
93 delete_current_context = true;
94}
95
Austin Schuh044e18b2015-10-21 20:17:09 -070096} // namespace internal
97} // namespace logging
98} // namespace aos