8 #include <sys/resource.h>
14 /*---------- !ALL(MEM): prevent us eating all RAM ----------*/
16 static void rtf_limit_MEM(void) {
19 r= getrlimit64(RLIMIT_MEMLOCK,&rl); if (r) diee("getrlimit RLIMIT_MEMLOCK");
20 rl.rlim_cur= 4*1024*1024;
21 r= setrlimit64(RLIMIT_MEMLOCK,&rl); if (r) diee("setrlimit RLIMIT_MEMLOCK");
24 /*---------- MEM: lock us into memory ----------*/
26 static void rtf_acquire_MEM(void) {
28 r= mlockall(MCL_CURRENT|MCL_FUTURE); if (r) diee("mlockall");
31 /*---------- !ALL(CPU): use SIGXCPU to detect us spinning ----------*/
33 #define MAX_CPU_CREDIT 5 /* max burst of 5 seconds */
34 #define MAX_CPU_NTH 2 /* allow up to 50% usage, sustained */
36 static time_t now, last;
37 static struct rlimit rlcpu;
38 static struct sigaction sa_xcpu;
40 static void write_stderr(const char *m, int l) { write(2,m,l); }
42 static void cpulim_bomb(const char *what) __attribute__((noreturn));
43 static void cpulim_bomb(const char *what) {
44 static const char m[]= "realtime: cpu limitation failure: ";
49 write_stderr(m,sizeof(m)-1);
50 write_stderr(what,strlen(what));
54 write_stderr(s,strlen(s));
59 static const char *cpulim_gnow(void) { /* returns what failed */
60 if (time(&now) == (time_t)-1) return "time(2)";
64 static const char *cpulim_makepending(void) { /* returns what failed */
67 r= sigaction(SIGXCPU, &sa_xcpu, 0); if (r) return "sigaction SIGXCPU";
68 r= setrlimit(RLIMIT_CPU, &rlcpu); if (r) return "setrlimit RLIMIT_CPU";
72 static void cpulim_exceeded(void) {
73 static const char m[]= "realtime: cpu limit exceeded\n";
74 write_stderr(m,sizeof(m)-1);
79 static void xcpuhandler(int ignored) {
81 const char *whatfailed;
83 whatfailed= cpulim_gnow();
84 if (whatfailed) goto fail;
86 credit= (now - last)/MAX_CPU_NTH;
87 if (credit <= 0) cpulim_exceeded();
88 if (credit > MAX_CPU_CREDIT) credit= MAX_CPU_CREDIT;
89 rlcpu.rlim_cur += credit;
91 whatfailed= cpulim_makepending();
92 if (whatfailed) goto fail;
96 cpulim_bomb(whatfailed);
99 static void rtf_limit_CPU(void) {
101 const char *whatfailed;
103 memset(&sa_xcpu,0,sizeof(sa_xcpu));
104 sa_xcpu.sa_handler= xcpuhandler;
105 sigemptyset(&sa_xcpu.sa_mask);
106 sa_xcpu.sa_flags= SA_RESETHAND | SA_RESTART | SA_NODEFER;
108 r= getrlimit(RLIMIT_CPU, &rlcpu);
109 if (r) { whatfailed= "getrlimit RLIMIT_CPU"; goto fail; }
111 whatfailed= cpulim_gnow();
112 if (whatfailed) goto fail;
114 rlcpu.rlim_cur= MAX_CPU_CREDIT;
116 whatfailed= cpulim_makepending();
117 if (whatfailed) goto fail;
121 diee("prepare cpu limiter: %s",whatfailed);
124 /*---------- CPU: set hard scheduling priority ----------*/
126 static void rtf_acquire_CPU(void) {
130 if (child<0) diee("fork for auth-sched-setscheduler");
133 execlp("auth-sched-setscheduler",
134 "auth-sched-setscheduler","fifo","54",(char*)0);
135 diee("exec auth-sched-setscheduler");
137 mwaitpid(child, "auth-sched-setscheduler");
140 /*---------- core ----------*/
142 unsigned rtfeats_use= RTFEAT_DEFAULTS;
144 void realtime_priority(void) {
145 #define RESOURCE(NAME) \
146 if (rtfeats_use & RTFEAT_##NAME) { \
147 if (!(rtfeats_use & RTFEAT_ALL(NAME))) rtf_limit_##NAME(); \
148 rtf_acquire_##NAME(); \