blob: b0a5c1b601fefe8ae9c9b6010266fb4499d8e429 [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/common/die.h"
7
8namespace aos {
9namespace logging {
10namespace internal {
11namespace {
12
Brian Silverman2fe007c2014-12-28 12:20:01 -080013// TODO(brians): Differentiate between threads with the same name in the same
14// process.
Brian Silverman8bd31532014-09-05 11:40:55 -040015
Brian Silvermanb0893882014-02-10 14:48:30 -080016::std::string GetMyName() {
17 // The maximum number of characters that can make up a thread name.
18 // The docs are unclear if it can be 16 characters with no '\0', so we'll be
19 // safe by adding our own where necessary.
20 static const size_t kThreadNameLength = 16;
21
22 ::std::string process_name(program_invocation_short_name);
23
24 char thread_name_array[kThreadNameLength + 1];
25 if (prctl(PR_GET_NAME, thread_name_array) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070026 PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
Brian Silvermanb0893882014-02-10 14:48:30 -080027 }
28 thread_name_array[sizeof(thread_name_array) - 1] = '\0';
29 ::std::string thread_name(thread_name_array);
30
31 // If the first bunch of characters are the same.
32 // We cut off comparing at the shorter of the 2 strings because one or the
33 // other often ends up cut off.
34 if (strncmp(thread_name.c_str(), process_name.c_str(),
35 ::std::min(thread_name.length(), process_name.length())) == 0) {
36 // This thread doesn't have an actual name.
37 return process_name;
38 }
39
40 return process_name + '.' + thread_name;
41}
42
Brian Silverman17311c92014-09-06 00:48:59 -040043::aos::ComplexThreadLocal<Context> my_context;
Brian Silverman43d57d12014-05-20 14:04:07 -070044
Brian Silverman17311c92014-09-06 00:48:59 -040045// True if we're going to delete the current Context object ASAP. The
Brian Silverman43d57d12014-05-20 14:04:07 -070046// reason for doing this instead of just deleting them is that tsan (at least)
47// doesn't like it when pthread_atfork handlers do complicated stuff and it's
48// not a great idea anyways.
Brian Silverman8f373b12015-04-03 15:36:52 -040049thread_local bool delete_current_context(false);
Brian Silvermanb0893882014-02-10 14:48:30 -080050
51} // namespace
52
Brian Silverman2fe007c2014-12-28 12:20:01 -080053// Used in aos/linux_code/init.cc when a thread's name is changed.
54void ReloadThreadName() {
55 if (my_context.created()) {
Austin Schuhaebbc342015-01-25 02:25:13 -080056 ::std::string my_name = GetMyName();
57 if (my_name.size() + 1 > sizeof(Context::name)) {
Brian Silverman2fe007c2014-12-28 12:20:01 -080058 Die("logging: process/thread name '%s' is too long\n",
Austin Schuhaebbc342015-01-25 02:25:13 -080059 my_name.c_str());
Brian Silverman2fe007c2014-12-28 12:20:01 -080060 }
Austin Schuhaebbc342015-01-25 02:25:13 -080061 strcpy(my_context->name, my_name.c_str());
62 my_context->name_size = my_name.size();
Brian Silverman2fe007c2014-12-28 12:20:01 -080063 }
64}
65
Brian Silvermanb0893882014-02-10 14:48:30 -080066Context *Context::Get() {
Brian Silverman17311c92014-09-06 00:48:59 -040067 if (__builtin_expect(delete_current_context, false)) {
68 my_context.Clear();
69 delete_current_context = false;
70 }
71 if (__builtin_expect(!my_context.created(), false)) {
72 my_context.Create();
Brian Silverman2fe007c2014-12-28 12:20:01 -080073 ReloadThreadName();
Brian Silvermanb0893882014-02-10 14:48:30 -080074 my_context->source = getpid();
75 }
Brian Silverman17311c92014-09-06 00:48:59 -040076 return my_context.get();
Brian Silvermanb0893882014-02-10 14:48:30 -080077}
78
79void Context::Delete() {
Brian Silverman17311c92014-09-06 00:48:59 -040080 delete_current_context = true;
Brian Silvermanb0893882014-02-10 14:48:30 -080081}
82
83} // namespace internal
84} // namespace logging
85} // namespace aos