blob: eb3658cb6a25a45f4e3d5435c114de5f99afcede [file] [log] [blame]
Brian Silverman14fd0fb2014-01-14 21:42:01 -08001#include "aos/linux_code/init.h"
brians343bc112013-02-10 01:53:46 +00002
3#include <stdio.h>
4#include <string.h>
5#include <sys/mman.h>
6#include <errno.h>
7#include <sched.h>
8#include <sys/resource.h>
brians343bc112013-02-10 01:53:46 +00009#include <sys/types.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <stdint.h>
Brian Silverman2fe007c2014-12-28 12:20:01 -080013#include <sys/prctl.h>
Brian Silverman40486622014-12-30 17:38:55 -080014#include <malloc.h>
brians343bc112013-02-10 01:53:46 +000015
brians343bc112013-02-10 01:53:46 +000016#include "aos/common/die.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -080017#include "aos/linux_code/logging/linux_logging.h"
18#include "aos/linux_code/ipc_lib/shared_mem.h"
brians343bc112013-02-10 01:53:46 +000019
Brian Silverman40486622014-12-30 17:38:55 -080020#ifdef TCMALLOC
21namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
22extern double FLAGS_tcmalloc_release_rate;
23}
24using FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead::
25 FLAGS_tcmalloc_release_rate;
26#endif
27
brians343bc112013-02-10 01:53:46 +000028namespace aos {
Brian Silverman2fe007c2014-12-28 12:20:01 -080029namespace logging {
30namespace internal {
brians343bc112013-02-10 01:53:46 +000031
Brian Silverman2fe007c2014-12-28 12:20:01 -080032// Implemented in aos/linux_code/logging/linux_interface.cc.
33void ReloadThreadName();
34
35} // namespace internal
36} // namespace logging
brians343bc112013-02-10 01:53:46 +000037namespace {
38
Brian Silverman80353cb2013-03-19 18:27:53 -070039void SetSoftRLimit(int resource, rlim64_t soft, bool set_for_root) {
40 bool am_root = getuid() == 0;
41 if (set_for_root || !am_root) {
brians343bc112013-02-10 01:53:46 +000042 struct rlimit64 rlim;
43 if (getrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070044 PDie("%s-init: getrlimit64(%d) failed",
45 program_invocation_short_name, resource);
brians343bc112013-02-10 01:53:46 +000046 }
47 rlim.rlim_cur = soft;
Austin Schuh6c7edbf2014-10-21 22:26:58 -070048 rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
49
brians343bc112013-02-10 01:53:46 +000050 if (setrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070051 PDie("%s-init: setrlimit64(%d, {cur=%ju,max=%ju}) failed",
52 program_invocation_short_name, resource, (uintmax_t)rlim.rlim_cur,
53 (uintmax_t)rlim.rlim_max);
brians343bc112013-02-10 01:53:46 +000054 }
55 }
56}
57
58// Common stuff that needs to happen at the beginning of both the realtime and
59// non-realtime initialization sequences. May be called twice.
60void InitStart() {
Brian Silvermanff485782014-06-18 19:59:09 -070061 ::aos::logging::Init();
Brian Silvermanfe1ef172014-04-12 17:12:45 -070062 WriteCoreDumps();
brians343bc112013-02-10 01:53:46 +000063}
64
Brian Silverman6da04272014-05-18 18:47:48 -070065void LockAllMemory() {
Brian Silverman8a6dac92015-02-21 20:08:24 -050066 // Allow locking as much as we want into RAM.
67 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, false);
68
brians343bc112013-02-10 01:53:46 +000069 InitStart();
70 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070071 PDie("%s-init: mlockall failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +000072 }
73
Brian Silverman40486622014-12-30 17:38:55 -080074 // Don't give freed memory back to the OS.
75 CHECK_EQ(1, mallopt(M_TRIM_THRESHOLD, -1));
76 // Don't use mmap for large malloc chunks.
77 CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
78
79#ifdef TCMALLOC
80 // Tell tcmalloc not to return memory.
81 FLAGS_tcmalloc_release_rate = 0.0;
82#endif
83
brians343bc112013-02-10 01:53:46 +000084 // Forces the memory pages for all the stack space that we're ever going to
85 // use to be loaded into memory (so it can be locked there).
86 uint8_t data[4096 * 8];
87 // Not 0 because linux might optimize that to a 0-filled page.
88 memset(data, 1, sizeof(data));
Brian Silverman40486622014-12-30 17:38:55 -080089
90 static const size_t kHeapPreallocSize = 1024 * 1024 * 2;
91 char *const heap_data = static_cast<char *>(malloc(kHeapPreallocSize));
92 memset(heap_data, 1, kHeapPreallocSize);
93 free(heap_data);
brians343bc112013-02-10 01:53:46 +000094}
95
brians343bc112013-02-10 01:53:46 +000096const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
97
98} // namespace
99
Brian Silverman8a6dac92015-02-21 20:08:24 -0500100void InitNRT() {
101 InitStart();
102 aos_core_create_shared_mem(false, false);
103 logging::linux_code::Register();
104}
105
106void InitCreate() {
107 InitStart();
108 aos_core_create_shared_mem(true, false);
109 logging::linux_code::Register();
110}
111
Brian Silvermanf3cfbd72013-10-28 16:26:09 -0700112void Init(int relative_priority) {
Brian Silverman8a6dac92015-02-21 20:08:24 -0500113 bool realtime = getenv(kNoRealtimeEnvironmentVariable) == nullptr;
114 if (realtime) {
brians343bc112013-02-10 01:53:46 +0000115 LockAllMemory();
Brian Silverman6da04272014-05-18 18:47:48 -0700116
Brian Silverman8dc9fd42014-02-10 13:35:43 -0800117 // Only let rt processes run for 3 seconds straight.
118 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
Brian Silverman6da04272014-05-18 18:47:48 -0700119
brians343bc112013-02-10 01:53:46 +0000120 // Allow rt processes up to priority 40.
Brian Silverman80353cb2013-03-19 18:27:53 -0700121 SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
Brian Silverman6da04272014-05-18 18:47:48 -0700122
123 // Set our process to the appropriate priority.
brians343bc112013-02-10 01:53:46 +0000124 struct sched_param param;
Brian Silvermanf3cfbd72013-10-28 16:26:09 -0700125 param.sched_priority = 30 + relative_priority;
brians343bc112013-02-10 01:53:46 +0000126 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -0700127 PDie("%s-init: setting SCHED_FIFO failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +0000128 }
129 } else {
130 fprintf(stderr, "%s not doing realtime initialization because environment"
131 " variable %s is set\n", program_invocation_short_name,
132 kNoRealtimeEnvironmentVariable);
133 printf("no realtime for %s. see stderr\n", program_invocation_short_name);
134 }
135
Brian Silverman8a6dac92015-02-21 20:08:24 -0500136 InitStart();
137 aos_core_create_shared_mem(false, realtime);
138 logging::linux_code::Register();
brians343bc112013-02-10 01:53:46 +0000139}
140
141void Cleanup() {
Brian Silverman01be0002014-05-10 15:44:38 -0700142 aos_core_free_shared_mem();
brians343bc112013-02-10 01:53:46 +0000143}
144
Brian Silvermanfe1ef172014-04-12 17:12:45 -0700145void WriteCoreDumps() {
146 // Do create core files of unlimited size.
147 SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, true);
148}
149
Brian Silvermanda45b6c2014-12-28 11:36:50 -0800150void SetCurrentThreadRealtimePriority(int priority) {
151 struct sched_param param;
152 param.sched_priority = priority;
153 if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
154 PLOG(FATAL, "sched_setscheduler(0, SCHED_FIFO, %d) failed", priority);
155 }
156}
157
Brian Silverman2fe007c2014-12-28 12:20:01 -0800158void SetCurrentThreadName(const ::std::string &name) {
159 if (name.size() > 16) {
160 LOG(FATAL, "thread name '%s' too long\n", name.c_str());
161 }
162 LOG(INFO, "this thread is changing to '%s'\n", name.c_str());
163 PCHECK(prctl(PR_SET_NAME, name.c_str()));
164 logging::internal::ReloadThreadName();
165}
166
brians343bc112013-02-10 01:53:46 +0000167} // namespace aos