Skip to content

Commit

Permalink
refactor: reimplement a portable OS time function
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Nov 11, 2023
1 parent 2ac96c2 commit 2fe96e2
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ HASH_LIBS=

#DEFS+= -DMT_ALL_DIRTY

WARNS=-W -Wall -pedantic
WARNS=-Wall -Wpedantic

# Place our include directories before the system's
INCS+= \
Expand Down Expand Up @@ -249,7 +249,7 @@ EMPTY:=
SPACE:=$(EMPTY) $(EMPTY)
CLANG_TIDY_HEADER_FILTER=$(PWD)/($(subst $(SPACE),|,$(LINTER_HEADERS)))

CXXFLAGS+=$(OPTFLAGS) -std=c++17 -fvisibility=hidden -fPIC -MMD $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(WARNS)
CXXFLAGS+=$(OPTFLAGS) -std=gnu++17 -fvisibility=hidden -fPIC -MMD $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(WARNS)
CFLAGS+=$(OPTFLAGS) -std=gnu99 -fvisibility=hidden -fPIC -MMD $(CC_MARCH) $(INCS) $(GCFLAGS) $(UBFLAGS) $(DEFS) $(WARNS)
LDFLAGS+=$(UBFLAGS)

Expand Down
2 changes: 1 addition & 1 deletion src/interpret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5324,7 +5324,7 @@ static FORCE_INLINE execute_status execute_insn(STATE_ACCESS &a, uint64_t &pc, u
return execute_ADDW_MULW_SUBW(a, pc, insn);
case insn_funct3_00000_opcode::SRLW_DIVUW_SRAW:
return execute_SRLW_DIVUW_SRAW(a, pc, insn);
case insn_funct3_00000_opcode::privileged:
case insn_funct3_00000_opcode::PRIVILEGED:
return execute_privileged(a, pc, mcycle, insn);
default: {
// Here we are sure that the next instruction, at best, can only be a floating point instruction,
Expand Down
65 changes: 58 additions & 7 deletions src/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#define HAVE_MMAP
#endif

#if !defined(_WIN32) && !defined(NO_MKDIR)
#define HAVE_MKDIR
#endif

#include <array>
#include <cstdint>
#include <cstdio>
Expand Down Expand Up @@ -57,7 +61,17 @@
#include <windows.h>
#endif

#include <sys/stat.h> // fstat
#if defined(HAVE_MMAP) || defined(HAVE_MKDIR) || defined(_WIN32)
#include <sys/stat.h> // fstat/mkdir
#endif

#include <ctime> // clock_gettime

#if defined(_POSIX_TIMERS) && defined(CLOCK_MONOTONIC) && !defined(NO_CLOCK_GETTTIME)
#define HAVE_MONOTONIC_CLOCK_GETTIME
#else
#include <sys/time.h> // gettimeofday
#endif

namespace cartesi {

Expand Down Expand Up @@ -183,21 +197,22 @@ void os_open_tty(void) {

void os_close_tty(void) {
#ifdef HAVE_TTY
auto *s = get_state();

#ifdef HAVE_TERMIOS
auto *s = get_state();
if (s->ttyfd >= 0) { // Restore old mode
tcsetattr(s->ttyfd, TCSANOW, &s->oldtty);
close(s->ttyfd);
s->ttyfd = 1;
}

#elif defined(_WIN32)
auto *s = get_state();
if (s->hStdin) {
SetConsoleMode(s->hStdin, s->dwOldStdinMode);
s->hStdin = NULL;
}
#endif // HAVE_TERMIOS

#endif // HAVE_TERMIOS
#endif // HAVE_TTY
}

Expand Down Expand Up @@ -316,12 +331,14 @@ void os_putchar(uint8_t ch) {
}

int os_mkdir(const char *path, int mode) {
#ifdef _WIN32
#ifdef HAVE_MKDIR
return mkdir(path, mode);
#elif defined(_WIN32)
(void) mode;
return _mkdir(path);
#else
return mkdir(path, mode);
#endif
return -1;
#endif // HAVE_MKDIR
}

unsigned char *os_map_file(const char *path, uint64_t length, bool shared) {
Expand Down Expand Up @@ -470,4 +487,38 @@ void os_unmap_file(unsigned char *host_memory, uint64_t length) {
#endif // HAVE_MMAP
}

int64_t os_now_us() {
#ifdef HAVE_MONOTONIC_CLOCK_GETTIME
// Prefer using a monolithic clock with clock_gettime(), because time can't jump.
static bool initialized = false;
static struct timespec start {};
if (!initialized) {
clock_gettime(CLOCK_MONOTONIC, &start);
initialized = true;
return 0;
} else {
struct timespec t {};
clock_gettime(CLOCK_MONOTONIC, &t);
return static_cast<int64_t>(t.tv_sec - start.tv_sec) * 1000000 +
static_cast<int64_t>(t.tv_nsec - start.tv_nsec) / 1000;
}

#else
// Fallback to gettimeofday(), note that time can jump in case administrator changes time.
static bool initialized = false;
static struct timeval start {};
if (!initialized) {
gettimeofday(&start, NULL);
initialized = true;
return 0;
} else {
struct timeval t;
gettimeofday(&t, NULL);
return static_cast<int64_t>(t.tv_sec - start.tv_sec) * 1000000000 +
static_cast<int64_t>(t.tv_usec - start.tv_usec) * 1000;
}

#endif // HAVE_MONOTONIC_CLOCK_GETTIME
}

} // namespace cartesi
3 changes: 3 additions & 0 deletions src/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ unsigned char *os_map_file(const char *path, uint64_t length, bool shared);
/// \brief Unmaps a file from memory
void os_unmap_file(unsigned char *host_memory, uint64_t length);

/// \brief Get time elapsed since its first call with microsecond precision
int64_t os_now_us();

} // namespace cartesi

#endif
2 changes: 1 addition & 1 deletion src/riscv-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ enum class insn_funct3_00000_opcode : uint32_t {
AND_REMU = 0b111000000110011,
ADDW_MULW_SUBW = 0b000000000111011,
SRLW_DIVUW_SRAW = 0b101000000111011,
privileged = 0b000000001110011,
PRIVILEGED = 0b000000001110011,
};

/// \brief The result of insn >> 26 (6 most significant bits of funct7) can be
Expand Down
8 changes: 3 additions & 5 deletions src/state-access.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,12 +406,10 @@ class state_access : public i_state_access<state_access, pma_entry> {
if (warp_cycle > mcycle) {
constexpr uint64_t cycles_per_us = RTC_CLOCK_FREQ / 1000000; // CLOCK_FREQ / 10^6
const uint64_t wait = (warp_cycle - mcycle) / cycles_per_us;
timeval start{};
timeval end{};
gettimeofday(&start, nullptr);
int64_t start = os_now_us();
os_poll_tty(wait);
gettimeofday(&end, nullptr);
const uint64_t elapsed_us = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec;
int64_t end = os_now_us();
const uint64_t elapsed_us = static_cast<uint64_t>(std::max(end - start, INT64_C(0)));
const uint64_t tty_cycle = mcycle + (elapsed_us * cycles_per_us);
mcycle = std::min(std::max(tty_cycle, mcycle), warp_cycle);
}
Expand Down

0 comments on commit 2fe96e2

Please sign in to comment.