Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Clemens Ladisch Newsgroups: comp.os.linux.misc,comp.os.linux.hardware Subject: Re: Realtime clock accessible without context-switch? Date: Wed, 21 May 2014 19:32:46 +0200 Lines: 66 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Trace: individual.net NKdAxNUklmHwCdeG1ADPTAZZ5xHJOHQftXUN2oflWEe9Qkv2U4 Cancel-Lock: sha1:sZvwa2JMHWa5nYryzgikV/CCUMk= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 In-Reply-To: Xref: csiph.com comp.os.linux.misc:11111 comp.os.linux.hardware:2392 Charles T. Smith wrote: > On Tue, 20 May 2014 21:56:48 +0200, Clemens Ladisch wrote: >> Charles T. Smith wrote: >>> Is there a way to access (say on Intel platforms) the realtime clock >>> without using a special device driver, but simply with non-synchronized >>> memory access? >> >> On IBM-PC compatible machines, the RTC lives in the good ol' ISA I/O >> space, which cannot be memory-mapped. >> >> When doing ISA I/O accesses, the switch to kernel mode is _not_ the >> bottleneck. If you want to avoid it anyway, use iopl and inb/outb. > > Still these days? If it didn't use I/O space, it wouldn't be compatible. > But aren't there other clocks around? Lots, but none of those store the _real_ time. I'd suggest the High Precision Event Timer; see the example program below. > Newer processors have various debug registers, I think. Try rdtsc. Or just forget about all that hardware-dependent hackery and use clock_gettime(). > Your statement that the "switch to kernel mode is *not* the bottleneck" > is intriguing. Can you give a hint or a URL about what you mean? An I/O access (about one microsecond) is much slower than the SYSCALL instruction; and with the RTC, you'd need to read several registers. Regards, Clemens --8<---------------------------------------------------------------->8-- #include #include #include #include int main(void) { int fd = open("/dev/hpet", O_RDONLY); if (fd == -1) { perror("/dev/hpet"); return 1; } const volatile unsigned int *ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { perror("mmap"); return 1; } printf("frequency: %.5f MHz\n", 1e9 / ptr[1]); for (;;) { printf("\rcounter: %08x", ptr[60]); fflush(stdout); usleep(123456); } }