* main program for realtime control
*/
+#include <sys/resource.h>
+
#include "realtime.h"
const char *progname= "realtime";
serial_transmit_now(pi->d, pi->l);
}
+/*---------- reporting page faults etc. ----------*/
+
+#define CHECK_RUSAGE_FIELDS(F) \
+ F(ru_majflt) \
+ F(ru_nswap) \
+ F(ru_nivcsw)
+
+/* F(ru_minflt) \
+ */
+
+#define CRF_DECL(f) static long check_rusage_last_##f;
+CHECK_RUSAGE_FIELDS(CRF_DECL)
+
+static void getru(struct rusage *ru) {
+ int r= getrusage(RUSAGE_SELF, ru); if (r) diee("getrusage");
+}
+
+void check_rusage_baseline(void) {
+ struct rusage ru;
+ getru(&ru);
+ #define CRF_BASE(f) check_rusage_last_##f= ru.f;
+ CHECK_RUSAGE_FIELDS(CRF_BASE)
+}
+
+static void check_rusage_field(const char *f, long *last, long this, int alw) {
+ long diff= this - *last;
+ if (alw || diff) {
+ ouprintf(" %s+=%ld", f, diff);
+ *last= diff;
+ }
+}
+
+void check_rusage_check(int always_report) {
+ struct rusage ru;
+ getru(&ru);
+ #define CRF_CHANGED(f) || ru.f != check_rusage_last_##f
+ if (always_report
+ CHECK_RUSAGE_FIELDS(CRF_CHANGED)) {
+ ouprintf("info rusage :");
+ #define CRF_SHOW(f) \
+ check_rusage_field(STR(f), &check_rusage_last_##f, ru.f, always_report);
+ CHECK_RUSAGE_FIELDS(CRF_SHOW);
+ ouprintf(".\n");
+ }
+}
+
/*---------- debugging ----------*/
unsigned long eventcounter;
case 'P': rtfeats_use |= RTFEAT_ALL(CPU); break;
case 'm': rtfeats_use |= RTFEAT_MEM; break;
case 'M': rtfeats_use |= RTFEAT_ALL(MEM); break;
+ case 'r': rtfeats_use |= RTFEAT_RUSAGE; break;
default: badusage("unknown -R suboption");
}
}
events->on_fd(events, serial_fd, OOP_EXCEPTION, read_exception, 0);
if (rtfeats_use & RTFEAT_DEFAULTS)
- rtfeats_use |= RTFEAT_CPU | RTFEAT_MEM;
+ rtfeats_use |= RTFEAT_CPU | RTFEAT_MEM | RTFEAT_RUSAGE;
} else {
sim_initialise(logcopy_fn);
sys_events= 0;
void command_doline(ParseState *ps, CommandInput *cmdi_arg);
const CmdInfo *current_cmd;
+void check_rusage_baseline(void);
+void check_rusage_check(int always_report);
+
/*---------- for/from simulate.c ----------*/
void serial_indata_process(int buf_used);
void realtime_priority(void);
-#define RTFEAT_DEFAULTS 0100u /* turns on MLOCK and SCHEDPRIO iff not sim */
+#define RTFEAT_DEFAULTS 0100u /* turns things on iff not sim */
#define RTFEAT_MEM 0001u /* mlock */
#define RTFEAT_CPU 0002u /* hard CPU scheduling priority */
+#define RTFEAT_RUSAGE 0004u /* check up on faults etc. in getrusage */
#define RTFEAT_ALL_SHIFT 16
#define RTFEAT_ALL(x) (RTFEAT_##x << RTFEAT_ALL_SHIFT)
static PicInsn watchdog_piob;
static void watchdog_transmit(TimeoutEvent *toev) {
+ check_rusage_check(0);
toev_start(&watchdog_toev);
serial_transmit(&watchdog_piob);
}
static void watchdog_start(void) {
+ check_rusage_baseline();
watchdog_toev.callback= watchdog_transmit;
enco_pic_watchdog(&watchdog_piob, UNMARGIN_WATCHDOG_16);
watchdog_transmit(0);
toev_stop(&watchdog_toev);
enco_pic_watchdog(&watchdog_piob, 0);
serial_transmit(&watchdog_piob);
+ check_rusage_check(1);
}
/*---------- main startup algorithm ----------*/
void on_pic_wtimeout(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
if (sta_state <= Sta_Settling) return;
+ check_rusage_check(1);
die("microcontrollers' watchdog timer triggered\n");
}