blob: f3ea9e02eb75c58daa0c4e686a7a0025486d62f5 [file] [log] [blame]
Brian Silvermanb0893882014-02-10 14:48:30 -08001#include "aos/linux_code/logging/linux_logging.h"
2
3#include <sys/prctl.h>
4
5#include "aos/linux_code/thread_local.h"
6#include "aos/common/die.h"
7
8namespace aos {
9namespace logging {
10namespace internal {
11namespace {
12
13::std::string GetMyName() {
14 // The maximum number of characters that can make up a thread name.
15 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
16 // safe by adding our own where necessary.
17 static const size_t kThreadNameLength = 16;
18
19 ::std::string process_name(program_invocation_short_name);
20
21 char thread_name_array[kThreadNameLength + 1];
22 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070023 PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
Brian Silvermanb0893882014-02-10 14:48:30 -080024 }
25 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
26 ::std::string thread_name(thread_name_array);
27
28 // If the first bunch of characters are the same.
29 // We cut off comparing at the shorter of the 2 strings because one or the
30 // other often ends up cut off.
31 if (strncmp(thread_name.c_str(), process_name.c_str(),
32 ::std::min(thread_name.length(), process_name.length())) == 0) {
33 // This thread doesn't have an actual name.
34 return process_name;
35 }
36
37 return process_name + '.' + thread_name;
38}
39
Brian Silverman43d57d12014-05-20 14:04:07 -070040AOS_THREAD_LOCAL Context *my_context(nullptr);
41
42// A temporary stash for Context objects that we're going to delete ASAP. The
43// reason for doing this instead of just deleting them is that tsan (at least)
44// doesn't like it when pthread_atfork handlers do complicated stuff and it's
45// not a great idea anyways.
46AOS_THREAD_LOCAL Context *old_context(nullptr);
Brian Silvermanb0893882014-02-10 14:48:30 -080047
48} // namespace
49
50Context *Context::Get() {
Brian Silverman43d57d12014-05-20 14:04:07 -070051 if (__builtin_expect(my_context == nullptr, 0)) {
52 if (old_context != nullptr) {
53 delete old_context;
54 old_context = nullptr;
55 }
Brian Silvermanb0893882014-02-10 14:48:30 -080056 my_context = new Context();
57 my_context->name = GetMyName();
58 if (my_context->name.size() + 1 > sizeof(LogMessage::name)) {
59 Die("logging: process/thread name '%s' is too long\n",
60 my_context->name.c_str());
61 }
62 my_context->source = getpid();
63 }
64 return my_context;
65}
66
67void Context::Delete() {
Brian Silverman43d57d12014-05-20 14:04:07 -070068 if (my_context != nullptr) {
69 if (old_context != nullptr) {
70 delete old_context;
71 }
72 old_context = my_context;
73 my_context = nullptr;
74 }
Brian Silvermanb0893882014-02-10 14:48:30 -080075}
76
77} // namespace internal
78} // namespace logging
79} // namespace aos