aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-04-10 15:25:22 +0200
committerJosh Triplett <josh@freedesktop.org>2008-04-21 11:08:50 -0700
commitc3903563ac88d18a726aef47220573b383d697d1 (patch)
tree04272e882b60665f7306cbf12648a4b56e5f3fcf /validation
parentsparse test suite: add test mixing __context__ and __attribute__((context(...))) (diff)
downloadsparse-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.c161
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
+ */