blob: 0945ddd041e5f6fea902f75dced5f711108ef7db [file] [log] [blame]
#include "aos/linux_code/logging/linux_logging.h"
#include <sys/prctl.h>
#include "aos/linux_code/thread_local.h"
#include "aos/common/die.h"
namespace aos {
namespace logging {
namespace internal {
namespace {
// TODO(brians): Differentiate between threads in the same process.
::std::string GetMyName() {
// The maximum number of characters that can make up a thread name.
// The docs are unclear if it can be 16 characters with no '\0', so we'll be
// safe by adding our own where necessary.
static const size_t kThreadNameLength = 16;
::std::string process_name(program_invocation_short_name);
char thread_name_array[kThreadNameLength + 1];
if (prctl(PR_GET_NAME, thread_name_array) != 0) {
PDie("prctl(PR_GET_NAME, %p) failed", thread_name_array);
}
thread_name_array[sizeof(thread_name_array) - 1] = '\0';
::std::string thread_name(thread_name_array);
// If the first bunch of characters are the same.
// We cut off comparing at the shorter of the 2 strings because one or the
// other often ends up cut off.
if (strncmp(thread_name.c_str(), process_name.c_str(),
::std::min(thread_name.length(), process_name.length())) == 0) {
// This thread doesn't have an actual name.
return process_name;
}
return process_name + '.' + thread_name;
}
AOS_THREAD_LOCAL Context *my_context(nullptr);
// A temporary stash for Context objects that we're going to delete ASAP. The
// reason for doing this instead of just deleting them is that tsan (at least)
// doesn't like it when pthread_atfork handlers do complicated stuff and it's
// not a great idea anyways.
AOS_THREAD_LOCAL Context *old_context(nullptr);
} // namespace
Context *Context::Get() {
if (__builtin_expect(my_context == nullptr, 0)) {
if (old_context != nullptr) {
delete old_context;
old_context = nullptr;
}
my_context = new Context();
my_context->name = GetMyName();
if (my_context->name.size() + 1 > sizeof(LogMessage::name)) {
Die("logging: process/thread name '%s' is too long\n",
my_context->name.c_str());
}
my_context->source = getpid();
}
return my_context;
}
void Context::Delete() {
if (my_context != nullptr) {
if (old_context != nullptr) {
delete old_context;
}
old_context = my_context;
my_context = nullptr;
}
}
} // namespace internal
} // namespace logging
} // namespace aos