blob: 0945ddd041e5f6fea902f75dced5f711108ef7db [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
Brian Silverman8bd31532014-09-05 11:40:55 -040013// TODO(brians): Differentiate between threads in the same process.
14
Brian Silvermanb0893882014-02-10 14:48:30 -080015::std::string GetMyName() {
16 // The maximum number of characters that can make up a thread name.
17 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
18 // safe by adding our own where necessary.
19 static const size_t kThreadNameLength = 16;
20
21 ::std::string process_name(program_invocation_short_name);
22
23 char thread_name_array[kThreadNameLength + 1];
24 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070025 PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
Brian Silvermanb0893882014-02-10 14:48:30 -080026 }
27 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
28 ::std::string thread_name(thread_name_array);
29
30 // If the first bunch of characters are the same.
31 // We cut off comparing at the shorter of the 2 strings because one or the
32 // other often ends up cut off.
33 if (strncmp(thread_name.c_str(), process_name.c_str(),
34 ::std::min(thread_name.length(), process_name.length())) == 0) {
35 // This thread doesn't have an actual name.
36 return process_name;
37 }
38
39 return process_name + '.' + thread_name;
40}
41
Brian Silverman43d57d12014-05-20 14:04:07 -070042AOS_THREAD_LOCAL Context *my_context(nullptr);
43
44// A temporary stash for Context objects that we're going to delete ASAP. The
45// reason for doing this instead of just deleting them is that tsan (at least)
46// doesn't like it when pthread_atfork handlers do complicated stuff and it's
47// not a great idea anyways.
48AOS_THREAD_LOCAL Context *old_context(nullptr);
Brian Silvermanb0893882014-02-10 14:48:30 -080049
50} // namespace
51
52Context *Context::Get() {
Brian Silverman43d57d12014-05-20 14:04:07 -070053 if (__builtin_expect(my_context == nullptr, 0)) {
54 if (old_context != nullptr) {
55 delete old_context;
56 old_context = nullptr;
57 }
Brian Silvermanb0893882014-02-10 14:48:30 -080058 my_context = new Context();
59 my_context->name = GetMyName();
60 if (my_context->name.size() + 1 > sizeof(LogMessage::name)) {
61 Die("logging: process/thread name '%s' is too long\n",
62 my_context->name.c_str());
63 }
64 my_context->source = getpid();
65 }
66 return my_context;
67}
68
69void Context::Delete() {
Brian Silverman43d57d12014-05-20 14:04:07 -070070 if (my_context != nullptr) {
71 if (old_context != nullptr) {
72 delete old_context;
73 }
74 old_context = my_context;
75 my_context = nullptr;
76 }
Brian Silvermanb0893882014-02-10 14:48:30 -080077}
78
79} // namespace internal
80} // namespace logging
81} // namespace aos