Browse Source

Coccinelle: add a semantic patch that detects missing calls to starpu_task_destroy() in the error handling code for starpu_task_submit().

Cyril Roelandt 13 years ago
parent
commit
25eafb6aa8

+ 111 - 0
tools/dev/experimental/destroy_task_on_error.cocci

@@ -0,0 +1,111 @@
+/*
+ * StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2012 inria
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+/*
+ * When the submission of a task fails, StarPU cannot destroy the task, even if
+ * the destroy flag is set. So we have to destroy it ourselves while handling
+ * the error.
+ *
+ * TODO: match if statments without braces.
+ */
+
+virtual context
+virtual org
+virtual patch
+virtual report
+
+@initialize:python depends on org || report@
+msg = "Warning: in %s(): "
+msg+= "\"%s\" should probably be destroyed in the body of the if statement"
+
+@r@
+local idexpression t;
+identifier err;
+identifier f;
+position p;
+@@
+f(...)
+{
+<+...
+(
+err = starpu_task_submit(t);
+|
+int err = starpu_task_submit(t);
+)
+if@p(
+(
+err == -ENODEV
+|
+err != 0
+|
+STARPU_UNLIKELY(err == -ENODEV)
+|
+STARPU_UNLIKELY(err != 0)
+)
+ )
+{
+... when != starpu_task_destroy(t);
+    when != exit(...);
+    when != STARPU_ASSERT(...);
+    when != return 77;
+}
+...+>
+}
+
+// Context mode.
+@depends on r && context@
+position r.p;
+@@
+*if@p(...) { ... }
+
+// Org mode.
+@script:python depends on r && org@
+p << r.p;
+t << r.t;
+f << r.f;
+@@
+coccilib.org.print_todo(p[0], msg % (f,t))
+
+// Patch mode.
+// XXX: Instead of "..." we could use a statement list (statement list SS). But
+// it does not seem to work with if there is a "return" statement in the body
+// of the if condition.
+// Using "..." makes the patch ugly, but this may be fixed in a future version
+// of spatch.
+@depends on r && patch@
+local idexpression r.t;
+position r.p;
+identifier r.f;
+@@
+f(...)
+{
+<+...
+if@p (...)
+{
+...
++ starpu_task_destroy(t);
+}
+...+>
+}
+
+// Report mode.
+@script:python depends on r && report@
+p << r.p;
+t << r.t;
+f << r.f;
+@@
+coccilib.report.print_report(p[0], msg % (f,t))

+ 65 - 0
tools/dev/experimental/destroy_task_on_error_test.c

@@ -0,0 +1,65 @@
+/*
+ * StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2012 inria
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+static void
+good_0(void)
+{
+	struct starpu_task *task;
+	task = starpu_task_create();
+	int ret = starpu_task_submit(task);
+	if (ret == -ENODEV)
+	{
+		fprintf(stderr, "fail\n");
+		starpu_task_destroy(task);
+	}
+}
+
+static void
+bad_0(void)
+{
+	struct starpu_task *task1, *task2;
+
+	task1 = starpu_task_create();
+	int ret = starpu_task_submit(task1);
+	if (ret == -ENODEV)
+	{
+		fprintf(stderr, "Fail\n");
+	}
+
+	task2 = starpu_task_create();
+	ret = starpu_task_submit(task2);
+	if (ret == -ENODEV)
+	{
+		fprintf(stderr, "Fail\n");
+	}
+}
+
+static void
+bad_unlikely(void)
+{
+	struct starpu_task *task;
+
+	task = starpu_task_create();
+
+	int ret = starpu_task_submit(task);
+	if (STARPU_UNLIKELY(ret == -ENODEV))
+	{
+		error();
+		return 1;
+	}
+
+	starpu_task_destroy(task);
+}