<div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 7, 2019 at 3:29 PM Sumit Garg <<a href="mailto:sumit.garg@linaro.org">sumit.garg@linaro.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Greg Hackmann <<a href="mailto:ghackmann@google.com" target="_blank">ghackmann@google.com</a>><br>
<br>
tgkill() delivers a signal to a specific thread.  Test this by<br>
installing a SIGUSR1 handler which records the current pthread ID.<br>
Start a number of threads in parallel, then one-by-one call tgkill(...,<br>
tid, SIGUSR1) and check that the expected pthread ID was recorded.<br>
<br>
Signed-off-by: Greg Hackmann <<a href="mailto:ghackmann@google.com" target="_blank">ghackmann@google.com</a>><br>
Signed-off-by: Sumit Garg <<a href="mailto:sumit.garg@linaro.org" target="_blank">sumit.garg@linaro.org</a>><br></blockquote><div><span class="gmail_default" style="font-size:small"></span></div><div><span class="gmail_default" style="font-size:small">Reviewed-by: Li Wang <<a href="mailto:liwang@redhat.com">liwang@redhat.com</a>></span></div><div><span class="gmail_default" style="font-size:small"><br></span></div><div><span class="gmail_default" style="font-size:small">This patch set looks pretty good to me. Just have a tiny comments for PATCH 1/3 in below.</span></div><div><span class="gmail_default" style="font-size:small"></span> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
 runtest/syscalls                            |   2 +<br>
 testcases/kernel/syscalls/tgkill/.gitignore |   1 +<br>
 testcases/kernel/syscalls/tgkill/Makefile   |  10 ++<br>
 testcases/kernel/syscalls/tgkill/tgkill.h   |  22 +++++<br>
 testcases/kernel/syscalls/tgkill/tgkill01.c | 138 ++++++++++++++++++++++++++++<br>
 5 files changed, 173 insertions(+)<br>
 create mode 100644 testcases/kernel/syscalls/tgkill/.gitignore<br>
 create mode 100644 testcases/kernel/syscalls/tgkill/Makefile<br>
 create mode 100644 testcases/kernel/syscalls/tgkill/tgkill.h<br>
 create mode 100644 testcases/kernel/syscalls/tgkill/tgkill01.c<br>
<br>
diff --git a/runtest/syscalls b/runtest/syscalls<br>
index b43de7a..9ed1214 100644<br>
--- a/runtest/syscalls<br>
+++ b/runtest/syscalls<br>
@@ -1395,6 +1395,8 @@ syslog10 syslog10<br>
 syslog11 syslog11<br>
 syslog12 syslog12<br>
<br>
+tgkill01 tgkill01<br>
+<br>
 time01 time01<br>
 time02 time02<br>
<br>
diff --git a/testcases/kernel/syscalls/tgkill/.gitignore b/testcases/kernel/syscalls/tgkill/.gitignore<br>
new file mode 100644<br>
index 0000000..f4566fd<br>
--- /dev/null<br>
+++ b/testcases/kernel/syscalls/tgkill/.gitignore<br>
@@ -0,0 +1 @@<br>
+tgkill01<br>
diff --git a/testcases/kernel/syscalls/tgkill/Makefile b/testcases/kernel/syscalls/tgkill/Makefile<br>
new file mode 100644<br>
index 0000000..a51080c<br>
--- /dev/null<br>
+++ b/testcases/kernel/syscalls/tgkill/Makefile<br>
@@ -0,0 +1,10 @@<br>
+# SPDX-License-Identifier: GPL-2.0-or-later<br>
+# Copyright (c) 2018 Google, Inc.<br>
+<br>
+top_srcdir             ?= ../../../..<br>
+<br>
+include $(top_srcdir)/include/mk/<a href="http://testcases.mk" rel="noreferrer" target="_blank">testcases.mk</a><br>
+<br>
+include $(top_srcdir)/include/mk/<a href="http://generic_leaf_target.mk" rel="noreferrer" target="_blank">generic_leaf_target.mk</a><br>
+<br>
+LDLIBS                 += -pthread<br>
diff --git a/testcases/kernel/syscalls/tgkill/tgkill.h b/testcases/kernel/syscalls/tgkill/tgkill.h<br>
new file mode 100644<br>
index 0000000..a7d96f4<br>
--- /dev/null<br>
+++ b/testcases/kernel/syscalls/tgkill/tgkill.h<br>
@@ -0,0 +1,22 @@<br>
+// SPDX-License-Identifier: GPL-2.0-or-later<br>
+/*<br>
+ * Copyright (c) 2018 Google, Inc.<br>
+ */<br>
+<br>
+#ifndef TGKILL_H<br>
+#define TGKILL_H<br>
+<br>
+#include "config.h"<br>
+#include "lapi/syscalls.h"<br>
+<br>
+static inline int sys_tgkill(int tgid, int tid, int sig)<br>
+{<br>
+       return tst_syscall(__NR_tgkill, tgid, tid, sig);<br>
+}<br>
+<br>
+static inline pid_t sys_gettid(void)<br>
+{<br>
+       return tst_syscall(__NR_gettid);<br>
+}<br>
+<br>
+#endif /* TGKILL_H */<br>
diff --git a/testcases/kernel/syscalls/tgkill/tgkill01.c b/testcases/kernel/syscalls/tgkill/tgkill01.c<br>
new file mode 100644<br>
index 0000000..1fb1171<br>
--- /dev/null<br>
+++ b/testcases/kernel/syscalls/tgkill/tgkill01.c<br>
@@ -0,0 +1,138 @@<br>
+// SPDX-License-Identifier: GPL-2.0-or-later<br>
+/*<br>
+ * Copyright (c) 2018 Google, Inc.<br>
+ *<br>
+ * tgkill() delivers a signal to a specific thread.  Test this by installing<br>
+ * a SIGUSR1 handler which records the current pthread ID.  Start a number<br>
+ * of threads in parallel, then one-by-one call tgkill(..., tid, SIGUSR1)<br>
+ * and check that the expected pthread ID was recorded.<br>
+ */<br>
+<br>
+#include <pthread.h><br>
+<br>
+#include "tst_safe_pthread.h"<br>
+#include "tst_test.h"<br>
+#include "tgkill.h"<br>
+<br>
+struct thread_state {<br>
+       pthread_t thread;<br>
+       pid_t tid;<br>
+};<br>
+<br>
+static char *str_threads;<br>
+static int n_threads = 10;<br>
+static struct thread_state *threads;<br>
+<br>
+static pthread_t sigusr1_thread;<br>
+<br>
+static int test_running;<br>
+static pthread_cond_t test_running_cond = PTHREAD_COND_INITIALIZER;<br>
+static pthread_mutex_t test_running_mutex = PTHREAD_MUTEX_INITIALIZER;<br>
+<br>
+static void sigusr1_handler(int signum __attribute__((unused)))<br>
+{<br>
+       sigusr1_thread = pthread_self();<br>
+}<br>
+<br>
+static void *thread_func(void *arg)<br>
+{<br>
+       struct thread_state *thread = arg;<br>
+<br>
+       /**<br>
+        * There is no standard way to map pthread -> tid, so we will have the<br>
+        * child stash its own tid then notify the parent that the stashed tid<br>
+        * is available.<br>
+        */<br>
+       thread->tid = sys_gettid();<br>
+<br>
+       TST_CHECKPOINT_WAKE(0);<br>
+<br>
+       pthread_mutex_lock(&test_running_mutex);<br>
+       while (test_running)<br>
+               pthread_cond_wait(&test_running_cond, &test_running_mutex);<br>
+       pthread_mutex_unlock(&test_running_mutex);<br>
+<br>
+       return arg;<br>
+}<br>
+<br>
+static void start_thread(struct thread_state *thread)<br>
+{<br>
+       SAFE_PTHREAD_CREATE(&thread->thread, NULL, thread_func, thread);<br>
+<br>
+       TST_CHECKPOINT_WAIT(0);<br>
+}<br>
+<br>
+static void stop_threads(void)<br>
+{<br>
+       int i;<br>
+<br>
+       test_running = 0;<br>
+       pthread_cond_broadcast(&test_running_cond);<br>
+<br>
+       for (i = 0; i < n_threads; i++) {<br>
+               if (threads[i].tid == -1)<br>
+                       continue;<br>
+<br>
+               SAFE_PTHREAD_JOIN(threads[i].thread, NULL);<br>
+               threads[i].tid = -1;<br>
+       }<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Maybe we can add free() to release the allocated memory here.</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small">  if (threads)</div><div class="gmail_default" style="font-size:small">        free(threads);</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+}<br>
+<br>
+static void run(void)<br>
+{<br>
+       int i;<br>
+<br>
+       for (i = 0; i < n_threads; i++)<br>
+               threads[i].tid = -1;<br>
+<br>
+       test_running = 1;<br>
+       for (i = 0; i < n_threads; i++)<br>
+               start_thread(&threads[i]);<br>
+<br>
+       for (i = 0; i < n_threads; i++) {<br>
+               sigusr1_thread = pthread_self();<br>
+<br>
+               TEST(sys_tgkill(getpid(), threads[i].tid, SIGUSR1));<br>
+               if (TST_RET) {<br>
+                       tst_res(TFAIL | TTERRNO, "tgkill() failed");<br>
+                       return;<br>
+               }<br>
+<br>
+               while (pthread_equal(sigusr1_thread, pthread_self()))<br>
+                       usleep(1000);<br>
+<br>
+               if (!pthread_equal(sigusr1_thread, threads[i].thread)) {<br>
+                       tst_res(TFAIL, "SIGUSR1 delivered to wrong thread");<br>
+                       return;<br>
+               }<br>
+       }<br>
+<br>
+       stop_threads();<br></blockquote><div><br></div><div class="gmail_default" style="font-size:small">Since we have set the .cleanup function as stop_threads() in tst_test struct, I think</div><div class="gmail_default" style="font-size:small">we can remove it here.</div><div class="gmail_default" style="font-size:small"></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+       tst_res(TPASS, "SIGUSR1 delivered to correct threads");<br>
+}<br>
+<br>
+static void setup(void)<br>
+{<br>
+       if (tst_parse_int(str_threads, &n_threads, 1, INT_MAX))<br>
+               tst_brk(TBROK, "Invalid number of threads '%s'", str_threads);<br>
+<br>
+       threads = SAFE_MALLOC(sizeof(*threads) * n_threads);<br>
+<br>
+       struct sigaction sigusr1 = {<br>
+               .sa_handler = sigusr1_handler,<br>
+       };<br>
+       SAFE_SIGACTION(SIGUSR1, &sigusr1, NULL);<br>
+}<br>
+<br>
+static struct tst_option options[] = {<br>
+       {"t:", &str_threads, "-t       Number of threads (default 10)"},<br>
+       {NULL, NULL, NULL},<br>
+};<br>
+<br>
+static struct tst_test test = {<br>
+       .options = options,<br>
+       .needs_checkpoints = 1,<br>
+       .setup = setup,<br>
+       .test_all = run,<br>
+       .cleanup = stop_threads,<br>
+};<br>
-- <br>
2.7.4<br>
<br>
<br>
-- <br>
Mailing list info: <a href="https://lists.linux.it/listinfo/ltp" rel="noreferrer" target="_blank">https://lists.linux.it/listinfo/ltp</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div></div>