blob: 6a80550f15ec3d9e57b099a855d013b8cf470567 [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
36void SetSoftRLimit(int resource, rlim64_t soft, bool set_for_root) {
37 bool am_root = getuid() == 0;
38 if (set_for_root || !am_root) {
39 struct rlimit64 rlim;
40 PCHECK(getrlimit64(resource, &rlim) == 0)
41 << ": " << program_invocation_short_name << "-init: getrlimit64("
42 << resource << ") failed";
43
44 rlim.rlim_cur = soft;
45 rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
46
47 PCHECK(setrlimit64(resource, &rlim) == 0)
48 << ": " << program_invocation_short_name << "-init: setrlimit64("
49 << resource << ", {cur=" << (uintmax_t)rlim.rlim_cur
50 << ",max=" << (uintmax_t)rlim.rlim_max << "}) failed";
51 }
52}
53
54} // namespace
55
56void LockAllMemory() {
57 // Allow locking as much as we want into RAM.
58 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, false);
59
60 WriteCoreDumps();
61 PCHECK(mlockall(MCL_CURRENT | MCL_FUTURE) == 0)
62 << ": " << program_invocation_short_name << "-init: mlockall failed";
63
64 // Don't give freed memory back to the OS.
65 CHECK_EQ(1, mallopt(M_TRIM_THRESHOLD, -1));
66 // Don't use mmap for large malloc chunks.
67 CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
68
69 if (&FLAGS_tcmalloc_release_rate) {
70 // Tell tcmalloc not to return memory.
71 FLAGS_tcmalloc_release_rate = 0.0;
72 }
73
74 // Forces the memory pages for all the stack space that we're ever going to
75 // use to be loaded into memory (so it can be locked there).
76 uint8_t data[4096 * 8];
77 // Not 0 because linux might optimize that to a 0-filled page.
78 memset(data, 1, sizeof(data));
79
80 static const size_t kHeapPreallocSize = 512 * 1024;
81 char *const heap_data = static_cast<char *>(malloc(kHeapPreallocSize));
82 memset(heap_data, 1, kHeapPreallocSize);
83 free(heap_data);
84}
85
86void InitRT() {
87 LockAllMemory();
88
89 // Only let rt processes run for 3 seconds straight.
90 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
91
92 // Allow rt processes up to priority 40.
93 SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
94}
95
96void UnsetCurrentThreadRealtimePriority() {
97 struct sched_param param;
98 param.sched_priority = 0;
99 PCHECK(sched_setscheduler(0, SCHED_OTHER, &param) == 0)
100 << ": sched_setscheduler(0, SCHED_OTHER, 0) failed";
101}
102
103void SetCurrentThreadName(const ::std::string &name) {
104 CHECK_LE(name.size(), 16u) << ": thread name '" << name << "' too long";
105 VLOG(1) << "This thread is changing to '" << name << "'";
106 PCHECK(prctl(PR_SET_NAME, name.c_str()) == 0);
107 if (&logging::internal::ReloadThreadName != nullptr) {
108 logging::internal::ReloadThreadName();
109 }
110}
111
112void SetCurrentThreadRealtimePriority(int priority) {
113 // Make sure we will only be allowed to run for 3 seconds straight.
114 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
115
116 struct sched_param param;
117 param.sched_priority = priority;
118 PCHECK(sched_setscheduler(0, SCHED_FIFO, &param) == 0)
119 << ": sched_setscheduler(0, SCHED_FIFO, " << priority << ") failed";
120}
121
122void WriteCoreDumps() {
123 // Do create core files of unlimited size.
124 SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, true);
125}
126
127} // namespace aos