#include <signal.h> // for signal handling
+#ifdef REALTIME_VERSION
+#include <time.h>
+#include <sched.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+#endif //REALTIME_VERSION
+
// --- Variable definitions --- //
Options g_options; // options passed to program through command line arguments
Log(LOGDEBUG, "Finish cleanup.");
}
+
+#ifdef REALTIME_VERSION
+
+#define MAX_SAFE_STACK (8*1024)
+#define NSEC_PER_SEC (1000000000)
+
+void stack_prefault()
+{
+ unsigned char dummy[MAX_SAFE_STACK];
+ memset(dummy, 0, MAX_SAFE_STACK);
+ return;
+}
+
+bool is_realtime()
+{
+ struct utsname u;
+ bool crit1 = 0;
+ bool crit2 = 0;
+ FILE * f;
+ uname(&u);
+ crit1 = (strcasestr(u.version, "PREEMPT RT") != NULL);
+ if (crit1 && ((f = fopen("/sys/kernel/realtime", "r")) != NULL))
+ {
+ int flag;
+ crit2 = ((fscanf(f, "%d", &flag) == 1) && (flag == 1));
+ fclose(f);
+ }
+ return (crit1 && crit2);
+}
+
+#endif //REALTIME_VERSION
+
/**
* Main entry point; start worker threads, setup signal handling, wait for threads to exit, exit
* @param argc - Num args
*/
int main(int argc, char ** argv)
{
+
// Open log before calling ParseArguments (since ParseArguments may call the Log functions)
openlog("mctxserv", LOG_PID | LOG_PERROR, LOG_USER);
- Log(LOGINFO, "Server started");
ParseArguments(argc, argv); // Setup the g_options structure from program arguments
+ Log(LOGINFO, "Server started");
+
+
+
+ #ifdef REALTIME_VERSION
+
+ if (is_realtime())
+ {
+ Log(LOGDEBUG, "Running under realtime kernel");
+ }
+ else
+ {
+ Fatal("Not running under realtime kernel");
+ }
+ struct sched_param param;
+ param.sched_priority = 49;
+ if (sched_setscheduler(0, SCHED_FIFO, ¶m) < 0)
+ Fatal("sched_setscheduler failed - %s", strerror(errno));
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
+ Fatal("mlockall failed - %s", strerror(errno));
+ stack_prefault();
+ #endif //REALTIME_VERSION
+
+
+
Sensor_Init();
Actuator_Init();
Pin_Init();
s->init = init; // Set init function
// Start by averaging values taken over a second
- s->sample_time.tv_sec = 1;
- s->sample_time.tv_nsec = 0;
+ DOUBLE_TO_TIMEVAL(1e-4, &(s->sample_time));
s->averages = 1;
+ s->num_read = 0;
// Set sanity function
s->sanity = sanity;
Fatal("Couldn't init sensor %s", name);
}
-
+ s->current_data.time_stamp = 0;
+ s->current_data.value = 0;
return g_num_sensors;
}
Fatal("Sensor %s (%d,%d) reads unsafe value", s->name, s->id, s->user_id);
}
}
- Data_Save(&(s->data_file), &d, 1); // Record it
+ s->current_data.time_stamp += d.time_stamp;
+ s->current_data.value += d.value;
+
+ if (++(s->num_read) >= s->averages)
+ {
+ s->current_data.time_stamp /= s->averages;
+ s->current_data.value /= s->averages;
+ Data_Save(&(s->data_file), &(s->current_data), 1); // Record it
+ s->num_read = 0;
+ s->current_data.time_stamp = 0;
+ s->current_data.value = 0;
+ }
}
else
Log(LOGWARN, "Failed to read sensor %s (%d,%d)", s->name, s->id,s->user_id);