diff options
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) |