Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
KERN_TESTFRWK(9)	 BSD Kernel Developer's	Manual	      KERN_TESTFRWK(9)

     kern_testfrwk -- A	kernel testing framework

     kldload kern_testfrwk

     So	what is	this sys/tests directory in the	kernel all about?

     Have you ever wanted to test a part of the	FreeBSD	kernel in some way and
     you had no	real way from user-land	to make	what you want to occur happen?
     Say an error path or situation where locking occurs in a particular man-
     ner that happens only once	in a blue moon?

     If	so, then the kernel test framework is just what	you are	looking	for.
     It	is designed to help you	create the situation you want.

     There are two components to the system: the test framework	and your test.
     This document will	describe both components and use the test submitted
     with the initial commit of	this code to discuss the test
     (callout_test(4)).	 All of	the tests become kernel	loadable modules.  The
     test you write should have	a dependency on	the test framework.  That way
     it	will be	loaded automatically with your test.  For example, you can see
     how to do this in the bottom of callout_test.c in

     The framework itself is in	sys/tests/framework/kern_testfrwk.c.  Its job
     is	to manage the tests that are loaded.  (More than one can be loaded.)
     The idea is pretty	simple;	you load the test framework and	then load your

     When your test loads, you register	your tests with	the kernel test	frame-
     work.  You	do that	through	a call to kern_testframework_register().  Usu-
     ally this is done at the module load event	as shown below:

		   switch (type) {
		   case	MOD_LOAD:
			   err = kern_testframework_register("callout_test",

     Here the test is "callout_test" and it is registered to run the function
     run_callout_test()	passing	it a struct kern_test *ptr.  The kern_test
     structure is defined in kern_testfrwk.h.

	   struct kern_test {
		   char	name[TEST_NAME_LEN];
		   int num_threads;  /*	Fill in	how many threads you want */
		   int tot_threads_running;	  /* Private to	framework */
		   uint8_t test_options[TEST_OPTION_SPACE];

     The user sends this structure down	via a sysctl to	start your test.  He
     or	she places the same name you registered	("callout_test"	in our exam-
     ple) in the name field.  The user can also	set the	number of threads to
     run with num_threads.

     The framework will	start the requested number of kernel threads, all run-
     ning your test at the same	time.  The user	does not specify anything in
     tot_threads_running; it is	private	to the framework.  As the framework
     calls each	of your	tests, it will set the tot_threads_running to the in-
     dex of the	thread that your call is made from.  For example, if the user
     sets num_threads to 2, then the function run_callout_test() will be
     called once with tot_threads_running to 0,	and a second time with
     tot_threads_running set to	1.

     The test_options field is a test-specific set of information that is an
     opaque blob.  It is passed	in from	user space and has a maximum size of
     256 bytes.	 You can pass arbitrary	test input in the space.  In the case
     of	callout_test we	reshape	that to:

	   struct callout_test {
		   int number_of_callouts;
		   int test_number;

     So	the first lines	of run_callout_test() does the following to get	at the
     user specific data:

		   struct callout_test *u;
		   size_t sz;
		   int i;
		   struct callout_run *rn;
		   int index = test->tot_threads_running;

		   u = (struct callout_test *)test->test_options;

     That way it can access: u-_test_number (there are two types of tests pro-
     vided with	this test) and u-_number_of_callouts (how many simultaneous
     callouts to run).

     Your test can do anything with these bytes.  So the callout_test in ques-
     tion wants	to create a situation where multiple callouts are all run,
     that is the number_of_callouts, and it tries to cancel the	callout	with
     the new callout_async_drain().  The threads do this by acquiring the lock
     in	question, and then starting each of the	callouts.  It waits for	the
     callouts to all go	off (the executor spins	waits).	 This forces the situ-
     ation that	the callouts have expired and are all waiting on the lock that
     the executor holds.  After	the callouts are all blocked, the executor
     calls callout_async_drain() on each callout and releases the lock.

     After all the callouts are	done, a	total status is	printed	showing	the
     results via printf(9).  The human tester can run dmesg(8) to see the re-
     sults.  In	this case it is	expected that if you are running test 0, all
     the callouts expire on the	same CPU so only one callout_drain function
     would have	been called.  the number of zero_returns should	match the num-
     ber of callout_drains that	were called, i.e., 1.  The one_returns should
     be	the remainder of the callouts.	If the test number was 1, the callouts
     were spread across	all CPUs.  The number of zero_returns will again match
     the number	of drain calls made which matches the number of	CPUs that were
     put in use.

     More than one thread can be used with this	test, though in	the example
     case it is	probably not necessary.

     You should	not need to change the framework.  Just	add tests and register
     them after	loading.

     The kernel	test framework was written by Randall Stewart
     <> with help from
     John Mark Gurney <>.

BSD			       November	12, 2015			   BSD


Want to link to this manual page? Use this URL:

home | help