Subject: kernel->userland r/o page mapping
To: None <tech-kern@netbsd.org>
From: Matthew Mondor <mm_lists@pulsar-zone.net>
List: tech-kern
Date: 03/08/2007 07:45:52
--Multipart_Thu__8_Mar_2007_07_45_52_-0500_dV3w_9G55XMQkscc
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

For some applications I noticed that it would be useful to have minor
live kernel information bits accessible efficiently in userland in
read-only mode.  For instance a new structure could be defined and some
userland library functions could obtain a pointer to it in the process
vm space to access the fields, unprivileged and efficiently.

Since I'm not familiar much with uvm it raised the following questions:

Is there currently in place a subsystem doing this which can be expanded
as needed?  If not:

If init_main.c allocated a wired kernel physical page and mapped it in
init(8)'s virtual space as a wired, read-only, inheritable page, how
would userland reliably know at which address the page was mapped to,
without a new syscall?  Perhaps throuh sysctl?  Or if a specific address
had to be decided on, would there be an arch-independent address that
would suit this?  Would using "page 0" for this be out of the question?

An alternative would possibly be a new device, say krtm(4) with only
mmap support, allowing any users to obtain the read-only mapping to the
wired kernel page.  Unless I'm mistaken, other than initial
open(2)/mmap(2) overhead, accesses to the fields in memory would then
theoretically be at the same speed as with the previous method?

I could see various users of this such as to access the current time
faster.  I guess that a process-specific page in a similar manner would
allow more real-time access of process statistics also, but probably
with the first method rather than through a device, the kernel updating
those statistics into the special page...

Thanks
-- 
Matt
--Multipart_Thu__8_Mar_2007_07_45_52_-0500_dV3w_9G55XMQkscc
Content-Type: application/octet-stream; name=clocktests.txt
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=clocktests.txt


$ time ./clocktest1 1000000 
    8.35s real     0.52s user     7.81s system
$ time ./clocktest2 1000000 
    8.50s real     0.52s user     7.96s system
$ time ./clocktest3 1000000 
    3.40s real     0.29s user     3.09s system



#include <sys/time.h>
#include <stdlib.h>

int	main(int, char **);

int
main(int argc, char **argv)
{
	int	i, t;

	if (argc != 2)
		return EXIT_FAILURE;
	t = atoi(argv[1]);

	for (i = 0; i < t; i++) {
		struct timeval	tv;

		(void) gettimeofday(&tv, NULL);
	}

	return EXIT_SUCCESS;
}



#include <stdlib.h>
#include <time.h>

int	main(int, char **);

int
main(int argc, char **argv)
{
	int	i, t;

	if (argc != 2)
		return EXIT_FAILURE;
	t = atoi(argv[1]);

	for (i = 0; i < t; i++) {
		struct timespec	ts;

		(void) clock_gettime(CLOCK_REALTIME, &ts);
	}

	return EXIT_SUCCESS;
}



#include <sys/param.h>
#include <sys/sysctl.h>
#include <stdlib.h>

int	main(int, char **);

int
main(int argc, char **argv)
{
	int	i, t;
	int	mib[2];
	size_t	l;

	mib[0] = CTL_KERN;
	mib[1] = KERN_HARDCLOCK_TICKS;
	l = sizeof(int);

	if (argc != 2)
		return EXIT_FAILURE;
	t = atoi(argv[1]);

	for (i = 0; i < t; i++) {
		int	c;

		(void) sysctl(mib, 2, &c, &l, NULL, 0);
	}

	return EXIT_SUCCESS;
}


--Multipart_Thu__8_Mar_2007_07_45_52_-0500_dV3w_9G55XMQkscc--