blob: fdb1800423f7051810351517bed3067af1075576 [file] [log] [blame]
John Park398c74a2018-10-20 21:17:39 -07001#include "aos/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
John Park33858a32018-09-28 23:05:48 -070016#include "aos/die.h"
17#include "aos/logging/implementations.h"
John Park398c74a2018-10-20 21:17:39 -070018#include "aos/ipc_lib/shared_mem.h"
brians343bc112013-02-10 01:53:46 +000019
Brian Silverman40486622014-12-30 17:38:55 -080020namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
Brian Silverman26438442015-10-11 19:36:47 -040021extern double FLAGS_tcmalloc_release_rate __attribute__((weak));
Brian Silverman40486622014-12-30 17:38:55 -080022}
23using FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead::
24 FLAGS_tcmalloc_release_rate;
Brian Silverman40486622014-12-30 17:38:55 -080025
brians343bc112013-02-10 01:53:46 +000026namespace aos {
Brian Silverman2fe007c2014-12-28 12:20:01 -080027namespace logging {
28namespace internal {
brians343bc112013-02-10 01:53:46 +000029
John Park33858a32018-09-28 23:05:48 -070030// Implemented in aos/logging/context.cc.
Brian Silverman2fe007c2014-12-28 12:20:01 -080031void ReloadThreadName();
32
33} // namespace internal
34} // namespace logging
brians343bc112013-02-10 01:53:46 +000035namespace {
36
Brian Silverman80353cb2013-03-19 18:27:53 -070037void SetSoftRLimit(int resource, rlim64_t soft, bool set_for_root) {
38 bool am_root = getuid() == 0;
39 if (set_for_root || !am_root) {
brians343bc112013-02-10 01:53:46 +000040 struct rlimit64 rlim;
41 if (getrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070042 PDie("%s-init: getrlimit64(%d) failed",
43 program_invocation_short_name, resource);
brians343bc112013-02-10 01:53:46 +000044 }
45 rlim.rlim_cur = soft;
Austin Schuh6c7edbf2014-10-21 22:26:58 -070046 rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
47
brians343bc112013-02-10 01:53:46 +000048 if (setrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070049 PDie("%s-init: setrlimit64(%d, {cur=%ju,max=%ju}) failed",
50 program_invocation_short_name, resource, (uintmax_t)rlim.rlim_cur,
51 (uintmax_t)rlim.rlim_max);
brians343bc112013-02-10 01:53:46 +000052 }
53 }
54}
55
56// Common stuff that needs to happen at the beginning of both the realtime and
57// non-realtime initialization sequences. May be called twice.
58void InitStart() {
Brian Silvermanff485782014-06-18 19:59:09 -070059 ::aos::logging::Init();
Brian Silvermanfe1ef172014-04-12 17:12:45 -070060 WriteCoreDumps();
brians343bc112013-02-10 01:53:46 +000061}
62
Austin Schuh3d4d5df2015-10-17 15:51:41 -070063const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
64
Brian Silverman8f8debf2018-03-11 19:30:23 -070065bool ShouldBeRealtime() {
66 return getenv(kNoRealtimeEnvironmentVariable) == nullptr;
67}
68
Austin Schuh3d4d5df2015-10-17 15:51:41 -070069} // namespace
70
Brian Silverman6da04272014-05-18 18:47:48 -070071void LockAllMemory() {
Brian Silverman8a6dac92015-02-21 20:08:24 -050072 // Allow locking as much as we want into RAM.
73 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, false);
74
brians343bc112013-02-10 01:53:46 +000075 InitStart();
76 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070077 PDie("%s-init: mlockall failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +000078 }
79
Brian Silverman40486622014-12-30 17:38:55 -080080 // Don't give freed memory back to the OS.
Austin Schuhf257f3c2019-10-27 21:00:43 -070081 AOS_CHECK_EQ(1, mallopt(M_TRIM_THRESHOLD, -1));
Brian Silverman40486622014-12-30 17:38:55 -080082 // Don't use mmap for large malloc chunks.
Austin Schuhf257f3c2019-10-27 21:00:43 -070083 AOS_CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
Brian Silverman40486622014-12-30 17:38:55 -080084
Brian Silverman26438442015-10-11 19:36:47 -040085 if (&FLAGS_tcmalloc_release_rate) {
86 // Tell tcmalloc not to return memory.
87 FLAGS_tcmalloc_release_rate = 0.0;
88 }
Brian Silverman40486622014-12-30 17:38:55 -080089
brians343bc112013-02-10 01:53:46 +000090 // Forces the memory pages for all the stack space that we're ever going to
91 // use to be loaded into memory (so it can be locked there).
92 uint8_t data[4096 * 8];
93 // Not 0 because linux might optimize that to a 0-filled page.
94 memset(data, 1, sizeof(data));
Brian Silverman40486622014-12-30 17:38:55 -080095
Austin Schuha96cdd92015-03-14 21:09:39 -070096 static const size_t kHeapPreallocSize = 512 * 1024;
Brian Silverman40486622014-12-30 17:38:55 -080097 char *const heap_data = static_cast<char *>(malloc(kHeapPreallocSize));
98 memset(heap_data, 1, kHeapPreallocSize);
99 free(heap_data);
brians343bc112013-02-10 01:53:46 +0000100}
101
Brian Silverman8f8debf2018-03-11 19:30:23 -0700102void InitNRT(bool for_realtime) {
Brian Silverman8a6dac92015-02-21 20:08:24 -0500103 InitStart();
Brian Silverman8f8debf2018-03-11 19:30:23 -0700104 aos_core_create_shared_mem(false, for_realtime && ShouldBeRealtime());
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500105 logging::RegisterQueueImplementation();
Austin Schuhf257f3c2019-10-27 21:00:43 -0700106 AOS_LOG(INFO, "%s initialized non-realtime\n", program_invocation_short_name);
Brian Silverman8a6dac92015-02-21 20:08:24 -0500107}
108
109void InitCreate() {
110 InitStart();
111 aos_core_create_shared_mem(true, false);
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500112 logging::RegisterQueueImplementation();
Austin Schuhf257f3c2019-10-27 21:00:43 -0700113 AOS_LOG(INFO, "%s created shm\n", program_invocation_short_name);
Brian Silverman8a6dac92015-02-21 20:08:24 -0500114}
115
Brian Silvermanf3cfbd72013-10-28 16:26:09 -0700116void Init(int relative_priority) {
Brian Silverman8f8debf2018-03-11 19:30:23 -0700117 InitStart();
118 aos_core_create_shared_mem(false, ShouldBeRealtime());
119 logging::RegisterQueueImplementation();
120 GoRT(relative_priority);
121}
122
Austin Schuh9fe68f72019-08-10 19:32:03 -0700123void InitRT() {
124 LockAllMemory();
125
126 // Only let rt processes run for 3 seconds straight.
127 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
128
129 // Allow rt processes up to priority 40.
130 SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
131}
132
Brian Silverman8f8debf2018-03-11 19:30:23 -0700133void GoRT(int relative_priority) {
134 if (ShouldBeRealtime()) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700135 InitRT();
Brian Silverman6da04272014-05-18 18:47:48 -0700136
137 // Set our process to the appropriate priority.
brians343bc112013-02-10 01:53:46 +0000138 struct sched_param param;
Brian Silvermanf3cfbd72013-10-28 16:26:09 -0700139 param.sched_priority = 30 + relative_priority;
brians343bc112013-02-10 01:53:46 +0000140 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -0700141 PDie("%s-init: setting SCHED_FIFO failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +0000142 }
143 } else {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700144 fprintf(stderr,
145 "%s not doing realtime initialization because environment"
146 " variable %s is set\n",
147 program_invocation_short_name, kNoRealtimeEnvironmentVariable);
brians343bc112013-02-10 01:53:46 +0000148 printf("no realtime for %s. see stderr\n", program_invocation_short_name);
149 }
150
Austin Schuhf257f3c2019-10-27 21:00:43 -0700151 AOS_LOG(INFO, "%s initialized realtime\n", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +0000152}
153
154void Cleanup() {
Brian Silverman01be0002014-05-10 15:44:38 -0700155 aos_core_free_shared_mem();
brians343bc112013-02-10 01:53:46 +0000156}
157
Brian Silvermanfe1ef172014-04-12 17:12:45 -0700158void WriteCoreDumps() {
159 // Do create core files of unlimited size.
160 SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, true);
161}
162
Brian Silvermanda45b6c2014-12-28 11:36:50 -0800163void SetCurrentThreadRealtimePriority(int priority) {
Brian Silvermane4d8b282015-12-24 13:44:48 -0800164 // Make sure we will only be allowed to run for 3 seconds straight.
165 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
166
Brian Silvermanda45b6c2014-12-28 11:36:50 -0800167 struct sched_param param;
168 param.sched_priority = priority;
169 if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700170 AOS_PLOG(FATAL, "sched_setscheduler(0, SCHED_FIFO, %d) failed\n", priority);
Brian Silvermana70994f2017-03-16 22:32:55 -0700171 }
172}
173
174void UnsetCurrentThreadRealtimePriority() {
175 struct sched_param param;
176 param.sched_priority = 0;
177 if (sched_setscheduler(0, SCHED_OTHER, &param) == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700178 AOS_PLOG(FATAL, "sched_setscheduler(0, SCHED_OTHER, 0) failed\n");
Brian Silvermanda45b6c2014-12-28 11:36:50 -0800179 }
180}
181
Brian Silvermane4d8b282015-12-24 13:44:48 -0800182void PinCurrentThreadToCPU(int number) {
183 cpu_set_t cpuset;
184 CPU_ZERO(&cpuset);
185 CPU_SET(number, &cpuset);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700186 AOS_PRCHECK(pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset));
Brian Silvermane4d8b282015-12-24 13:44:48 -0800187}
188
Brian Silverman2fe007c2014-12-28 12:20:01 -0800189void SetCurrentThreadName(const ::std::string &name) {
190 if (name.size() > 16) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700191 AOS_LOG(FATAL, "thread name '%s' too long\n", name.c_str());
Brian Silverman2fe007c2014-12-28 12:20:01 -0800192 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700193 AOS_LOG(INFO, "this thread is changing to '%s'\n", name.c_str());
194 AOS_PCHECK(prctl(PR_SET_NAME, name.c_str()));
Brian Silverman2fe007c2014-12-28 12:20:01 -0800195 logging::internal::ReloadThreadName();
196}
197
brians343bc112013-02-10 01:53:46 +0000198} // namespace aos