blob: a0af97a88dffa2165476c055636717f4b43a94fb [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#include "aos/realtime.h"
2
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>
9#include <sys/types.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <sys/prctl.h>
14#include <malloc.h>
15
16#include "glog/logging.h"
17
18namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
19extern double FLAGS_tcmalloc_release_rate __attribute__((weak));
20}
21using FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead::
22 FLAGS_tcmalloc_release_rate;
23
24namespace aos {
25namespace logging {
26namespace internal {
27
28// Implemented in aos/logging/context.cc.
29void ReloadThreadName() __attribute__((weak));
30
31} // namespace internal
32} // namespace logging
33
34namespace {
35
James Kuszmaulb4874eb2020-01-18 17:50:35 -080036enum class SetLimitForRoot {
37 kYes,
38 kNo
39};
40
41enum class AllowSoftLimitDecrease {
42 kYes,
43 kNo
44};
45
46void SetSoftRLimit(
47 int resource, rlim64_t soft, SetLimitForRoot set_for_root,
48 AllowSoftLimitDecrease allow_decrease = AllowSoftLimitDecrease::kYes) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070049 bool am_root = getuid() == 0;
James Kuszmaulb4874eb2020-01-18 17:50:35 -080050 if (set_for_root == SetLimitForRoot::kYes || !am_root) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070051 struct rlimit64 rlim;
52 PCHECK(getrlimit64(resource, &rlim) == 0)
Brian Silverman6a54ff32020-04-28 16:41:39 -070053 << ": getting limit for " << resource;
Alex Perrycb7da4b2019-08-28 19:35:56 -070054
James Kuszmaulb4874eb2020-01-18 17:50:35 -080055 if (allow_decrease == AllowSoftLimitDecrease::kYes) {
56 rlim.rlim_cur = soft;
57 } else {
58 rlim.rlim_cur = std::max(rlim.rlim_cur, soft);
59 }
Alex Perrycb7da4b2019-08-28 19:35:56 -070060 rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
61
62 PCHECK(setrlimit64(resource, &rlim) == 0)
Brian Silverman6a54ff32020-04-28 16:41:39 -070063 << ": changing limit for " << resource << " to " << rlim.rlim_cur
64 << " with max of " << rlim.rlim_max;
Alex Perrycb7da4b2019-08-28 19:35:56 -070065 }
66}
67
68} // namespace
69
70void LockAllMemory() {
71 // Allow locking as much as we want into RAM.
James Kuszmaulb4874eb2020-01-18 17:50:35 -080072 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, SetLimitForRoot::kNo);
Alex Perrycb7da4b2019-08-28 19:35:56 -070073
74 WriteCoreDumps();
Brian Silverman6a54ff32020-04-28 16:41:39 -070075 PCHECK(mlockall(MCL_CURRENT | MCL_FUTURE) == 0);
Alex Perrycb7da4b2019-08-28 19:35:56 -070076
Austin Schuh85faf672020-09-10 22:58:46 -070077#if !__has_feature(address_sanitizer)
Alex Perrycb7da4b2019-08-28 19:35:56 -070078 // Don't give freed memory back to the OS.
79 CHECK_EQ(1, mallopt(M_TRIM_THRESHOLD, -1));
80 // Don't use mmap for large malloc chunks.
81 CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
Austin Schuh85faf672020-09-10 22:58:46 -070082#endif
Alex Perrycb7da4b2019-08-28 19:35:56 -070083
84 if (&FLAGS_tcmalloc_release_rate) {
85 // Tell tcmalloc not to return memory.
86 FLAGS_tcmalloc_release_rate = 0.0;
87 }
88
89 // Forces the memory pages for all the stack space that we're ever going to
90 // use to be loaded into memory (so it can be locked there).
91 uint8_t data[4096 * 8];
92 // Not 0 because linux might optimize that to a 0-filled page.
93 memset(data, 1, sizeof(data));
Lee Mracek6afc0ac2020-03-06 12:42:33 -050094 __asm__ __volatile__("" :: "m" (data));
Alex Perrycb7da4b2019-08-28 19:35:56 -070095
96 static const size_t kHeapPreallocSize = 512 * 1024;
97 char *const heap_data = static_cast<char *>(malloc(kHeapPreallocSize));
98 memset(heap_data, 1, kHeapPreallocSize);
Lee Mracek6afc0ac2020-03-06 12:42:33 -050099 __asm__ __volatile__("" :: "m" (heap_data));
Alex Perrycb7da4b2019-08-28 19:35:56 -0700100 free(heap_data);
101}
102
103void InitRT() {
104 LockAllMemory();
105
106 // Only let rt processes run for 3 seconds straight.
James Kuszmaulb4874eb2020-01-18 17:50:35 -0800107 SetSoftRLimit(RLIMIT_RTTIME, 3000000, SetLimitForRoot::kYes);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700108
109 // Allow rt processes up to priority 40.
James Kuszmaulb4874eb2020-01-18 17:50:35 -0800110 SetSoftRLimit(RLIMIT_RTPRIO, 40, SetLimitForRoot::kNo);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111}
112
113void UnsetCurrentThreadRealtimePriority() {
114 struct sched_param param;
115 param.sched_priority = 0;
Brian Silverman6a54ff32020-04-28 16:41:39 -0700116 PCHECK(sched_setscheduler(0, SCHED_OTHER, &param) == 0);
117}
118
119void SetCurrentThreadAffinity(const cpu_set_t &cpuset) {
120 PCHECK(sched_setaffinity(0, sizeof(cpuset), &cpuset) == 0);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700121}
122
James Kuszmaul57c2baa2020-01-19 14:52:52 -0800123void SetCurrentThreadName(const std::string_view name) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700124 CHECK_LE(name.size(), 16u) << ": thread name '" << name << "' too long";
125 VLOG(1) << "This thread is changing to '" << name << "'";
James Kuszmaul57c2baa2020-01-19 14:52:52 -0800126 std::string string_name(name);
Brian Silverman6a54ff32020-04-28 16:41:39 -0700127 PCHECK(prctl(PR_SET_NAME, string_name.c_str()) == 0)
128 << ": changing name to " << string_name;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700129 if (&logging::internal::ReloadThreadName != nullptr) {
130 logging::internal::ReloadThreadName();
131 }
132}
133
134void SetCurrentThreadRealtimePriority(int priority) {
135 // Make sure we will only be allowed to run for 3 seconds straight.
James Kuszmaulb4874eb2020-01-18 17:50:35 -0800136 SetSoftRLimit(RLIMIT_RTTIME, 3000000, SetLimitForRoot::kYes);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700137
Brian Silvermanb3826f52020-07-02 19:41:18 -0700138 // Raise our soft rlimit if necessary.
139 SetSoftRLimit(RLIMIT_RTPRIO, priority, SetLimitForRoot::kNo,
140 AllowSoftLimitDecrease::kNo);
141
Alex Perrycb7da4b2019-08-28 19:35:56 -0700142 struct sched_param param;
143 param.sched_priority = priority;
144 PCHECK(sched_setscheduler(0, SCHED_FIFO, &param) == 0)
Brian Silverman6a54ff32020-04-28 16:41:39 -0700145 << ": changing to SCHED_FIFO with " << priority;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700146}
147
148void WriteCoreDumps() {
149 // Do create core files of unlimited size.
James Kuszmaulb4874eb2020-01-18 17:50:35 -0800150 SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, SetLimitForRoot::kYes);
151}
152
153void ExpandStackSize() {
154 SetSoftRLimit(RLIMIT_STACK, 1000000, SetLimitForRoot::kYes,
155 AllowSoftLimitDecrease::kNo);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700156}
157
158} // namespace aos