kernel - Add /dev/upmap and /dev/kpmap and sys/upmap.h (2)
* Disallow writing to kpmap.
* Handle cpu read/update races against ts_uptime and ts_realtime by
making these arrays[2] and using kpmap->upticks to tell userland
which one is stable.
The procedure is as follows:
struct timespec ts_uptime;
struct timespec ts_realtime;
int w;
do {
w = kpmap->upticks;
cpu_lfence();
ts_uptime = kpmap->ts_uptime[w & 1];
ts_realtime = kpmap->ts_realtime[w & 1];
cpu_lfence();
w = kpmap->upticks - w;
} while (w > 1);
This procedure avoids having to loop in all standard cases including
the nominal kernel update / userland read race. It will only loop if
the kernel deschedules the user process for > 1 tick during the access
sequence.