aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyril Hrubis <chrubis@suse.cz>2015-02-17 17:16:09 +0100
committerCyril Hrubis <chrubis@suse.cz>2015-02-18 12:04:21 +0100
commit9f136a48c6205362cd8d35c726491ca93cb16514 (patch)
tree3c09cdf3ffc58f704b5429267890570ed8667cb3
parenta3edcb7cc27983f3ce03db4bdc759f471e7806f2 (diff)
downloadltp-9f136a48c6205362cd8d35c726491ca93cb16514.tar.gz
lib: Rewrite checkpoint synchronization
* Rewrite checkpoint synchronization (based on futexes now) * Fix all testcases to use the new interface * Update docs Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
-rw-r--r--doc/test-writing-guidelines.txt102
-rw-r--r--include/tst_checkpoint.h88
-rw-r--r--lib/tests/tst_checkpoint.c (renamed from lib/tests/tst_checkpoint_child.c)13
-rw-r--r--lib/tests/tst_checkpoint_child_exits.c59
-rw-r--r--lib/tests/tst_checkpoint_parent.c60
-rw-r--r--lib/tests/tst_checkpoint_wait_timeout.c (renamed from lib/tests/tst_checkpoint_parent_exits.c)11
-rw-r--r--lib/tests/tst_checkpoint_wake_timeout.c (renamed from lib/tests/tst_checkpoint_no_child.c)14
-rw-r--r--lib/tst_checkpoint.c289
-rw-r--r--testcases/kernel/containers/mountns/mountns01.c16
-rw-r--r--testcases/kernel/containers/mountns/mountns02.c16
-rw-r--r--testcases/kernel/containers/mountns/mountns03.c19
-rw-r--r--testcases/kernel/containers/mountns/mountns_helper.h7
-rw-r--r--testcases/kernel/containers/netns/netns_netlink.c8
-rw-r--r--testcases/kernel/containers/sysvipc/msg_comm.c18
-rw-r--r--testcases/kernel/containers/sysvipc/sem_comm.c32
-rw-r--r--testcases/kernel/containers/sysvipc/shm_comm.c22
-rw-r--r--testcases/kernel/syscalls/creat/creat07.c18
-rw-r--r--testcases/kernel/syscalls/creat/creat07_child.c8
-rw-r--r--testcases/kernel/syscalls/flock/flock03.c8
-rw-r--r--testcases/kernel/syscalls/mmap/mmap16.c13
-rw-r--r--testcases/kernel/syscalls/setpgid/setpgid03.c17
-rw-r--r--testcases/kernel/syscalls/setpgid/setpgid03_child.c11
-rw-r--r--testcases/kernel/syscalls/waitid/waitid02.c13
23 files changed, 267 insertions, 595 deletions
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 888b43063..e2b455ec7 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -195,7 +195,7 @@ const char *dataroot = tst_dataroot();
-------------------------------------------------------------------------------
Datafiles can also be accessed as '$LTPROOT/testcases/data/$TCID/...',
-but '$LTP_DATAROOT' and 'tst_dataroot()' are preffered as these can be used
+but '$LTP_DATAROOT' and 'tst_dataroot()' are preferred as these can be used
when running testcases directly in git tree as well as from install
location.
@@ -634,50 +634,62 @@ return value into the overall test result.
2.2.8 Fork() and Parent-child synchronization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-As LTP tests are written for Linux, most of the test involves fork()-ing and
-parent-child process synchronization. We have a checkpoint library code
-that works even for two different processes, all they need to is to run with
-the same working directory (they use FIFO for synchronization). The checkpoint
-interface provides two pairs of signal and wait functions. One pair to be used
-to signal child from parent and second to signal parent from child.
-
-Checkpoint is represented by 'struct tst_checkpoint', which has to be
-initialized before first usage and FIFO has to be created. This is
-usually done in parent process in single step by calling
-'tst_checkpoint_create()'.
-
-Child processes created via fork() are ready to use tst_checkpoint_*
-synchronization functions, as they inherited already initialized
-'struct tst_checkpoint'.
-
-Child processes started via exec*, or any other process can use already
-created FIFO, provided they initialize 'struct tst_checkpoint' first by
-call to 'tst_checkpoint_init()'. This function does not create any FIFO,
-it relies on fact, that it was already created by some other process.
-Note, that if you use multiple FIFOs in this scenario, these should be
-initialized in same order as in process you are sychronizing against.
-
-IMPORTANT: Be aware, that following scenario is _NOT_ safe when using
- only single checkpoint. You are advised to use two checkpoints
- in this case.
-
-* tst_checkpoint_signal_child() followed by tst_checkpoint_parent_wait()
-
- parent | child
--------------------------------+-------------------------------
- | tst_checkpoint_child_wait()
- | blocking read, waits until
- | parent opens write side
-tst_checkpoint_signal_child() |
- NONBLOCK write |
- | child is now able to read
- | from FIFO
-tst_checkpoint_parent_wait() |
- NONBLOCK read parent able to |
- read from FIFO and can race |
- with read in child |
- | tst_checkpoint_signal_parent()
--------------------------------+--------------------------------
+As LTP tests are written for Linux, most of the tests involve fork()-ing and
+parent-child process synchronization. To solve this problem LTP has checkpoint
+library that provides up to page_size / sizeof(uint32_t) wait/wake pairs. The
+checkpoint library expects all synchronized processes to run with the same
+working directory (it uses shared memory backed with a file for futex based
+synchronization).
+
+The library must be initialized with 'TST_CHECKPOINT_INIT()' function (which
+creates a page of shared memory to be used with futexes). The function takes a
+cleanup callback as a parameter which is used to remove the test temporary
+directory before the process exits if something went wrong.
+
+IMPORTANT: As the init function creates a file the 'tst_tmpdir()' must be
+ called beforehand to create a temporary directory.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include "test.h"
+
+TST_SAFE_CHECKPOINT_WAIT(cleanup_fn, id)
+
+TST_SAFE_CHECKPOINT_WAKE(cleanup_fn, id)
+
+TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake)
+
+TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup_fn, id)
+-------------------------------------------------------------------------------
+
+The checkpoint interface provides pair of wake and wait functions. The 'id' is
+unsigned integer which specifies checkpoint to wake/wait for.
+
+The 'TST_SAFE_CHECKPOINT_WAIT()' suspends process execution until it's woken
+up or until timeout is reached.
+
+The 'TST_SAFE_CHECKPOINT_WAKE()' wakes one process waiting on the checkpoint.
+If no process is waiting the function retries until it success or until
+timeout is reached.
+
+If timeout has been reached process exits with appropriate error message (uses
+'tst_brkm()').
+
+The 'TST_SAFE_CHECKPOINT_WAKE2()' does the same as
+'TST_SAFE_CHECKPOINT_WAKE()' but can be used to wake precisely 'nr_wake'
+processes.
+
+The 'TST_SAFE_CHECKPOINT_WAKE_AND_WAIT()' is a shorthand for doing wake and
+then immediately waiting on the same checkpoint.
+
+Child processes created via fork() are ready to use the checkpoint
+synchronization functions, as they inherited the mapped page automatically.
+
+Child processes started via exec*, or any other processes must initialize the
+checkpoint by calling 'TST_CHECKPOINT_INIT()' before usage.
+
+IMPORTANT: The call to 'TST_CHECKPOINT_INIT()' from the child process must pass
+ 'NULL' pointer as a cleanup callback.
For the details of the interface, look into the 'include/tst_checkpoint.h' and
'lib/tests/tst_checkpoint_*'.
diff --git a/include/tst_checkpoint.h b/include/tst_checkpoint.h
index 6ea3366fd..e6b8100b7 100644
--- a/include/tst_checkpoint.h
+++ b/include/tst_checkpoint.h
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2012 Cyril Hrubis chrubis@suse.cz
- * Copyright (C) 2014 Matus Marhefka mmarhefk@redhat.com
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -23,12 +22,13 @@
*/
/*
-
+
Checkpoint - easy to use parent-child synchronization.
- Note that there are two differnt usages and two different wait and signal
- functions. The choice depends on whether we want parent wait for child or
- child for parent.
+ Checkpoint is based on futexes (man futex). The library allocates a page of
+ shared memory for futexes and the id is an offset to it which gives the user
+ up to page_size/sizeof(uint32_t) checkpoint pairs. Up to INT_MAX processes
+ can sleep on single id and can be woken up by single wake.
*/
@@ -37,67 +37,55 @@
#include "test.h"
-
-#define TST_FIFO_LEN 30
-struct tst_checkpoint {
- char file[TST_FIFO_LEN];
- /* child return value in case of failure */
- int retval;
- /* timeout in msecs */
- unsigned int timeout;
-};
-
/*
* Checkpoint initializaton, must be done first.
+ *
+ * NOTE: tst_tmpdir() must be called beforehand.
*/
-#define TST_CHECKPOINT_INIT(self) \
- tst_checkpoint_init(__FILE__, __LINE__, self)
+#define TST_CHECKPOINT_INIT(cleanup_fn) \
+ tst_checkpoint_init(__FILE__, __LINE__, cleanup_fn)
void tst_checkpoint_init(const char *file, const int lineno,
- struct tst_checkpoint *self);
+ void (*cleanup_fn)(void));
-#define TST_CHECKPOINT_CREATE(self) \
- tst_checkpoint_create(__FILE__, __LINE__, self)
-void tst_checkpoint_create(const char *file, const int lineno,
- struct tst_checkpoint *self);
/*
- * Wait called from parent. In case parent waits for child.
+ * Waits for wakeup.
+ *
+ * @id: Checkpoint id, possitive number
+ * @msec_timeout: Timeout in miliseconds, 0 == no timeout
*/
-#define TST_CHECKPOINT_PARENT_WAIT(cleanup_fn, self) \
- tst_checkpoint_parent_wait(__FILE__, __LINE__, (cleanup_fn), self)
-
-void tst_checkpoint_parent_wait(const char *file, const int lineno,
- void (*cleanup_fn)(void),
- struct tst_checkpoint *self);
+int tst_checkpoint_wait(unsigned int id, unsigned int msec_timeout);
/*
- * Wait called from child. In case child waits for parent.
+ * Wakes up sleeping process(es)/thread(s).
+ *
+ * @id: Checkpoint id, possitive number
+ * @nr_wake: Number of processes/threads to wake up
+ * @msec_timeout: Timeout in miliseconds, 0 == no timeout
*/
-#define TST_CHECKPOINT_CHILD_WAIT(self) \
- tst_checkpoint_child_wait(__FILE__, __LINE__, self)
+int tst_checkpoint_wake(unsigned int id, unsigned int nr_wake,
+ unsigned int msec_timeout);
-void tst_checkpoint_child_wait(const char *file, const int lineno,
- struct tst_checkpoint *self);
+void tst_safe_checkpoint_wait(const char *file, const int lineno,
+ void (*cleanup_fn)(void), unsigned int id);
-/*
- * Signals parent that child has reached the checkpoint. Called from child.
- */
-#define TST_CHECKPOINT_SIGNAL_PARENT(self) \
- tst_checkpoint_signal_parent(__FILE__, __LINE__, self)
+void tst_safe_checkpoint_wake(const char *file, const int lineno,
+ void (*cleanup_fn)(void), unsigned int id,
+ unsigned int nr_wake);
-void tst_checkpoint_signal_parent(const char *file, const int lineno,
- struct tst_checkpoint *self);
+#define TST_SAFE_CHECKPOINT_WAIT(cleanup_fn, id) \
+ tst_safe_checkpoint_wait(__FILE__, __LINE__, cleanup_fn, id);
-/*
- * Signals child that parent has reached the checkpoint. Called from parent.
- */
-#define TST_CHECKPOINT_SIGNAL_CHILD(cleanup_fn, self) \
- tst_checkpoint_signal_child(__FILE__, __LINE__, (cleanup_fn), self)
+#define TST_SAFE_CHECKPOINT_WAKE(cleanup_fn, id) \
+ tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1);
+
+#define TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake) \
+ tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, nr_wake);
-void tst_checkpoint_signal_child(const char *file, const int lineno,
- void (*cleanup_fn)(void),
- struct tst_checkpoint *self);
+#define TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup_fn, id) \
+ tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1); \
+ tst_safe_checkpoint_wait(__FILE__, __LINE__, cleanup_fn, id);
#endif /* TST_CHECKPOINT */
diff --git a/lib/tests/tst_checkpoint_child.c b/lib/tests/tst_checkpoint.c
index a13a9a2e4..2cb17a5f7 100644
--- a/lib/tests/tst_checkpoint_child.c
+++ b/lib/tests/tst_checkpoint.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2012-2015 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -25,17 +25,16 @@
#include "test.h"
-char *TCID = "tst_checkpoint_child";
+char *TCID = "tst_checkpoint";
int TST_TOTAL = 1;
int main(void)
{
int pid;
- struct tst_checkpoint checkpoint;
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
pid = fork();
@@ -45,15 +44,15 @@ int main(void)
break;
case 0:
fprintf(stderr, "Child: checkpoint signaling\n");
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
exit(0);
break;
default:
- TST_CHECKPOINT_PARENT_WAIT(NULL, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(tst_rmdir, 0);
fprintf(stderr, "Parent: checkpoint reached\n");
break;
}
-
+
wait(NULL);
tst_rmdir();
return 0;
diff --git a/lib/tests/tst_checkpoint_child_exits.c b/lib/tests/tst_checkpoint_child_exits.c
deleted file mode 100644
index d2e3f7481..000000000
--- a/lib/tests/tst_checkpoint_child_exits.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2012 Cyril Hrubis <chrubis@suse.cz>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <sys/wait.h>
-
-#include "test.h"
-
-char *TCID = "tst_checkpoint_child_exits";
-int TST_TOTAL = 1;
-
-int main(void)
-{
- int pid;
- struct tst_checkpoint checkpoint;
-
- tst_tmpdir();
-
- TST_CHECKPOINT_CREATE(&checkpoint);
-
- pid = fork();
-
- switch (pid) {
- case -1:
- tst_brkm(TBROK | TERRNO, NULL, "Fork failed");
- break;
- case 0:
- fprintf(stderr, "Child: exiting without signaling\n");
- exit(0);
- break;
- default:
- TST_CHECKPOINT_PARENT_WAIT(NULL, &checkpoint);
- fprintf(stderr, "Parent: checkpoint reached\n");
- break;
- }
-
- wait(NULL);
- tst_rmdir();
- return 0;
-}
diff --git a/lib/tests/tst_checkpoint_parent.c b/lib/tests/tst_checkpoint_parent.c
deleted file mode 100644
index a42b37abb..000000000
--- a/lib/tests/tst_checkpoint_parent.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 Cyril Hrubis <chrubis@suse.cz>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <sys/wait.h>
-
-#include "test.h"
-
-char *TCID = "tst_checkpoint_parent";
-int TST_TOTAL = 1;
-
-int main(void)
-{
- int pid;
- struct tst_checkpoint checkpoint;
-
- tst_tmpdir();
-
- TST_CHECKPOINT_CREATE(&checkpoint);
-
- pid = fork();
-
- switch (pid) {
- case -1:
- tst_brkm(TBROK | TERRNO, NULL, "Fork failed");
- break;
- case 0:
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
- fprintf(stderr, "Child: checkpoint reached\n");
- exit(0);
- break;
- default:
- fprintf(stderr, "Parent: checkpoint signaling\n");
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint);
- break;
- }
-
- wait(NULL);
- tst_rmdir();
- return 0;
-}
diff --git a/lib/tests/tst_checkpoint_parent_exits.c b/lib/tests/tst_checkpoint_wait_timeout.c
index 3056c2c69..c5fae670e 100644
--- a/lib/tests/tst_checkpoint_parent_exits.c
+++ b/lib/tests/tst_checkpoint_wait_timeout.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2012-2015 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -25,17 +25,16 @@
#include "test.h"
-char *TCID = "tst_checkpoint_parent_exits";
+char *TCID = "tst_checkpoint_wait_timeout";
int TST_TOTAL = 1;
int main(void)
{
int pid;
- struct tst_checkpoint checkpoint;
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
pid = fork();
@@ -44,7 +43,7 @@ int main(void)
tst_brkm(TBROK | TERRNO, NULL, "Fork failed");
break;
case 0:
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
fprintf(stderr, "Child: checkpoint reached\n");
exit(0);
break;
@@ -54,6 +53,6 @@ int main(void)
exit(0);
break;
}
-
+
return 0;
}
diff --git a/lib/tests/tst_checkpoint_no_child.c b/lib/tests/tst_checkpoint_wake_timeout.c
index 2e721984c..8af1feb18 100644
--- a/lib/tests/tst_checkpoint_no_child.c
+++ b/lib/tests/tst_checkpoint_wake_timeout.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Linux Test Project
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -25,22 +26,15 @@
#include "test.h"
-char *TCID = "tst_checkpoint_no_child";
+char *TCID = "tst_checkpoint_wake_timeout";
int TST_TOTAL = 1;
-static void cleanup(void)
-{
- tst_rmdir();
-}
-
int main(void)
{
- struct tst_checkpoint checkpoint;
-
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
+ TST_SAFE_CHECKPOINT_WAKE(tst_rmdir, 0);
fprintf(stderr, "Parent: checkpoint reached\n");
return 0;
diff --git a/lib/tst_checkpoint.c b/lib/tst_checkpoint.c
index ebc379ee4..79e49ac95 100644
--- a/lib/tst_checkpoint.c
+++ b/lib/tst_checkpoint.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2012 Cyril Hrubis chrubis@suse.cz
- * Copyright (C) 2014 Matus Marhefka mmarhefk@redhat.com
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -22,254 +21,124 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <stdint.h>
+#include <limits.h>
#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <poll.h>
+#include <sys/syscall.h>
+#include <linux/futex.h>
-#include "tst_checkpoint.h"
+#include "test.h"
+#include "safe_macros.h"
-/*
- * Issue open() on 'path' fifo with O_WRONLY flag and wait for
- * a reader up to 'timeout' ms.
- *
- * Returns:
- * >= 0 - file descriptor
- * -1 - an error has occurred (errno is set accordingly)
- *
- */
-int open_wronly_timed(const char *path, unsigned int timeout)
-{
- int fd;
- unsigned int i;
- int interval = 1; /* how often issue open(O_NONBLOCK), in ms */
-
- for (i = 0; i < timeout; i += interval) {
- fd = open(path, O_WRONLY | O_NONBLOCK);
- if (fd < 0) {
- if ((errno == ENXIO) || (errno == EINTR)) {
- usleep(interval * 1000);
+#define DEFAULT_MSEC_TIMEOUT 10000
- continue;
- }
+typedef volatile uint32_t futex_t;
- return -1;
- }
-
- return fd;
- }
-
- errno = ETIMEDOUT;
- return -1;
-}
+static futex_t *futexes;
+static int page_size;
void tst_checkpoint_init(const char *file, const int lineno,
- struct tst_checkpoint *self)
+ void (*cleanup_fn)(void))
{
- static unsigned int fifo_counter = 0;
- int rval;
-
- /* default values */
- rval = snprintf(self->file, TST_FIFO_LEN, "tst_checkopoint_fifo_%u",
- fifo_counter++);
- if (rval < 0) {
- tst_brkm(TBROK, NULL,
- "Failed to create a unique temp file name at %s:%d",
- file, lineno);
- }
- self->retval = 1;
- self->timeout = 5000;
-}
-
-void tst_checkpoint_create(const char *file, const int lineno,
- struct tst_checkpoint *self)
-
-{
-
- if (!tst_tmpdir_created()) {
- tst_brkm(TBROK, NULL, "Checkpoint could be used only in test "
- "temporary directory at %s:%d",
- file, lineno);
- }
-
- tst_checkpoint_init(file, lineno, self);
+ int fd;
- if (mkfifo(self->file, 0666)) {
- tst_brkm(TBROK | TERRNO, NULL,
- "Failed to create fifo '%s' at %s:%d",
- self->file, file, lineno);
+ if (futexes) {
+ tst_brkm(TBROK, cleanup_fn,
+ "%s: %d checkopoints allready initialized",
+ file, lineno);
}
-}
-
-void tst_checkpoint_parent_wait(const char *file, const int lineno,
- void (*cleanup_fn)(void),
- struct tst_checkpoint *self)
-{
- int ret;
- char ch;
- struct pollfd fd;
-
- fd.fd = open(self->file, O_RDONLY | O_NONBLOCK);
- if (fd.fd < 0) {
- tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Failed to open fifo '%s' at %s:%d",
- self->file, file, lineno);
+ /*
+ * The parent test process is responsible for creating the temporary
+ * directory and therefore must pass non-zero cleanup (to remove the
+ * directory if something went wrong).
+ *
+ * We cannot do this check unconditionally because if we need to init
+ * the checkpoint from a binary that was started by exec() the
+ * tst_tmpdir_created() will return false because the tmpdir was
+ * created by parent. In this case we expect the subprogram can call
+ * the init as a first function with NULL as cleanup function.
+ */
+ if (cleanup_fn && !tst_tmpdir_created()) {
+ tst_brkm(TBROK, cleanup_fn,
+ "%s:%d You have to create test temporary directory "
+ "first (call tst_tmpdir())", file, lineno);
}
- fd.events = POLLIN;
- fd.revents = 0;
+ page_size = getpagesize();
- ret = poll(&fd, 1, self->timeout);
-
- switch (ret) {
- case 0:
- close(fd.fd);
- tst_brkm(TBROK, cleanup_fn, "Checkpoint timeouted after "
- "%u msecs at %s:%d", self->timeout, file, lineno);
- break;
- case 1:
- break;
- default:
- tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Poll failed for fifo '%s' at %s:%d",
- self->file, file, lineno);
- }
+ fd = SAFE_OPEN(cleanup_fn, "checkpoint_futex_base_file",
+ O_RDWR | O_CREAT, 0666);
- ret = read(fd.fd, &ch, 1);
+ SAFE_FTRUNCATE(cleanup_fn, fd, page_size);
- switch (ret) {
- case 0:
- close(fd.fd);
- tst_brkm(TBROK, cleanup_fn,
- "The other end of the pipe was closed "
- "unexpectedly at %s:%d", file, lineno);
- break;
- case -1:
- close(fd.fd);
- tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Failed to read from pipe at %s:%d\n",
- file, lineno);
- break;
- }
+ futexes = SAFE_MMAP(cleanup_fn, NULL, page_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (ch != 'c') {
- close(fd.fd);
- tst_brkm(TBROK, cleanup_fn,
- "Wrong data read from the pipe at %s:%d\n",
- file, lineno);
- }
-
- close(fd.fd);
+ SAFE_CLOSE(cleanup_fn, fd);
}
-void tst_checkpoint_child_wait(const char *file, const int lineno,
- struct tst_checkpoint *self)
+int tst_checkpoint_wait(unsigned int id, unsigned int msec_timeout)
{
- int ret, fd;
- char ch;
-
- fd = open(self->file, O_RDONLY);
+ struct timespec timeout;
- if (fd < 0) {
- fprintf(stderr, "CHILD: Failed to open fifo '%s': %s at "
- "%s:%d\n", self->file, strerror(errno),
- file, lineno);
- exit(self->retval);
+ if (id >= page_size / sizeof(uint32_t)) {
+ errno = EOVERFLOW;
+ return -1;
}
-
- ret = read(fd, &ch, 1);
- if (ret == -1) {
- fprintf(stderr, "CHILD: Failed to read from fifo '%s': %s "
- "at %s:%d\n", self->file, strerror(errno),
- file, lineno);
- goto err;
- }
+ timeout.tv_sec = msec_timeout/1000;
+ timeout.tv_nsec = (msec_timeout%1000) * 1000000;
- if (ch != 'p') {
- fprintf(stderr, "CHILD: Wrong data read from the pipe "
- "at %s:%d\n", file, lineno);
- goto err;
- }
-
- close(fd);
- return;
-err:
- close(fd);
- exit(self->retval);
+ return syscall(SYS_futex, &futexes[id], FUTEX_WAIT, futexes[id], &timeout);
}
-void tst_checkpoint_signal_parent(const char *file, const int lineno,
- struct tst_checkpoint *self)
+int tst_checkpoint_wake(unsigned int id, unsigned int nr_wake,
+ unsigned int msec_timeout)
{
- int ret, fd;
-
- fd = open(self->file, O_WRONLY);
+ unsigned int msecs = 0, waked = 0;
- if (fd < 0) {
- fprintf(stderr, "CHILD: Failed to open fifo '%s': %s at %s:%d",
- self->file, strerror(errno), file, lineno);
- exit(self->retval);
+ if (id >= page_size / sizeof(uint32_t)) {
+ errno = EOVERFLOW;
+ return -1;
}
- ret = write(fd, "c", 1);
+ do {
+ waked += syscall(SYS_futex, &futexes[id], FUTEX_WAKE, INT_MAX, NULL);
+ usleep(1000);
+ msecs++;
- switch (ret) {
- case 0:
- fprintf(stderr, "No data written, something is really "
- "screewed; at %s:%d\n", file, lineno);
- goto err;
- break;
- case -1:
- fprintf(stderr, "Failed to write to pipe: %s at %s:%d\n",
- strerror(errno), file, lineno);
- goto err;
- break;
- }
+ if (msecs >= msec_timeout) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ } while (waked != nr_wake);
- close(fd);
- return;
-err:
- close(fd);
- exit(self->retval);
+ return 0;
}
-void tst_checkpoint_signal_child(const char *file, const int lineno,
- void (*cleanup_fn)(void),
- struct tst_checkpoint *self)
+void tst_safe_checkpoint_wait(const char *file, const int lineno,
+ void (*cleanup_fn)(void), unsigned int id)
{
- int ret, fd;
-
- fd = open_wronly_timed(self->file, self->timeout);
+ int ret = tst_checkpoint_wait(id, DEFAULT_MSEC_TIMEOUT);
- if (fd < 0) {
+ if (ret) {
tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Failed to open fifo '%s' at %s:%d",
- self->file, file, lineno);
+ "%s:%d: tst_checkpoint_wait(%u, %i)",
+ file, lineno, id, DEFAULT_MSEC_TIMEOUT);
}
+}
- ret = write(fd, "p", 1);
+void tst_safe_checkpoint_wake(const char *file, const int lineno,
+ void (*cleanup_fn)(void), unsigned int id,
+ unsigned int nr_wake)
+{
+ int ret = tst_checkpoint_wake(id, nr_wake, DEFAULT_MSEC_TIMEOUT);
- switch (ret) {
- case 0:
- close(fd);
- tst_brkm(TBROK, cleanup_fn,
- "No data written, something is really screewed; "
- "at %s:%d\n", file, lineno);
- break;
- case -1:
- close(fd);
+ if (ret) {
tst_brkm(TBROK | TERRNO, cleanup_fn,
- "Failed to write to pipe at %s:%d\n",
- file, lineno);
- break;
+ "%s:%d: tst_checkpoint_wake(%u, %u, %i)",
+ file, lineno, id, nr_wake, DEFAULT_MSEC_TIMEOUT);
}
-
- close(fd);
}
diff --git a/testcases/kernel/containers/mountns/mountns01.c b/testcases/kernel/containers/mountns/mountns01.c
index 490f8dae4..d50cbbada 100644
--- a/testcases/kernel/containers/mountns/mountns01.c
+++ b/testcases/kernel/containers/mountns/mountns01.c
@@ -57,13 +57,12 @@ int child_func(void *arg)
{
int ret = 0;
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
if (access(DIRA"/B", F_OK) == -1)
ret = 2;
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
/* bind mounts DIRB to DIRA making contents of DIRB visible
* in DIRA */
@@ -72,8 +71,7 @@ int child_func(void *arg)
return 1;
}
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
umount(DIRA);
return ret;
@@ -102,20 +100,18 @@ static void test(void)
* in DIRA */
SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
SAFE_UMOUNT(cleanup, DIRA);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
if (access(DIRA"/B", F_OK) == 0)
tst_resm(TPASS, "shared mount in child passed");
else
tst_resm(TFAIL, "shared mount in child failed");
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
SAFE_WAIT(cleanup, &status);
diff --git a/testcases/kernel/containers/mountns/mountns02.c b/testcases/kernel/containers/mountns/mountns02.c
index f4edc8532..56533c00a 100644
--- a/testcases/kernel/containers/mountns/mountns02.c
+++ b/testcases/kernel/containers/mountns/mountns02.c
@@ -57,13 +57,12 @@ int child_func(void *arg)
{
int ret = 0;
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0))
ret = 2;
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
/* bind mounts DIRB to DIRA making contents of DIRB visible
* in DIRA */
@@ -72,8 +71,7 @@ int child_func(void *arg)
return 1;
}
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
umount(DIRA);
return ret;
@@ -102,20 +100,18 @@ static void test(void)
* in DIRA */
SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
SAFE_UMOUNT(cleanup, DIRA);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0))
tst_resm(TFAIL, "private mount in child failed");
else
tst_resm(TPASS, "private mount in child passed");
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
SAFE_WAIT(cleanup, &status);
diff --git a/testcases/kernel/containers/mountns/mountns03.c b/testcases/kernel/containers/mountns/mountns03.c
index d97965949..8457faf10 100644
--- a/testcases/kernel/containers/mountns/mountns03.c
+++ b/testcases/kernel/containers/mountns/mountns03.c
@@ -69,15 +69,13 @@ int child_func(void *arg)
return 1;
}
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
/* checks that shared mounts propagates to slave mount */
if (access(DIRA"/B", F_OK) == -1)
ret = 2;
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
/* bind mounts DIRB to DIRA making contents of DIRB visible
* in DIRA */
@@ -86,8 +84,7 @@ int child_func(void *arg)
return 1;
}
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
umount(DIRA);
return ret;
@@ -113,19 +110,17 @@ static void test(void)
tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
/* waits for child to make a slave mount */
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
/* bind mounts DIRB to DIRA making contents of DIRB visible
* in DIRA */
SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
SAFE_UMOUNT(cleanup, DIRA);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0);
/* checks that slave mount doesn't propagate to shared mount */
if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1))
@@ -133,7 +128,7 @@ static void test(void)
else
tst_resm(TFAIL, "propagation form slave mount failed");
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
SAFE_WAIT(cleanup, &status);
diff --git a/testcases/kernel/containers/mountns/mountns_helper.h b/testcases/kernel/containers/mountns/mountns_helper.h
index d4a6a91fa..023205c78 100644
--- a/testcases/kernel/containers/mountns/mountns_helper.h
+++ b/testcases/kernel/containers/mountns/mountns_helper.h
@@ -17,12 +17,8 @@
#include "test.h"
#include "safe_macros.h"
-
#define DIRA "A"
#define DIRB "B"
-struct tst_checkpoint checkpoint1;
-struct tst_checkpoint checkpoint2;
-
static int dummy_child(void *v)
{
@@ -57,8 +53,7 @@ static void setup(void)
tst_require_root(NULL);
check_newns();
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint1);
- TST_CHECKPOINT_CREATE(&checkpoint2);
+ TST_CHECKPOINT_INIT(tst_rmdir);
SAFE_MKDIR(cleanup, DIRA, 0777);
SAFE_MKDIR(cleanup, DIRB, 0777);
SAFE_TOUCH(cleanup, DIRA"/A", 0, NULL);
diff --git a/testcases/kernel/containers/netns/netns_netlink.c b/testcases/kernel/containers/netns/netns_netlink.c
index 55b8abbd1..478536c57 100644
--- a/testcases/kernel/containers/netns/netns_netlink.c
+++ b/testcases/kernel/containers/netns/netns_netlink.c
@@ -50,8 +50,6 @@
char *TCID = "netns_netlink";
int TST_TOTAL = 1;
-struct tst_checkpoint checkpoint;
-
static void cleanup(void)
{
@@ -64,7 +62,7 @@ static void setup(void)
check_iproute(IP_TUNTAP_MIN_VER);
check_netns();
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
}
int child_func(void)
@@ -92,7 +90,7 @@ int child_func(void)
}
/* waits for parent to create an interface */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
/* To get rid of "resource temporarily unavailable" errors
* when testing with -i option */
@@ -150,7 +148,7 @@ static void test(void)
tst_brkm(TBROK | TERRNO, cleanup, "system failed");
/* allow child to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
SAFE_WAITPID(cleanup, pid, &status, 0);
diff --git a/testcases/kernel/containers/sysvipc/msg_comm.c b/testcases/kernel/containers/sysvipc/msg_comm.c
index 479069559..80409d400 100644
--- a/testcases/kernel/containers/sysvipc/msg_comm.c
+++ b/testcases/kernel/containers/sysvipc/msg_comm.c
@@ -43,14 +43,12 @@
#define MSGSIZE 50
char *TCID = "msg_comm";
int TST_TOTAL = 1;
-struct tst_checkpoint checkpoint1;
-struct tst_checkpoint checkpoint2;
+
struct sysv_msg {
long mtype;
char mtext[MSGSIZE];
};
-
static void cleanup(void)
{
tst_rmdir();
@@ -61,8 +59,7 @@ static void setup(void)
tst_require_root(NULL);
check_newipc();
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint1);
- TST_CHECKPOINT_CREATE(&checkpoint2);
+ TST_CHECKPOINT_INIT(tst_rmdir);
}
int chld1_msg(void *arg)
@@ -86,7 +83,7 @@ int chld1_msg(void *arg)
}
/* wait for child2 to write into the message queue */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
/* if child1 message queue has changed (by child2) report fail */
n = msgrcv(id, &rec, sizeof(struct sysv_msg) - sizeof(long),
@@ -102,7 +99,7 @@ int chld1_msg(void *arg)
}
/* tell child2 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
msgctl(id, IPC_RMID, NULL);
return rval;
@@ -127,11 +124,8 @@ int chld2_msg(void *arg)
return 2;
}
- /* tell child1 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint2);
-
- /* wait for child1 */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
+ /* tell child1 to continue and wait for it */
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
msgctl(id, IPC_RMID, NULL);
return 0;
diff --git a/testcases/kernel/containers/sysvipc/sem_comm.c b/testcases/kernel/containers/sysvipc/sem_comm.c
index 8d3b7aeef..b44be6db0 100644
--- a/testcases/kernel/containers/sysvipc/sem_comm.c
+++ b/testcases/kernel/containers/sysvipc/sem_comm.c
@@ -37,13 +37,9 @@
#include "libclone.h"
#include "ipcns_helper.h"
-
#define TESTKEY 124426L
char *TCID = "sem_comm";
int TST_TOTAL = 1;
-struct tst_checkpoint checkpoint1;
-struct tst_checkpoint checkpoint2;
-
static void cleanup(void)
{
@@ -55,8 +51,7 @@ static void setup(void)
tst_require_root(NULL);
check_newipc();
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint1);
- TST_CHECKPOINT_CREATE(&checkpoint2);
+ TST_CHECKPOINT_INIT(tst_rmdir);
}
int chld1_sem(void *arg)
@@ -76,11 +71,8 @@ int chld1_sem(void *arg)
return 2;
}
- /* tell child2 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
-
- /* wait for child2 to create the semaphore */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ /* tell child2 to continue and wait for it to create the semaphore */
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
sm.sem_num = 0;
sm.sem_op = -1;
@@ -91,11 +83,8 @@ int chld1_sem(void *arg)
return 2;
}
- /* tell child2 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
-
- /* wait for child2 to lock the semaphore */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ /* tell child2 to continue and wait for it to lock the semaphore */
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
sm.sem_op = 1;
semop(id, &sm, 1);
@@ -110,7 +99,7 @@ int chld2_sem(void *arg)
struct sembuf sm;
/* wait for child1 to create the semaphore */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
id = semget(TESTKEY, 1, IPC_CREAT);
if (id == -1) {
@@ -124,11 +113,8 @@ int chld2_sem(void *arg)
return 2;
}
- /* tell child1 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint2);
-
- /* wait for child1 to lock the semaphore */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
+ /* tell child1 to continue and wait for it to lock the semaphore */
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
sm.sem_num = 0;
sm.sem_op = -1;
@@ -144,7 +130,7 @@ int chld2_sem(void *arg)
}
/* tell child1 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
sm.sem_op = 1;
semop(id, &sm, 1);
diff --git a/testcases/kernel/containers/sysvipc/shm_comm.c b/testcases/kernel/containers/sysvipc/shm_comm.c
index fb06b659e..16823a2b6 100644
--- a/testcases/kernel/containers/sysvipc/shm_comm.c
+++ b/testcases/kernel/containers/sysvipc/shm_comm.c
@@ -43,9 +43,6 @@
#define SHMSIZE 50
char *TCID = "shm_comm";
int TST_TOTAL = 1;
-struct tst_checkpoint checkpoint1;
-struct tst_checkpoint checkpoint2;
-
static void cleanup(void)
{
@@ -57,8 +54,7 @@ static void setup(void)
tst_require_root(NULL);
check_newipc();
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint1);
- TST_CHECKPOINT_CREATE(&checkpoint2);
+ TST_CHECKPOINT_INIT(tst_rmdir);
}
int chld1_shm(void *arg)
@@ -80,18 +76,14 @@ int chld1_shm(void *arg)
*shmem = 'A';
- /* tell child2 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
-
- /* wait for child2 */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
/* if child1 shared segment has changed (by child2) report fail */
if (*shmem != 'A')
rval = 1;
/* tell child2 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
shmdt(shmem);
shmctl(id, IPC_RMID, NULL);
@@ -116,15 +108,11 @@ int chld2_shm(void *arg)
}
/* wait for child1 to write to his segment */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
*shmem = 'B';
- /* tell child1 to continue */
- TST_CHECKPOINT_SIGNAL_CHILD(NULL, &checkpoint2);
-
- /* wait for child1 */
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint1);
+ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
shmdt(shmem);
shmctl(id, IPC_RMID, NULL);
diff --git a/testcases/kernel/syscalls/creat/creat07.c b/testcases/kernel/syscalls/creat/creat07.c
index 2260ac7ba..bbebf7b63 100644
--- a/testcases/kernel/syscalls/creat/creat07.c
+++ b/testcases/kernel/syscalls/creat/creat07.c
@@ -38,11 +38,9 @@
char *TCID = "creat07";
int TST_TOTAL = 1;
-static void setup(char *);
+static void setup(void);
static void cleanup(void);
-static struct tst_checkpoint checkpoint;
-
int main(int ac, char **av)
{
int lc;
@@ -52,7 +50,7 @@ int main(int ac, char **av)
if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
- setup(av[0]);
+ setup();
for (lc = 0; TEST_LOOPING(lc); lc++) {
@@ -70,7 +68,7 @@ int main(int ac, char **av)
exit(1);
}
- TST_CHECKPOINT_PARENT_WAIT(NULL, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
TEST(creat(TEST_APP, O_WRONLY));
@@ -86,24 +84,24 @@ int main(int ac, char **av)
if (kill(pid, SIGKILL) == -1)
tst_resm(TINFO | TERRNO, "kill failed");
-
+
if (wait(NULL) == -1)
tst_brkm(TBROK|TERRNO, cleanup, "wait failed");
}
-
+
cleanup();
tst_exit();
}
-static void setup(char *app)
+static void setup(void)
{
tst_sig(FORK, DEF_HANDLER, cleanup);
tst_tmpdir();
+ TST_CHECKPOINT_INIT(tst_rmdir);
+
TST_RESOURCE_COPY(cleanup, TEST_APP, NULL);
-
- TST_CHECKPOINT_CREATE(&checkpoint);
TEST_PAUSE;
}
diff --git a/testcases/kernel/syscalls/creat/creat07_child.c b/testcases/kernel/syscalls/creat/creat07_child.c
index 164160102..0273fde31 100644
--- a/testcases/kernel/syscalls/creat/creat07_child.c
+++ b/testcases/kernel/syscalls/creat/creat07_child.c
@@ -26,13 +26,9 @@ char *TCID = "creat07_child";
int main(void)
{
- struct tst_checkpoint checkpoint;
+ TST_CHECKPOINT_INIT(NULL);
- /* we are already in tmpdir, so only initialize checkpoint,
- * fifo has been created by parent already. */
- TST_CHECKPOINT_INIT(&checkpoint);
-
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
for (;;) {
sleep(1);
diff --git a/testcases/kernel/syscalls/flock/flock03.c b/testcases/kernel/syscalls/flock/flock03.c
index aa38d8825..f264b44c9 100644
--- a/testcases/kernel/syscalls/flock/flock03.c
+++ b/testcases/kernel/syscalls/flock/flock03.c
@@ -56,8 +56,6 @@ static void childfunc_uc(void)
char *TCID = "flock03";
int TST_TOTAL = 3;
-static struct tst_checkpoint checkpoint;
-
int main(int argc, char **argv)
{
int lc;
@@ -109,7 +107,7 @@ int main(int argc, char **argv)
tst_resm(TPASS,
"Parent: Initial attempt to flock() passed");
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
if ((waitpid(pid, &status, 0)) < 0) {
tst_resm(TFAIL, "wait() failed");
@@ -132,7 +130,7 @@ static void childfunc(int fd)
{
int fd2;
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
fd2 = open(FILE_NAME, O_RDWR);
@@ -185,7 +183,7 @@ static void setup(void)
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
fd = creat(FILE_NAME, 0666);
if (fd < 0) {
diff --git a/testcases/kernel/syscalls/mmap/mmap16.c b/testcases/kernel/syscalls/mmap/mmap16.c
index 89483ec44..5fe8cb01f 100644
--- a/testcases/kernel/syscalls/mmap/mmap16.c
+++ b/testcases/kernel/syscalls/mmap/mmap16.c
@@ -50,7 +50,6 @@ static int mount_flag;
static int chdir_flag;
static int page_size;
-static struct tst_checkpoint checkpoint1, checkpoint2;
static int bug_reproduced;
char *TCID = "mmap16";
@@ -112,7 +111,7 @@ static void do_test(void)
fd = SAFE_OPEN(cleanup, "testfilep", O_RDWR);
memset(buf, 'a', FS_BLOCKSIZE);
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint1);
+ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
while (1) {
ret = write(fd, buf, FS_BLOCKSIZE);
if (ret < 0) {
@@ -125,7 +124,7 @@ static void do_test(void)
}
}
SAFE_CLOSE(cleanup, fd);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
}
wait(&status);
@@ -155,6 +154,8 @@ static void setup(void)
TEST_PAUSE;
tst_tmpdir();
+ TST_CHECKPOINT_INIT(tst_rmdir);
+
page_size = getpagesize();
device = tst_acquire_device(cleanup);
@@ -173,8 +174,6 @@ static void setup(void)
SAFE_CHDIR(cleanup, MNTPOINT);
chdir_flag = 1;
- TST_CHECKPOINT_CREATE(&checkpoint1);
- TST_CHECKPOINT_CREATE(&checkpoint2);
}
static void do_child(void)
@@ -222,8 +221,8 @@ static void do_child(void)
* if not, the data 'A', 'B', 'C' will be silently discarded later when
* kernel writepage is called, that means data corruption.
*/
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint1);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint2);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
for (offset = FS_BLOCKSIZE; offset < page_size; offset += FS_BLOCKSIZE)
addr[offset] = 'a';
diff --git a/testcases/kernel/syscalls/setpgid/setpgid03.c b/testcases/kernel/syscalls/setpgid/setpgid03.c
index 17cecbaf5..9c7f826af 100644
--- a/testcases/kernel/syscalls/setpgid/setpgid03.c
+++ b/testcases/kernel/syscalls/setpgid/setpgid03.c
@@ -43,8 +43,6 @@
char *TCID = "setpgid03";
int TST_TOTAL = 1;
-static struct tst_checkpoint checkpoint;
-
static void do_child(void);
static void setup(void);
static void cleanup(void);
@@ -82,7 +80,7 @@ int main(int ac, char **av)
#endif
}
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
rval = setpgid(child_pid, getppid());
if (rval == -1 && errno == EPERM) {
tst_resm(TPASS, "setpgid failed with EPERM");
@@ -91,7 +89,7 @@ int main(int ac, char **av)
"retval %d, errno %d, expected errno %d",
rval, errno, EPERM);
}
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
if (wait(&status) < 0)
tst_resm(TFAIL | TERRNO, "wait() for child 1 failed");
@@ -111,7 +109,7 @@ int main(int ac, char **av)
exit(127);
}
- TST_CHECKPOINT_PARENT_WAIT(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
rval = setpgid(child_pid, getppid());
if (rval == -1 && errno == EACCES) {
tst_resm(TPASS, "setpgid failed with EACCES");
@@ -120,7 +118,7 @@ int main(int ac, char **av)
"retval %d, errno %d, expected errno %d",
rval, errno, EACCES);
}
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
if (wait(&status) < 0)
tst_resm(TFAIL | TERRNO, "wait() for child 2 failed");
@@ -141,9 +139,9 @@ static void do_child(void)
exit(2);
}
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
exit(0);
}
@@ -154,8 +152,7 @@ static void setup(void)
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
- checkpoint.timeout = 10000;
+ TST_CHECKPOINT_INIT(tst_rmdir);
umask(0);
diff --git a/testcases/kernel/syscalls/setpgid/setpgid03_child.c b/testcases/kernel/syscalls/setpgid/setpgid03_child.c
index c9ea87f6e..2657422a6 100644
--- a/testcases/kernel/syscalls/setpgid/setpgid03_child.c
+++ b/testcases/kernel/syscalls/setpgid/setpgid03_child.c
@@ -23,15 +23,10 @@ char *TCID = "setpgid03_child";
int main(void)
{
- struct tst_checkpoint checkpoint;
+ TST_CHECKPOINT_INIT(NULL);
- /* we are already in tmpdir, so only initialize checkpoint,
- * fifo has been created by parent already. */
- TST_CHECKPOINT_INIT(&checkpoint);
- checkpoint.timeout = 10000;
-
- TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
return 0;
}
diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c
index 5f6917cf0..e6c62bb5c 100644
--- a/testcases/kernel/syscalls/waitid/waitid02.c
+++ b/testcases/kernel/syscalls/waitid/waitid02.c
@@ -144,7 +144,6 @@ struct testcase_t tdat[] = {
char *TCID = "waitid02";
static int TST_TOTAL = ARRAY_SIZE(tdat);
-static struct tst_checkpoint checkpoint;
static void makechild(struct testcase_t *t, void (*childfn)(void))
{
@@ -174,13 +173,13 @@ static void dummy_child(void)
static void waiting_child(void)
{
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
}
static void stopped_child(void)
{
kill(getpid(), SIGSTOP);
- TST_CHECKPOINT_CHILD_WAIT(&checkpoint);
+ TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
}
static void setup2(struct testcase_t *t)
@@ -190,7 +189,7 @@ static void setup2(struct testcase_t *t)
static void cleanup2(struct testcase_t *t)
{
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
wait4child(t->child);
}
@@ -215,7 +214,7 @@ static void setup5(struct testcase_t *t)
static void cleanup5(struct testcase_t *t)
{
kill(t->child, SIGCONT);
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
wait4child(t->child);
}
@@ -231,7 +230,7 @@ static void setup6(struct testcase_t *t)
static void cleanup6(struct testcase_t *t)
{
- TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint);
+ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
wait4child(t->child);
}
@@ -239,7 +238,7 @@ static void setup(void)
{
TEST_PAUSE;
tst_tmpdir();
- TST_CHECKPOINT_CREATE(&checkpoint);
+ TST_CHECKPOINT_INIT(tst_rmdir);
}
static void cleanup(void)