blob: 7eecde3a8755f34b7048a440e2c35df0d5cf5888 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include "aos/atom_code/init.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 <asm-generic/resource.h> // for RLIMIT_RTTIME
10#include <sys/types.h>
11#include <unistd.h>
12#include <stdlib.h>
13#include <stdint.h>
14
brians343bc112013-02-10 01:53:46 +000015#include "aos/common/die.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080016#include "aos/atom_code/logging/atom_logging.h"
17#include "aos/atom_code/ipc_lib/shared_mem.h"
brians343bc112013-02-10 01:53:46 +000018
19namespace aos {
20
21namespace {
22
23void SetSoftRLimit(int resource, rlim64_t soft) {
24 // If we're root, then we don't need to change the soft limits because none of
25 // the ones we care about get checked for root.
26 if (getuid() != 0) {
27 struct rlimit64 rlim;
28 if (getrlimit64(resource, &rlim) == -1) {
29 Die("%s-init: getrlimit64(%d) failed with %d (%s)\n",
30 program_invocation_short_name, resource, errno, strerror(errno));
31 }
32 rlim.rlim_cur = soft;
33 if (setrlimit64(resource, &rlim) == -1) {
34 Die("%s-init: setrlimit64(%d, {cur=%jd,max=%jd})"
35 " failed with %d (%s)\n", program_invocation_short_name,
36 resource, (intmax_t)rlim.rlim_cur, (intmax_t)rlim.rlim_max,
37 errno, strerror(errno));
38 }
39 }
40}
41
42// Common stuff that needs to happen at the beginning of both the realtime and
43// non-realtime initialization sequences. May be called twice.
44void InitStart() {
45 // Allow locking as much as we want into RAM.
46 SetSoftRLimit(RLIMIT_MEMLOCK, RLIM_INFINITY);
47}
48
49int LockAllMemory() {
50 InitStart();
51 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
52 Die("%s-init: mlockall failed with %d (%s)\n",
53 program_invocation_short_name, errno, strerror(errno));
54 }
55
56 // Forces the memory pages for all the stack space that we're ever going to
57 // use to be loaded into memory (so it can be locked there).
58 uint8_t data[4096 * 8];
59 // Not 0 because linux might optimize that to a 0-filled page.
60 memset(data, 1, sizeof(data));
61
62 return 0;
63}
64
65// Do the initialization code that is necessary for both realtime and
66// non-realtime processes.
67void DoInitNRT(aos_core_create create) {
68 InitStart();
69 if (aos_core_create_shared_mem(create)) {
70 Die("%s-init: creating shared memory reference failed\n",
71 program_invocation_short_name);
72 }
Brian Silvermanf665d692013-02-17 22:11:39 -080073 logging::atom::Register();
brians343bc112013-02-10 01:53:46 +000074}
75
76const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
77
78} // namespace
79
80void InitNRT() { DoInitNRT(aos_core_create::reference); }
81void InitCreate() { DoInitNRT(aos_core_create::create); }
82void Init() {
83 if (getenv(kNoRealtimeEnvironmentVariable) == NULL) { // if nobody set it
84 LockAllMemory();
85 // Only let rt processes run for 1 second straight.
86 SetSoftRLimit(RLIMIT_RTTIME, 1000000);
87 // Allow rt processes up to priority 40.
88 SetSoftRLimit(RLIMIT_RTPRIO, 40);
89 // Set our process to priority 40.
90 struct sched_param param;
91 param.sched_priority = 40;
92 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
93 Die("%s-init: setting SCHED_FIFO failed with %d (%s)\n",
94 program_invocation_short_name, errno, strerror(errno));
95 }
96 } else {
97 fprintf(stderr, "%s not doing realtime initialization because environment"
98 " variable %s is set\n", program_invocation_short_name,
99 kNoRealtimeEnvironmentVariable);
100 printf("no realtime for %s. see stderr\n", program_invocation_short_name);
101 }
102
103 InitNRT();
104}
105
106void Cleanup() {
107 if (aos_core_free_shared_mem()) {
108 Die("%s-init: freeing shared mem failed\n",
109 program_invocation_short_name);
110 }
111}
112
113} // namespace aos