blob: 4f153e90c9b22cf9898dff51840f9971748d505f [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>
brians343bc112013-02-10 01:53:46 +000014
brians343bc112013-02-10 01:53:46 +000015#include "aos/common/die.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -080016#include "aos/linux_code/logging/linux_logging.h"
17#include "aos/linux_code/ipc_lib/shared_mem.h"
brians343bc112013-02-10 01:53:46 +000018
19namespace aos {
Brian Silverman2fe007c2014-12-28 12:20:01 -080020namespace logging {
21namespace internal {
brians343bc112013-02-10 01:53:46 +000022
Brian Silverman2fe007c2014-12-28 12:20:01 -080023// Implemented in aos/linux_code/logging/linux_interface.cc.
24void ReloadThreadName();
25
26} // namespace internal
27} // namespace logging
brians343bc112013-02-10 01:53:46 +000028namespace {
29
Brian Silverman80353cb2013-03-19 18:27:53 -070030void SetSoftRLimit(int resource, rlim64_t soft, bool set_for_root) {
31 bool am_root = getuid() == 0;
32 if (set_for_root || !am_root) {
brians343bc112013-02-10 01:53:46 +000033 struct rlimit64 rlim;
34 if (getrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070035 PDie("%s-init: getrlimit64(%d) failed",
36 program_invocation_short_name, resource);
brians343bc112013-02-10 01:53:46 +000037 }
38 rlim.rlim_cur = soft;
Austin Schuh6c7edbf2014-10-21 22:26:58 -070039 rlim.rlim_max = ::std::max(rlim.rlim_max, soft);
40
brians343bc112013-02-10 01:53:46 +000041 if (setrlimit64(resource, &rlim) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070042 PDie("%s-init: setrlimit64(%d, {cur=%ju,max=%ju}) failed",
43 program_invocation_short_name, resource, (uintmax_t)rlim.rlim_cur,
44 (uintmax_t)rlim.rlim_max);
brians343bc112013-02-10 01:53:46 +000045 }
46 }
47}
48
49// Common stuff that needs to happen at the beginning of both the realtime and
50// non-realtime initialization sequences. May be called twice.
51void InitStart() {
Brian Silvermanff485782014-06-18 19:59:09 -070052 ::aos::logging::Init();
brians343bc112013-02-10 01:53:46 +000053 // Allow locking as much as we want into RAM.
Brian Silverman80353cb2013-03-19 18:27:53 -070054 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY, false);
Brian Silvermanfe1ef172014-04-12 17:12:45 -070055 WriteCoreDumps();
brians343bc112013-02-10 01:53:46 +000056}
57
Brian Silverman6da04272014-05-18 18:47:48 -070058void LockAllMemory() {
brians343bc112013-02-10 01:53:46 +000059 InitStart();
60 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070061 PDie("%s-init: mlockall failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +000062 }
63
64 // Forces the memory pages for all the stack space that we're ever going to
65 // use to be loaded into memory (so it can be locked there).
66 uint8_t data[4096 * 8];
67 // Not 0 because linux might optimize that to a 0-filled page.
68 memset(data, 1, sizeof(data));
brians343bc112013-02-10 01:53:46 +000069}
70
71// Do the initialization code that is necessary for both realtime and
72// non-realtime processes.
73void DoInitNRT(aos_core_create create) {
74 InitStart();
Brian Silverman01be0002014-05-10 15:44:38 -070075 aos_core_create_shared_mem(create);
Brian Silverman14fd0fb2014-01-14 21:42:01 -080076 logging::linux_code::Register();
brians343bc112013-02-10 01:53:46 +000077}
78
79const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
80
81} // namespace
82
83void InitNRT() { DoInitNRT(aos_core_create::reference); }
84void InitCreate() { DoInitNRT(aos_core_create::create); }
Brian Silvermanf3cfbd72013-10-28 16:26:09 -070085void Init(int relative_priority) {
brians343bc112013-02-10 01:53:46 +000086 if (getenv(kNoRealtimeEnvironmentVariable) == NULL) { // if nobody set it
87 LockAllMemory();
Brian Silverman6da04272014-05-18 18:47:48 -070088
Brian Silverman8dc9fd42014-02-10 13:35:43 -080089 // Only let rt processes run for 3 seconds straight.
90 SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
Brian Silverman6da04272014-05-18 18:47:48 -070091
brians343bc112013-02-10 01:53:46 +000092 // Allow rt processes up to priority 40.
Brian Silverman80353cb2013-03-19 18:27:53 -070093 SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
Brian Silverman6da04272014-05-18 18:47:48 -070094
95 // Set our process to the appropriate priority.
brians343bc112013-02-10 01:53:46 +000096 struct sched_param param;
Brian Silvermanf3cfbd72013-10-28 16:26:09 -070097 param.sched_priority = 30 + relative_priority;
brians343bc112013-02-10 01:53:46 +000098 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
Brian Silverman01be0002014-05-10 15:44:38 -070099 PDie("%s-init: setting SCHED_FIFO failed", program_invocation_short_name);
brians343bc112013-02-10 01:53:46 +0000100 }
101 } else {
102 fprintf(stderr, "%s not doing realtime initialization because environment"
103 " variable %s is set\n", program_invocation_short_name,
104 kNoRealtimeEnvironmentVariable);
105 printf("no realtime for %s. see stderr\n", program_invocation_short_name);
106 }
107
108 InitNRT();
109}
110
111void Cleanup() {
Brian Silverman01be0002014-05-10 15:44:38 -0700112 aos_core_free_shared_mem();
brians343bc112013-02-10 01:53:46 +0000113}
114
Brian Silvermanfe1ef172014-04-12 17:12:45 -0700115void WriteCoreDumps() {
116 // Do create core files of unlimited size.
117 SetSoftRLimit(RLIMIT_CORE, RLIM_INFINITY, true);
118}
119
Brian Silvermanda45b6c2014-12-28 11:36:50 -0800120void SetCurrentThreadRealtimePriority(int priority) {
121 struct sched_param param;
122 param.sched_priority = priority;
123 if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
124 PLOG(FATAL, "sched_setscheduler(0, SCHED_FIFO, %d) failed", priority);
125 }
126}
127
Brian Silverman2fe007c2014-12-28 12:20:01 -0800128void SetCurrentThreadName(const ::std::string &name) {
129 if (name.size() > 16) {
130 LOG(FATAL, "thread name '%s' too long\n", name.c_str());
131 }
132 LOG(INFO, "this thread is changing to '%s'\n", name.c_str());
133 PCHECK(prctl(PR_SET_NAME, name.c_str()));
134 logging::internal::ReloadThreadName();
135}
136
brians343bc112013-02-10 01:53:46 +0000137} // namespace aos