mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2025-12-30 15:30:28 -06:00
The goal here is to not have constant wakeups due to timeout. Do not attempt to clean things up nicely before termination -- just terminate instead. We can setup a proper termination system in the future, I first want to see if this makes a difference. Also, change xmon to use pipes for communication, so that it can wait without timers as well. Also, `write` directly for logging, so that we know the logs will make it to the file after the logging call returns (since we now do not have the chance to flush them afterwards).
92 lines
2.6 KiB
C++
92 lines
2.6 KiB
C++
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
#include "Exception.hpp"
|
|
#include "Time.hpp"
|
|
#include "Assert.hpp"
|
|
|
|
std::ostream& operator<<(std::ostream& out, Duration d) {
|
|
if (d.ns < 1'000) {
|
|
out << d.ns << "ns";
|
|
} else if (d.ns < 1'000'000) {
|
|
out << d.ns/1'000 << "." << d.ns%1'000 << "us";
|
|
} else if (d.ns < 1'000'000'000) {
|
|
out << d.ns/1'000'000 << "." << d.ns%1'000'000 << "ms";
|
|
} else if (d.ns < 1'000'000'000ull*60) {
|
|
out << d.ns/1'000'000'000 << "." << d.ns%1'000'000'000 << "s";
|
|
} else if (d.ns < 1'000'000'000ull*60*60) {
|
|
out << d.ns/(1'000'000'000ull*60) << "." << d.ns%(1'000'000'000ull*60) << "m";
|
|
} else {
|
|
out << d.ns/(1'000'000'000ull*60*60) << "." << d.ns%(1'000'000'000ull*60*60) << "h";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
void Duration::sleepRetry() const {
|
|
struct timespec ts = timespec();
|
|
for (;;) {
|
|
int ret = nanosleep(&ts, &ts);
|
|
if (likely(ret == 0)) {
|
|
return;
|
|
}
|
|
if (likely(errno == EINTR)) {
|
|
continue;
|
|
}
|
|
throw SYSCALL_EXCEPTION("nanosleep");
|
|
}
|
|
}
|
|
|
|
Duration Duration::sleep() const {
|
|
struct timespec ts = timespec();
|
|
int ret = nanosleep(&ts, &ts);
|
|
if (likely(ret == 0)) {
|
|
return 0;
|
|
}
|
|
if (likely(errno == EINTR)) {
|
|
return Duration(ts);
|
|
}
|
|
throw SYSCALL_EXCEPTION("nanosleep");
|
|
}
|
|
|
|
__attribute__((constructor))
|
|
static void checkClockRes() {
|
|
struct timespec ts;
|
|
if (clock_getres(CLOCK_REALTIME, &ts) != 0) {
|
|
throw SYSCALL_EXCEPTION("clock_getres");
|
|
}
|
|
if (ts.tv_sec != 0 || ts.tv_nsec != 1) {
|
|
throw EGGS_EXCEPTION("expected nanosecond precisions, got %s,%s", ts.tv_sec, ts.tv_nsec);
|
|
}
|
|
}
|
|
|
|
EggsTime eggsNow() {
|
|
struct timespec now;
|
|
|
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0) {
|
|
throw SYSCALL_EXCEPTION("clock_gettime");
|
|
}
|
|
|
|
return EggsTime(((uint64_t)now.tv_nsec + ((uint64_t)now.tv_sec * 1'000'000'000ull)));
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out, EggsTime eggst) {
|
|
time_t secs = eggst.ns / 1'000'000'000ull;
|
|
uint64_t nsecs = eggst.ns % 1'000'000'000ull;
|
|
struct tm tm;
|
|
if (gmtime_r(&secs, &tm) == nullptr) {
|
|
throw SYSCALL_EXCEPTION("gmtime_r");
|
|
}
|
|
// "2006-01-02T15:04:05.999999999"
|
|
char buf[31];
|
|
ALWAYS_ASSERT(strftime(buf, 29, "%Y-%m-%dT%H:%M:%S.", &tm) == 20);
|
|
ALWAYS_ASSERT(snprintf(buf+20, 10, "%09lu", nsecs) == 9);
|
|
buf[30] = '\0';
|
|
out << buf;
|
|
return out;
|
|
}
|
|
|
|
void sleepFor(Duration dt) {
|
|
std::this_thread::sleep_for(std::chrono::nanoseconds(dt.ns));
|
|
} |