diff options
author | Alexander Richardson <alexrichardson@google.com> | 2023-06-15 06:28:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-15 08:28:49 -0500 |
commit | 9b477812019a78510ebc7f4c7b7efbf378e64a42 (patch) | |
tree | c338d406fff3c7a06df1a24c1ce895fa6f21b1fd /c_emulator/riscv_sim.c | |
parent | 2d214136ce4da767d926bc18ff53478181bc729b (diff) | |
download | sail-riscv-9b477812019a78510ebc7f4c7b7efbf378e64a42.zip sail-riscv-9b477812019a78510ebc7f4c7b7efbf378e64a42.tar.gz sail-riscv-9b477812019a78510ebc7f4c7b7efbf378e64a42.tar.bz2 |
Add a clang-format configuration and reformat C code (#261)
* Add a clang-format configuration and reformat C code
From my testing it turns out the built-in WebKit style is the closest to
the current style. I added a few config options to further reduce the
diff and I think the current output looks reasonable.
In the future it would be good to add a CI and pre-commit check to enforce
that all C code is consistently formatted to reduce the need for reviewers
to look for formatting issues.
* Fix formatting of commented-out reservation debug code
Use an empty-by-default macro instead of commented-out fprintf calls.
This way clang-format can format the calls sensibly and it's easier
to enable the debug prints.
* Improve formatting of fprintf call in set_config_print()
Clang-format does not like long string literals, so split this manually
to format the call sensibly.
* Fix formatting of function pointer typedef
Clang-format gets this wrong `*` is part of the typedef.
* Improve formatting of getopt_long call
* Fix odd fprintf continuation by splitting long string literal
Diffstat (limited to 'c_emulator/riscv_sim.c')
-rw-r--r-- | c_emulator/riscv_sim.c | 259 |
1 files changed, 153 insertions, 106 deletions
diff --git a/c_emulator/riscv_sim.c b/c_emulator/riscv_sim.c index 9a37c18..fdb9ce0 100644 --- a/c_emulator/riscv_sim.c +++ b/c_emulator/riscv_sim.c @@ -57,7 +57,8 @@ unsigned char *dtb = NULL; size_t dtb_len = 0; #ifdef RVFI_DII static bool rvfi_dii = false; -/* Needs to be global to avoid the needed for a set-version packet on each trace */ +/* Needs to be global to avoid the needed for a set-version packet on each trace + */ static unsigned rvfi_trace_version = 1; static int rvfi_dii_port; static int rvfi_dii_sock; @@ -77,7 +78,8 @@ bool config_print_mem_access = true; bool config_print_platform = true; bool config_print_rvfi = false; -void set_config_print(char *var, bool val) { +void set_config_print(char *var, bool val) +{ if (var == NULL || strcmp("all", var) == 0) { config_print_instr = val; config_print_mem_access = val; @@ -95,7 +97,8 @@ void set_config_print(char *var, bool val) { } else if (strcmp("platform", var) == 0) { config_print_platform = val; } else { - fprintf(stderr, "Unknown trace category: '%s' (should be instr|reg|mem|platform|all)\n", var); + fprintf(stderr, "Unknown trace category: '%s' (should be %s)\n", + "instr|reg|mem|platform|all", var); exit(1); } } @@ -108,39 +111,41 @@ char *sailcov_file = NULL; #endif static struct option options[] = { - {"enable-dirty-update", no_argument, 0, 'd'}, - {"enable-misaligned", no_argument, 0, 'm'}, - {"enable-pmp", no_argument, 0, 'P'}, - {"enable-next", no_argument, 0, 'N'}, - {"ram-size", required_argument, 0, 'z'}, - {"disable-compressed", no_argument, 0, 'C'}, - {"disable-writable-misa", no_argument, 0, 'I'}, - {"disable-fdext", no_argument, 0, 'F'}, - {"mtval-has-illegal-inst-bits", no_argument, 0, 'i'}, - {"device-tree-blob", required_argument, 0, 'b'}, - {"terminal-log", required_argument, 0, 't'}, - {"show-times", required_argument, 0, 'p'}, - {"report-arch", no_argument, 0, 'a'}, - {"test-signature", required_argument, 0, 'T'}, - {"signature-granularity", required_argument, 0, 'g'}, + {"enable-dirty-update", no_argument, 0, 'd'}, + {"enable-misaligned", no_argument, 0, 'm'}, + {"enable-pmp", no_argument, 0, 'P'}, + {"enable-next", no_argument, 0, 'N'}, + {"ram-size", required_argument, 0, 'z'}, + {"disable-compressed", no_argument, 0, 'C'}, + {"disable-writable-misa", no_argument, 0, 'I'}, + {"disable-fdext", no_argument, 0, 'F'}, + {"mtval-has-illegal-inst-bits", no_argument, 0, 'i'}, + {"device-tree-blob", required_argument, 0, 'b'}, + {"terminal-log", required_argument, 0, 't'}, + {"show-times", required_argument, 0, 'p'}, + {"report-arch", no_argument, 0, 'a'}, + {"test-signature", required_argument, 0, 'T'}, + {"signature-granularity", required_argument, 0, 'g'}, #ifdef RVFI_DII - {"rvfi-dii", required_argument, 0, 'r'}, + {"rvfi-dii", required_argument, 0, 'r'}, #endif - {"help", no_argument, 0, 'h'}, - {"trace", optional_argument, 0, 'v'}, - {"no-trace", optional_argument, 0, 'V'}, - {"inst-limit", required_argument, 0, 'l'}, - {"enable-zfinx", no_argument, 0, 'x'}, + {"help", no_argument, 0, 'h'}, + {"trace", optional_argument, 0, 'v'}, + {"no-trace", optional_argument, 0, 'V'}, + {"inst-limit", required_argument, 0, 'l'}, + {"enable-zfinx", no_argument, 0, 'x'}, #ifdef SAILCOV - {"sailcov-file", required_argument, 0, 'c'}, + {"sailcov-file", required_argument, 0, 'c'}, #endif - {0, 0, 0, 0} + {0, 0, 0, 0 } }; static void print_usage(const char *argv0, int ec) { #ifdef RVFI_DII - fprintf(stdout, "Usage: %s [options] <elf_file>\n %s [options] -r <port>\n", argv0, argv0); + fprintf(stdout, + "Usage: %s [options] <elf_file>\n %s [options] -r <port>\n", + argv0, argv0); #else fprintf(stdout, "Usage: %s [options] <elf_file>\n", argv0); #endif @@ -216,7 +221,7 @@ char *process_args(int argc, char **argv) { int c; uint64_t ram_size = 0; - while(true) { + while (true) { c = getopt_long(argc, argv, "a" "d" @@ -238,15 +243,16 @@ char *process_args(int argc, char **argv) #ifdef RVFI_DII "r:" #endif - "V::" - "v::" - "l:" - "x" #ifdef SAILCOV "c:" #endif - , options, NULL); - if (c == -1) break; + "V::" + "v::" + "l:" + "x", + options, NULL); + if (c == -1) + break; switch (c) { case 'a': report_arch(); @@ -314,7 +320,8 @@ char *process_args(int argc, char **argv) break; case 'g': signature_granularity = atoi(optarg); - fprintf(stderr, "setting signature-granularity to %d bytes\n", signature_granularity); + fprintf(stderr, "setting signature-granularity to %d bytes\n", + signature_granularity); break; case 'h': print_usage(argv[0], 0); @@ -350,21 +357,24 @@ char *process_args(int argc, char **argv) break; } } - if (do_dump_dts) dump_dts(); + if (do_dump_dts) + dump_dts(); #ifdef RVFI_DII - if (optind > argc || (optind == argc && !rvfi_dii)) print_usage(argv[0], 0); + if (optind > argc || (optind == argc && !rvfi_dii)) + print_usage(argv[0], 0); #else if (optind >= argc) { fprintf(stderr, "No elf file provided.\n"); print_usage(argv[0], 0); } #endif - if (dtb_file) read_dtb(dtb_file); + if (dtb_file) + read_dtb(dtb_file); #ifdef RVFI_DII if (!rvfi_dii) #endif - fprintf(stdout, "Running file %s.\n", argv[optind]); + fprintf(stdout, "Running file %s.\n", argv[optind]); return argv[optind]; } @@ -372,12 +382,14 @@ void check_elf(bool is32bit) { if (is32bit) { if (zxlen_val != 32) { - fprintf(stderr, "32-bit ELF not supported by RV%" PRIu64 " model.\n", zxlen_val); + fprintf(stderr, "32-bit ELF not supported by RV%" PRIu64 " model.\n", + zxlen_val); exit(1); } } else { if (zxlen_val != 64) { - fprintf(stderr, "64-bit ELF not supported by RV%" PRIu64 " model.\n", zxlen_val); + fprintf(stderr, "64-bit ELF not supported by RV%" PRIu64 " model.\n", + zxlen_val); exit(1); } } @@ -416,22 +428,28 @@ void init_spike(const char *f, uint64_t entry, uint64_t ram_size) s = tv_init(isa, ram_size, 1); if (tv_is_dirty_enabled(s) != rv_enable_dirty_update) { mismatch = true; - fprintf(stderr, "inconsistent enable-dirty-update setting: spike %s, sail %s\n", + fprintf(stderr, + "inconsistent enable-dirty-update setting: spike %s, sail %s\n", tv_is_dirty_enabled(s) ? "on" : "off", rv_enable_dirty_update ? "on" : "off"); } if (tv_is_misaligned_enabled(s) != rv_enable_misaligned) { mismatch = true; - fprintf(stderr, "inconsistent enable-misaligned-access setting: spike %s, sail %s\n", + fprintf(stderr, + "inconsistent enable-misaligned-access setting: " + "spike %s, sail %s\n", tv_is_misaligned_enabled(s) ? "on" : "off", - rv_enable_misaligned ? "on" : "off"); + rv_enable_misaligned ? "on" : "off"); } if (tv_ram_size(s) != rv_ram_size) { mismatch = true; - fprintf(stderr, "inconsistent ram-size setting: spike 0x%" PRIx64 ", sail 0x%" PRIx64 "\n", + fprintf(stderr, + "inconsistent ram-size setting: spike 0x%" PRIx64 + ", sail 0x%" PRIx64 "\n", tv_ram_size(s), rv_ram_size); } - if (mismatch) exit(1); + if (mismatch) + exit(1); /* The initialization order below matters. */ tv_set_verbose(s, 1); @@ -448,7 +466,8 @@ void init_spike(const char *f, uint64_t entry, uint64_t ram_size) spike_dtb = (unsigned char *)malloc(spike_dtb_len + 1); spike_dtb[spike_dtb_len] = '\0'; if (!tv_get_dtb(s, spike_dtb, &spike_dtb_len)) { - fprintf(stderr, "Got %" PRIu64 " bytes of dtb at %p\n", spike_dtb_len, spike_dtb); + fprintf(stderr, "Got %" PRIu64 " bytes of dtb at %p\n", spike_dtb_len, + spike_dtb); } else { fprintf(stderr, "Error getting DTB from Spike.\n"); exit(1); @@ -472,18 +491,16 @@ void tick_spike() void init_sail_reset_vector(uint64_t entry) { #define RST_VEC_SIZE 8 - uint32_t reset_vec[RST_VEC_SIZE] = { - 0x297, // auipc t0,0x0 - 0x28593 + (RST_VEC_SIZE * 4 << 20), // addi a1, t0, &dtb - 0xf1402573, // csrr a0, mhartid - is_32bit_model() ? - 0x0182a283u : // lw t0,24(t0) - 0x0182b283u, // ld t0,24(t0) - 0x28067, // jr t0 - 0, - (uint32_t) (entry & 0xffffffff), - (uint32_t) (entry >> 32) - }; + uint32_t reset_vec[RST_VEC_SIZE] + = {0x297, // auipc t0,0x0 + 0x28593 + (RST_VEC_SIZE * 4 << 20), // addi a1, t0, &dtb + 0xf1402573, // csrr a0, mhartid + is_32bit_model() ? 0x0182a283u : // lw t0,24(t0) + 0x0182b283u, // ld t0,24(t0) + 0x28067, // jr t0 + 0, + (uint32_t)(entry & 0xffffffff), + (uint32_t)(entry >> 32)}; rv_rom_base = DEFAULT_RSTVEC; uint64_t addr = rv_rom_base; @@ -520,7 +537,7 @@ void init_sail_reset_vector(uint64_t entry) /* zero-fill to page boundary */ const int align = 0x1000; - uint64_t rom_end = (addr + align -1)/align * align; + uint64_t rom_end = (addr + align - 1) / align * align; for (int i = addr; i < rom_end; i++) write_mem(addr++, 0); @@ -551,10 +568,11 @@ void init_sail(uint64_t elf_entry) zPC = elf_entry; } else #endif - init_sail_reset_vector(elf_entry); + init_sail_reset_vector(elf_entry); // this is probably unnecessary now; remove - if (!rv_enable_rvc) z_set_Misa_C(&zmisa, 0); + if (!rv_enable_rvc) + z_set_Misa_C(&zmisa, 0); } /* reinitialize to clear state and memory, typically across tests runs */ @@ -577,7 +595,8 @@ int init_check(struct tv_spike_t *s) void write_signature(const char *file) { if (mem_sig_start >= mem_sig_end) { - fprintf(stderr, "Invalid signature region [0x%0" PRIx64 ",0x%0" PRIx64 "] to %s.\n", + fprintf(stderr, + "Invalid signature region [0x%0" PRIx64 ",0x%0" PRIx64 "] to %s.\n", mem_sig_start, mem_sig_end, file); return; } @@ -587,10 +606,11 @@ void write_signature(const char *file) return; } /* write out words depending on signature granularity in signature area */ - for (uint64_t addr = mem_sig_start; addr < mem_sig_end; addr += signature_granularity) { + for (uint64_t addr = mem_sig_start; addr < mem_sig_end; + addr += signature_granularity) { /* most-significant byte first */ for (int i = signature_granularity - 1; i >= 0; i--) { - uint8_t byte = (uint8_t) read_mem(addr+i); + uint8_t byte = (uint8_t)read_mem(addr + i); fprintf(f, "%02x", byte); } fprintf(f, "\n"); @@ -598,7 +618,8 @@ void write_signature(const char *file) fclose(f); } -void close_logs(void) { +void close_logs(void) +{ #ifdef SAILCOV if (sail_coverage_exit() != 0) { fprintf(stderr, "Could not write coverage information!\n"); @@ -609,7 +630,8 @@ void close_logs(void) { void finish(int ec) { - if (sig_file) write_signature(sig_file); + if (sig_file) + write_signature(sig_file); model_fini(); #ifdef ENABLE_SPIKE @@ -620,9 +642,11 @@ void finish(int ec) exit(1); } if (do_show_times) { - int init_msecs = (init_end.tv_sec - init_start.tv_sec)*1000 + (init_end.tv_usec - init_start.tv_usec)/1000; - int exec_msecs = (run_end.tv_sec - init_end.tv_sec)*1000 + (run_end.tv_usec - init_end.tv_usec)/1000; - double Kips = ((double)total_insns)/((double)exec_msecs); + int init_msecs = (init_end.tv_sec - init_start.tv_sec) * 1000 + + (init_end.tv_usec - init_start.tv_usec) / 1000; + int exec_msecs = (run_end.tv_sec - init_end.tv_sec) * 1000 + + (run_end.tv_usec - init_end.tv_usec) / 1000; + double Kips = ((double)total_insns) / ((double)exec_msecs); fprintf(stderr, "Initialization: %d msecs\n", init_msecs); fprintf(stderr, "Execution: %d msecs\n", exec_msecs); fprintf(stderr, "Instructions: %d\n", total_insns); @@ -637,8 +661,8 @@ int compare_states(struct tv_spike_t *s) int passed = 1; #ifdef ENABLE_SPIKE -#define TV_CHECK(reg, spike_reg, sail_reg) \ - passed &= tv_check_ ## reg(s, spike_reg, sail_reg); +#define TV_CHECK(reg, spike_reg, sail_reg) \ + passed &= tv_check_##reg(s, spike_reg, sail_reg); // fix default C enum map for cur_privilege uint8_t priv = (zcur_privilege == 2) ? 3 : zcur_privilege; @@ -699,7 +723,7 @@ int compare_states(struct tv_spike_t *s) void flush_logs(void) { - if(config_print_instr) { + if (config_print_instr) { fprintf(stderr, "\n"); fflush(stderr); fprintf(stdout, "\n"); @@ -709,14 +733,16 @@ void flush_logs(void) #ifdef RVFI_DII -typedef void (packet_reader_fn)(lbits *rop, unit); -static void get_and_send_rvfi_packet(packet_reader_fn *reader) { +typedef void (*packet_reader_fn)(lbits *rop, unit); +static void get_and_send_rvfi_packet(packet_reader_fn reader) +{ lbits packet; CREATE(lbits)(&packet); reader(&packet, UNIT); /* Note: packet.len is the size in bits, not bytes. */ if (packet.len % 8 != 0) { - fprintf(stderr, "RVFI-DII trace packet not byte aligned: %d\n", (int)packet.len); + fprintf(stderr, "RVFI-DII trace packet not byte aligned: %d\n", + (int)packet.len); exit(1); } const size_t send_size = packet.len / 8; @@ -743,7 +769,8 @@ static void get_and_send_rvfi_packet(packet_reader_fn *reader) { KILL(lbits)(&packet); } -void rvfi_send_trace(unsigned version) { +void rvfi_send_trace(unsigned version) +{ if (config_print_rvfi) { fprintf(stderr, "Sending v%d trace response...\n", version); } @@ -826,7 +853,8 @@ void run_sail(void) * we support version 2. */ if (config_print_rvfi) { - fprintf(stderr, "EndOfTrace was actually a version negotiation packet.\n"); + fprintf(stderr, + "EndOfTrace was actually a version negotiation packet.\n"); } get_and_send_rvfi_packet(&zrvfi_get_v2_support_packet); continue; @@ -841,23 +869,28 @@ void run_sail(void) case 'v': { /* Set wire format version */ mach_bits insn = zrvfi_get_insn(UNIT); if (config_print_rvfi) { - fprintf(stderr, "Got request for v%jd trace format!\n", (intmax_t)insn); + fprintf(stderr, "Got request for v%jd trace format!\n", + (intmax_t)insn); } if (insn == 1) { fprintf(stderr, "Requested trace in legacy format!\n"); } else if (insn == 2) { fprintf(stderr, "Requested trace in v2 format!\n"); } else { - fprintf(stderr, "Requested trace in unsupported format %jd!\n", (intmax_t)insn); + fprintf(stderr, "Requested trace in unsupported format %jd!\n", + (intmax_t)insn); exit(1); } - rvfi_trace_version = insn; // From now on send traces in the requested format + rvfi_trace_version + = insn; // From now on send traces in the requested format struct { char msg[8]; uint64_t version; - } version_response = { "version=", rvfi_trace_version }; - if (write(rvfi_dii_sock, &version_response, sizeof(version_response)) != sizeof(version_response)) { - fprintf(stderr, "Sending version response failed: %s\n", strerror(errno)); + } version_response = {"version=", rvfi_trace_version}; + if (write(rvfi_dii_sock, &version_response, sizeof(version_response)) + != sizeof(version_response)) { + fprintf(stderr, "Sending version response failed: %s\n", + strerror(errno)); exit(1); } continue; @@ -870,7 +903,8 @@ void run_sail(void) CREATE(sail_int)(&sail_step); CONVERT_OF(sail_int, mach_int)(&sail_step, step_no); stepped = zstep(sail_step); - if (have_exception) goto step_exception; + if (have_exception) + goto step_exception; flush_logs(); KILL(sail_int)(&sail_step); rvfi_send_trace(rvfi_trace_version); @@ -881,7 +915,8 @@ void run_sail(void) CREATE(sail_int)(&sail_step); CONVERT_OF(sail_int, mach_int)(&sail_step, step_no); stepped = zstep(sail_step); - if (have_exception) goto step_exception; + if (have_exception) + goto step_exception; flush_logs(); KILL(sail_int)(&sail_step); } @@ -892,13 +927,16 @@ void run_sail(void) } if (do_show_times && (total_insns & 0xfffff) == 0) { - uint64_t start_us = 1000000 * ((uint64_t) interval_start.tv_sec) + ((uint64_t)interval_start.tv_usec); + uint64_t start_us = 1000000 * ((uint64_t)interval_start.tv_sec) + + ((uint64_t)interval_start.tv_usec); if (gettimeofday(&interval_start, NULL) < 0) { fprintf(stderr, "Cannot gettimeofday: %s\n", strerror(errno)); - exit(1); + exit(1); } - uint64_t end_us = 1000000 * ((uint64_t) interval_start.tv_sec) + ((uint64_t)interval_start.tv_usec); - fprintf(stdout, "kips: %" PRIu64 "\n", ((uint64_t)1000) * 0x100000 / (end_us - start_us)); + uint64_t end_us = 1000000 * ((uint64_t)interval_start.tv_sec) + + ((uint64_t)interval_start.tv_usec); + fprintf(stdout, "kips: %" PRIu64 "\n", + ((uint64_t)1000) * 0x100000 / (end_us - start_us)); } #ifdef ENABLE_SPIKE { /* run a Spike step */ @@ -909,7 +947,8 @@ void run_sail(void) if (zhtif_done) { if (!spike_done) { - fprintf(stdout, "Sail done (exit-code %" PRIi64 "), but not Spike!\n", zhtif_exit_code); + fprintf(stdout, "Sail done (exit-code %" PRIi64 "), but not Spike!\n", + zhtif_exit_code); exit(1); } } else { @@ -940,13 +979,13 @@ void run_sail(void) } } - dump_state: +dump_state: if (diverged) { /* TODO */ } finish(diverged); - step_exception: +step_exception: fprintf(stderr, "Sail exception!"); goto dump_state; } @@ -962,8 +1001,12 @@ void init_logs() } #endif - if (term_log != NULL && (term_fd = open(term_log, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR)) < 0) { - fprintf(stderr, "Cannot create terminal log '%s': %s\n", term_log, strerror(errno)); + if (term_log != NULL + && (term_fd = open(term_log, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR)) + < 0) { + fprintf(stderr, "Cannot create terminal log '%s': %s\n", term_log, + strerror(errno)); exit(1); } @@ -997,15 +1040,16 @@ int main(int argc, char **argv) return 1; } int reuseaddr = 1; - if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1) { - fprintf(stderr, "Unable to set reuseaddr on socket: %s\n", strerror(errno)); + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, + sizeof(reuseaddr)) + == -1) { + fprintf(stderr, "Unable to set reuseaddr on socket: %s\n", + strerror(errno)); return 1; } - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - .sin_port = htons(rvfi_dii_port) - }; + struct sockaddr_in addr = {.sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + .sin_port = htons(rvfi_dii_port)}; if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "Unable to set bind socket: %s\n", strerror(errno)); return 1; @@ -1015,14 +1059,16 @@ int main(int argc, char **argv) return 1; } socklen_t addrlen = sizeof(addr); - if (getsockname(listen_sock, (struct sockaddr *) &addr, &addrlen) == -1) { - fprintf(stderr, "Unable to getsockname() on socket: %s\n", strerror(errno)); + if (getsockname(listen_sock, (struct sockaddr *)&addr, &addrlen) == -1) { + fprintf(stderr, "Unable to getsockname() on socket: %s\n", + strerror(errno)); return 1; } printf("Waiting for connection on port %d.\n", ntohs(addr.sin_port)); rvfi_dii_sock = accept(listen_sock, NULL, NULL); if (rvfi_dii_sock == -1) { - fprintf(stderr, "Unable to accept connection on socket: %s\n", strerror(errno)); + fprintf(stderr, "Unable to accept connection on socket: %s\n", + strerror(errno)); return 1; } close(listen_sock); @@ -1053,7 +1099,8 @@ int main(int argc, char **argv) init_spike(file, entry, rv_ram_size); init_sail(entry); - if (!init_check(s)) finish(1); + if (!init_check(s)) + finish(1); if (gettimeofday(&init_end, NULL) < 0) { fprintf(stderr, "Cannot gettimeofday: %s\n", strerror(errno)); |