From 5cf8d8d6dbfec71746173fae2a64d40f39e144cf Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 13 Mar 2014 21:25:01 +0100 Subject: [PATCH] lib/igt_core: document the caveats of magic code blocks v2: Polish the wording a bit. Signed-off-by: Daniel Vetter --- lib/igt_core.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/igt_core.c b/lib/igt_core.c index ff471178..0be77416 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -83,6 +83,38 @@ * To allow this i-g-t provides #igt_fixture code blocks for setup code outside * of subtests and automatically skips the subtest code blocks themselves. For * special cases igt_only_list_subtests() is also provided. + * + * # Magic Control Blocks + * + * i-g-t makes heavy use of C macros which serve as magic control blocks. They + * work fairly well and transparently but since C doesn't have full-blown + * closures there are caveats: + * + * - Asynchronous blocks which are used to spawn children internally use fork(). + * Which means that nonsensical control flow like jumping out of the control + * block is possible, but it will badly confuse the i-g-t library code. And of + * course all caveats of a real fork() call apply, namely that file + * descriptors are copied, but still point at the original file. This will + * terminally upset the libdrm buffer manager if both parent and child keep on + * using the same open instance of the drm device. Usually everything related + * to interacting with the kernel driver must be reinitialized to avoid such + * issues. + * + * - Code blocks with magic control flow are implemented with setjmp() and + * longjmp(). This applies to #igt_fixture and #igt_subtest blocks and all the + * three variants to finish test: igt_success(), igt_skip() and igt_fail(). + * Mostly this is of no concern, except when such a control block changes + * stack variables defined in the same function as the control block resides. + * Any store/load behaviour after a longjmp() is ill-defined for these + * variables. Avoid such code. + * + * Quoting the man page for longjmp(): + * + * "The values of automatic variables are unspecified after a call to + * longjmp() if they meet all the following criteria:" + * - "they are local to the function that made the corresponding setjmp() call; + * - "their values are changed between the calls to setjmp() and longjmp(); and + * - "they are not declared as volatile." */ static unsigned int exit_handler_count;