blob: 626b2ee1bca3c4b8265cd3a799f00909aef2a25d [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
Brian Silverman17311c92014-09-06 00:48:59 -04005#include "aos/linux_code/complex_thread_local.h"
Brian Silvermanb0893882014-02-10 14:48:30 -08006#include "aos/linux_code/thread_local.h"
7#include "aos/common/die.h"
8
9namespace aos {
10namespace logging {
11namespace internal {
12namespace {
13
Brian Silverman2fe007c2014-12-28 12:20:01 -080014// TODO(brians): Differentiate between threads with the same name in the same
15// process.
Brian Silverman8bd31532014-09-05 11:40:55 -040016
Brian Silvermanb0893882014-02-10 14:48:30 -080017::std::string GetMyName() {
18 // The maximum number of characters that can make up a thread name.
19 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
20 // safe by adding our own where necessary.
21 static const size_t kThreadNameLength = 16;
22
23 ::std::string process_name(program_invocation_short_name);
24
25 char thread_name_array[kThreadNameLength + 1];
26 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070027 PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
Brian Silvermanb0893882014-02-10 14:48:30 -080028 }
29 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
30 ::std::string thread_name(thread_name_array);
31
32 // If the first bunch of characters are the same.
33 // We cut off comparing at the shorter of the 2 strings because one or the
34 // other often ends up cut off.
35 if (strncmp(thread_name.c_str(), process_name.c_str(),
36 ::std::min(thread_name.length(), process_name.length())) == 0) {
37 // This thread doesn't have an actual name.
38 return process_name;
39 }
40
41 return process_name + '.' + thread_name;
42}
43
Brian Silverman17311c92014-09-06 00:48:59 -040044::aos::ComplexThreadLocal<Context> my_context;
Brian Silverman43d57d12014-05-20 14:04:07 -070045
Brian Silverman17311c92014-09-06 00:48:59 -040046// True if we're going to delete the current Context object ASAP. The
Brian Silverman43d57d12014-05-20 14:04:07 -070047// reason for doing this instead of just deleting them is that tsan (at least)
48// doesn't like it when pthread_atfork handlers do complicated stuff and it's
49// not a great idea anyways.
Brian Silverman17311c92014-09-06 00:48:59 -040050AOS_THREAD_LOCAL bool delete_current_context(false);
Brian Silvermanb0893882014-02-10 14:48:30 -080051
52} // namespace
53
Brian Silverman2fe007c2014-12-28 12:20:01 -080054// Used in aos/linux_code/init.cc when a thread's name is changed.
55void ReloadThreadName() {
56 if (my_context.created()) {
Austin Schuhaebbc342015-01-25 02:25:13 -080057 ::std::string my_name = GetMyName();
58 if (my_name.size() + 1 > sizeof(Context::name)) {
Brian Silverman2fe007c2014-12-28 12:20:01 -080059 Die("logging: process/thread name '%s' is too long\n",
Austin Schuhaebbc342015-01-25 02:25:13 -080060 my_name.c_str());
Brian Silverman2fe007c2014-12-28 12:20:01 -080061 }
Austin Schuhaebbc342015-01-25 02:25:13 -080062 strcpy(my_context->name, my_name.c_str());
63 my_context->name_size = my_name.size();
Brian Silverman2fe007c2014-12-28 12:20:01 -080064 }
65}
66
Brian Silvermanb0893882014-02-10 14:48:30 -080067Context *Context::Get() {
Brian Silverman17311c92014-09-06 00:48:59 -040068 if (__builtin_expect(delete_current_context, false)) {
69 my_context.Clear();
70 delete_current_context = false;
71 }
72 if (__builtin_expect(!my_context.created(), false)) {
73 my_context.Create();
Brian Silverman2fe007c2014-12-28 12:20:01 -080074 ReloadThreadName();
Brian Silvermanb0893882014-02-10 14:48:30 -080075 my_context->source = getpid();
76 }
Brian Silverman17311c92014-09-06 00:48:59 -040077 return my_context.get();
Brian Silvermanb0893882014-02-10 14:48:30 -080078}
79
80void Context::Delete() {
Brian Silverman17311c92014-09-06 00:48:59 -040081 delete_current_context = true;
Brian Silvermanb0893882014-02-10 14:48:30 -080082}
83
84} // namespace internal
85} // namespace logging
86} // namespace aos