diff options
author | 2008-04-10 15:25:22 +0200 | |
---|---|---|
committer | 2008-04-21 11:08:50 -0700 | |
commit | c3903563ac88d18a726aef47220573b383d697d1 (patch) | |
tree | 04272e882b60665f7306cbf12648a4b56e5f3fcf /validation | |
parent | sparse test suite: add test mixing __context__ and __attribute__((context(...))) (diff) | |
download | sparse-c3903563ac88d18a726aef47220573b383d697d1.tar.gz sparse-c3903563ac88d18a726aef47220573b383d697d1.tar.bz2 sparse-c3903563ac88d18a726aef47220573b383d697d1.zip |
sparse: simple conditional context tracking
This patch enables a very simple form of conditional context tracking,
namely something like
if (spin_trylock(...)) {
[...]
spin_unlock(...);
}
Note that
__ret = spin_trylock(...);
if (__ret) {
[...]
spin_unlock(...);
}
does /not/ work since that would require tracking the variable and doing
extra checks to ensure the variable isn't globally accessible or similar
which could lead to race conditions.
To declare a trylock, one uses:
int spin_trylock(...) __attribute__((conditional_context(spinlock,0,1,0)))
{...}
Note that doing this currently excludes that function itself from context
checking completely.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'validation')
-rw-r--r-- | validation/context-dynamic.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/validation/context-dynamic.c b/validation/context-dynamic.c new file mode 100644 index 0000000..e3bbb98 --- /dev/null +++ b/validation/context-dynamic.c @@ -0,0 +1,161 @@ +static void a(void) __attribute__ ((context(A, 0, 1))) +{ + __context__(A, 1); +} + +static void r(void) __attribute__ ((context(A, 1, 0))) +{ + __context__(A, -1); +} + +extern int condition, condition2; + +static int tl(void) __attribute__ ((conditional_context(A, 0, 1, 0))) +{ + if (condition) { + a(); + return 1; + } + return 0; +} + +static int tl2(void) __attribute__ ((conditional_context(A, 0, 0, 1))) +{ + if (condition) { + a(); + return 1; + } + return 0; +} + +static int dummy(void) +{ + return condition + condition2; +} + +static int good_trylock1(void) +{ + if (tl()) { + r(); + } +} + +static int good_trylock2(void) +{ + if (tl()) { + r(); + } + + if (tl()) { + r(); + } +} +static int good_trylock3(void) +{ + a(); + if (tl()) { + r(); + } + r(); + if (tl()) { + r(); + } +} + +static int good_trylock4(void) +{ + a(); + if (tl()) { + r(); + } + if (tl()) { + r(); + } + r(); +} + +static void bad_trylock1(void) +{ + a(); + if (dummy()) { + r(); + } + r(); +} + +static int good_trylock5(void) +{ + if (!tl2()) { + r(); + } +} + +static int good_trylock6(void) +{ + if (!tl2()) { + r(); + } + + if (!tl2()) { + r(); + } +} +static int good_trylock7(void) +{ + a(); + if (!tl2()) { + r(); + } + r(); + if (!tl2()) { + r(); + } +} + +static int good_trylock8(void) +{ + a(); + if (!tl2()) { + r(); + } + if (!tl2()) { + r(); + } + r(); +} + +static void bad_trylock2(void) +{ + a(); + if (!dummy()) { + r(); + } + r(); +} + +static int good_switch(void) +{ + switch (condition) { + case 1: + a(); + break; + case 2: + a(); + break; + case 3: + a(); + break; + default: + a(); + } + r(); +} + +/* + * check-name: Check -Wcontext with lock trylocks + * + * check-error-start +context-dynamic.c:83:6: warning: context problem in 'bad_trylock1' - function 'r' expected different context +context-dynamic.c:133:6: warning: context problem in 'bad_trylock2' - function 'r' expected different context + * check-error-end + */ |