This patch changes name of tst_futexes array and is using it to
store futexes as well as propagated values. The values are of newly
defined type: chp_value_t, which is initially defined as int32_t.

Patch is adding optional 3rd parameter to TST_SAFE_CHECKPOINT_WAKE,
which can be used to propagate this integer.
TST_SAFE_CHECKPOINT_WAIT has been changed to return it.

Signed-off-by: Jan Stancek <jstan...@redhat.com>
---
 doc/test-writing-guidelines.txt | 10 ++++-
 include/tst_checkpoint.h        | 55 ++++++++++++++++++------
 lib/tests/tst_checkpoint.c      | 10 +++--
 lib/tst_checkpoint.c            | 92 ++++++++++++++++++++++++++++++++---------
 lib/tst_tmpdir.c                |  9 ++--
 5 files changed, 135 insertions(+), 41 deletions(-)

diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 2c40e3d..974315e 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -670,8 +670,9 @@ IMPORTANT: As the init function creates a file the 
'tst_tmpdir()' must be
 TST_SAFE_CHECKPOINT_WAIT(cleanup_fn, id)
 
 TST_SAFE_CHECKPOINT_WAKE(cleanup_fn, id)
+TST_SAFE_CHECKPOINT_WAKE(cleanup_fn, id, val)
 
-TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake)
+TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake, val)
 
 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup_fn, id)
 -------------------------------------------------------------------------------
@@ -689,9 +690,14 @@ timeout is reached.
 If timeout has been reached process exits with appropriate error message (uses
 'tst_brkm()').
 
+'TST_SAFE_CHECKPOINT_WAKE' can optionally propagate an integer value
+(of type chp_value_t, see include/tst_checkpoint.h) to matching
+'TST_SAFE_CHECKPOINT_WAIT' call. This value can be passed as optional
+3rd parameter and is then returned by 'TST_SAFE_CHECKPOINT_WAIT' call.
+
 The 'TST_SAFE_CHECKPOINT_WAKE2()' does the same as
 'TST_SAFE_CHECKPOINT_WAKE()' but can be used to wake precisely 'nr_wake'
-processes.
+processes. 'val' is a value that will be propagated to WAIT calls.
 
 The 'TST_SAFE_CHECKPOINT_WAKE_AND_WAIT()' is a shorthand for doing wake and
 then immediately waiting on the same checkpoint.
diff --git a/include/tst_checkpoint.h b/include/tst_checkpoint.h
index e6b8100..7d67d9c 100644
--- a/include/tst_checkpoint.h
+++ b/include/tst_checkpoint.h
@@ -37,6 +37,8 @@
 
 #include "test.h"
 
+typedef volatile int32_t chp_value_t;
+
 /*
  * Checkpoint initializaton, must be done first.
  *
@@ -55,8 +57,10 @@ void tst_checkpoint_init(const char *file, const int lineno,
  *
  * @id: Checkpoint id, possitive number
  * @msec_timeout: Timeout in miliseconds, 0 == no timeout
+ * @pval: store propagated value to pval, ignored if pval == NULL
  */
-int tst_checkpoint_wait(unsigned int id, unsigned int msec_timeout);
+int tst_checkpoint_wait(unsigned int id, chp_value_t *pval,
+                       unsigned int msec_timeout);
 
 /*
  * Wakes up sleeping process(es)/thread(s).
@@ -64,28 +68,53 @@ int tst_checkpoint_wait(unsigned int id, unsigned int 
msec_timeout);
  * @id: Checkpoint id, possitive number
  * @nr_wake: Number of processes/threads to wake up
  * @msec_timeout: Timeout in miliseconds, 0 == no timeout
+ * @pval: propagate value of *pval, ignored if pval == NULL
  */
 int tst_checkpoint_wake(unsigned int id, unsigned int nr_wake,
-                        unsigned int msec_timeout);
+                       chp_value_t *pval,
+                       unsigned int msec_timeout);
 
 void tst_safe_checkpoint_wait(const char *file, const int lineno,
-                              void (*cleanup_fn)(void), unsigned int id);
+                             void (*cleanup_fn)(void), unsigned int id,
+                             chp_value_t *pval);
 
 void tst_safe_checkpoint_wake(const char *file, const int lineno,
-                              void (*cleanup_fn)(void), unsigned int id,
-                              unsigned int nr_wake);
+                             void (*cleanup_fn)(void), unsigned int id,
+                             unsigned int nr_wake, chp_value_t *pval);
 
-#define TST_SAFE_CHECKPOINT_WAIT(cleanup_fn, id) \
-        tst_safe_checkpoint_wait(__FILE__, __LINE__, cleanup_fn, id);
 
-#define TST_SAFE_CHECKPOINT_WAKE(cleanup_fn, id) \
-        tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1);
+#define SELECT_MACRO(_1, _2, _3, NAME, ...) NAME
+
+#define TST_SAFE_CHECKPOINT_WAKE(...) \
+               SELECT_MACRO(__VA_ARGS__, \
+                            TST_SAFE_CHECKPOINT_WAKE_3PARAM, \
+                            TST_SAFE_CHECKPOINT_WAKE_2PARAM)(__VA_ARGS__)
+
+#define TST_SAFE_CHECKPOINT_WAKE_2PARAM(cleanup_fn, id) \
+       tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1, NULL)
 
-#define TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake) \
-        tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, nr_wake);
+#define TST_SAFE_CHECKPOINT_WAKE_3PARAM(cleanup_fn, id, val) \
+{ \
+       chp_value_t tmp = val; \
+       tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1, &tmp); \
+}
+
+#define TST_SAFE_CHECKPOINT_WAKE2(cleanup_fn, id, nr_wake, val) \
+{ \
+       chp_value_t tmp = val; \
+       tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, \
+                                nr_wake, &tmp); \
+}
+
+#define TST_SAFE_CHECKPOINT_WAIT(cleanup_fn, id) \
+({ \
+       chp_value_t tmp; \
+       tst_safe_checkpoint_wait(__FILE__, __LINE__, cleanup_fn, id, &tmp); \
+       tmp; \
+})
 
 #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);
+       tst_safe_checkpoint_wake(__FILE__, __LINE__, cleanup_fn, id, 1, NULL); \
+       tst_safe_checkpoint_wait(__FILE__, __LINE__, cleanup_fn, id, NULL)
 
 #endif /* TST_CHECKPOINT */
diff --git a/lib/tests/tst_checkpoint.c b/lib/tests/tst_checkpoint.c
index 2cb17a5..f2c0019 100644
--- a/lib/tests/tst_checkpoint.c
+++ b/lib/tests/tst_checkpoint.c
@@ -25,12 +25,14 @@
 
 #include "test.h"
 
+#define TEST_VALUE 0xCAFE
+
 char *TCID = "tst_checkpoint";
 int TST_TOTAL = 1;
 
 int main(void)
 {
-       int pid;
+       int pid, val;
 
        tst_tmpdir();
 
@@ -44,12 +46,14 @@ int main(void)
        break;
        case 0:
                fprintf(stderr, "Child: checkpoint signaling\n");
-               TST_SAFE_CHECKPOINT_WAKE(NULL, 0);
+               TST_SAFE_CHECKPOINT_WAKE(NULL, 0, TEST_VALUE);
                exit(0);
        break;
        default:
-               TST_SAFE_CHECKPOINT_WAIT(tst_rmdir, 0);
+               val = TST_SAFE_CHECKPOINT_WAIT(tst_rmdir, 0);
                fprintf(stderr, "Parent: checkpoint reached\n");
+               fprintf(stderr, "Propagated value matches: %d\n",
+                               TEST_VALUE == val);
        break;
        }
 
diff --git a/lib/tst_checkpoint.c b/lib/tst_checkpoint.c
index a2c9563..08ca944 100644
--- a/lib/tst_checkpoint.c
+++ b/lib/tst_checkpoint.c
@@ -33,15 +33,50 @@
 
 #define DEFAULT_MSEC_TIMEOUT 10000
 
-futex_t *tst_futexes;
-static int page_size;
+#define MAX_CHECKPOINTS 256
+
+/*
+ * tst_checkpoints is mmapped file, that stores futexes and values
+ * propagated between checkpoint_wake and wait. The space allocated
+ * is for up to MAX_CHECKPOINTS checkpoints and is organized in
+ * following way:
+ *
+ * ----------------------------------------------------------------
+ * | FUTEX1 FUTEX2 FUTEX3 ... | VALUE1 VALUE2 VALUE3 ... | UNUSED |
+ * ---------------------------|------------------------------------
+ * ^                                                              ^
+ * |                                                              |
+ * +-- tst_checkpoints                     aligned to PAGE_SIZE --+
+ *
+ * Where FUTEXes are of type futex_t, and VALUEs of chp_value_t.
+ */
+void *tst_checkpoints = NULL;
+int tst_checkpoints_sz = 0;
+
+static inline futex_t *get_futex(unsigned int id)
+{
+       futex_t *futexes = tst_checkpoints;
+       return &futexes[id];
+}
+
+static inline chp_value_t *get_pval(unsigned int id)
+{
+       chp_value_t *values = tst_checkpoints
+               + sizeof(futex_t) * MAX_CHECKPOINTS;
+       return &values[id];
+}
+
+static inline int is_index_valid(unsigned int id)
+{
+       return (id < MAX_CHECKPOINTS);
+}
 
 void tst_checkpoint_init(const char *file, const int lineno,
-                         void (*cleanup_fn)(void))
+                        void (*cleanup_fn)(void))
 {
-       int fd;
+       int fd, page_size;
 
-       if (tst_futexes) {
+       if (tst_checkpoints) {
                tst_brkm(TBROK, cleanup_fn,
                         "%s: %d checkopoints allready initialized",
                         file, lineno);
@@ -66,22 +101,31 @@ void tst_checkpoint_init(const char *file, const int 
lineno,
 
        page_size = getpagesize();
 
+       /* we need at least this bytes */
+       tst_checkpoints_sz = ((sizeof(futex_t) + sizeof(chp_value_t))
+                               * MAX_CHECKPOINTS);
+       /* round up to whole pages */
+       tst_checkpoints_sz = (((tst_checkpoints_sz + page_size - 1)
+               / page_size) * page_size);
+
        fd = SAFE_OPEN(cleanup_fn, "checkpoint_futex_base_file",
                       O_RDWR | O_CREAT, 0666);
 
-       SAFE_FTRUNCATE(cleanup_fn, fd, page_size);
+       SAFE_FTRUNCATE(cleanup_fn, fd, tst_checkpoints_sz);
 
-       tst_futexes = SAFE_MMAP(cleanup_fn, NULL, page_size,
+       tst_checkpoints = SAFE_MMAP(cleanup_fn, NULL, tst_checkpoints_sz,
                            PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
        SAFE_CLOSE(cleanup_fn, fd);
 }
 
-int tst_checkpoint_wait(unsigned int id, unsigned int msec_timeout)
+int tst_checkpoint_wait(unsigned int id, chp_value_t *pval,
+                       unsigned int msec_timeout)
 {
        struct timespec timeout;
+       int ret;
 
-       if (id >= page_size / sizeof(uint32_t)) {
+       if (!is_index_valid(id)) {
                errno = EOVERFLOW;
                return -1;
        }
@@ -89,22 +133,31 @@ int tst_checkpoint_wait(unsigned int id, unsigned int 
msec_timeout)
        timeout.tv_sec = msec_timeout/1000;
        timeout.tv_nsec = (msec_timeout%1000) * 1000000;
 
-       return syscall(SYS_futex, &tst_futexes[id], FUTEX_WAIT,
-                      tst_futexes[id], &timeout);
+       ret = syscall(SYS_futex, get_futex(id), FUTEX_WAIT,
+                     *(get_futex(id)), &timeout);
+
+       if (pval)
+               *pval = *(get_pval(id));
+
+       return ret;
 }
 
 int tst_checkpoint_wake(unsigned int id, unsigned int nr_wake,
-                        unsigned int msec_timeout)
+                       chp_value_t *pval,
+                       unsigned int msec_timeout)
 {
        unsigned int msecs = 0, waked = 0;
 
-       if (id >= page_size / sizeof(uint32_t)) {
+       if (!is_index_valid(id)) {
                errno = EOVERFLOW;
                return -1;
        }
 
+       if (pval)
+               *(get_pval(id)) = *pval;
+
        do {
-               waked += syscall(SYS_futex, &tst_futexes[id], FUTEX_WAKE,
+               waked += syscall(SYS_futex, get_futex(id), FUTEX_WAKE,
                                 INT_MAX, NULL);
                usleep(1000);
                msecs++;
@@ -120,9 +173,10 @@ int tst_checkpoint_wake(unsigned int id, unsigned int 
nr_wake,
 }
 
 void tst_safe_checkpoint_wait(const char *file, const int lineno,
-                              void (*cleanup_fn)(void), unsigned int id)
+                             void (*cleanup_fn)(void), unsigned int id,
+                             chp_value_t *pval)
 {
-       int ret = tst_checkpoint_wait(id, DEFAULT_MSEC_TIMEOUT);
+       int ret = tst_checkpoint_wait(id, pval, DEFAULT_MSEC_TIMEOUT);
 
        if (ret) {
                tst_brkm(TBROK | TERRNO, cleanup_fn,
@@ -132,10 +186,10 @@ void tst_safe_checkpoint_wait(const char *file, const int 
lineno,
 }
 
 void tst_safe_checkpoint_wake(const char *file, const int lineno,
-                              void (*cleanup_fn)(void), unsigned int id,
-                              unsigned int nr_wake)
+                             void (*cleanup_fn)(void), unsigned int id,
+                             unsigned int nr_wake, chp_value_t *pval)
 {
-       int ret = tst_checkpoint_wake(id, nr_wake, DEFAULT_MSEC_TIMEOUT);
+       int ret = tst_checkpoint_wake(id, nr_wake, pval, DEFAULT_MSEC_TIMEOUT);
 
        if (ret) {
                tst_brkm(TBROK | TERRNO, cleanup_fn,
diff --git a/lib/tst_tmpdir.c b/lib/tst_tmpdir.c
index 3ea1a8b..08cba4a 100644
--- a/lib/tst_tmpdir.c
+++ b/lib/tst_tmpdir.c
@@ -100,7 +100,8 @@ static char *TESTDIR = NULL;        /* the directory 
created */
 static char test_start_work_dir[PATH_MAX];
 
 /* lib/tst_checkpoint.c */
-extern futex_t *tst_futexes;
+extern futex_t *tst_checkpoints;
+extern int tst_checkpoints_sz;
 
 int tst_tmpdir_created(void)
 {
@@ -206,9 +207,9 @@ void tst_rmdir(void)
         * Unmap the backend file.
         * This is needed to overcome the NFS "silly rename" feature.
         */
-       if (tst_futexes) {
-               msync((void *)tst_futexes, getpagesize(), MS_SYNC);
-               munmap((void *)tst_futexes, getpagesize());
+       if (tst_checkpoints) {
+               msync((void *)tst_checkpoints, tst_checkpoints_sz, MS_SYNC);
+               munmap((void *)tst_checkpoints, tst_checkpoints_sz);
        }
 
        /*
-- 
1.8.3.1


------------------------------------------------------------------------------
Monitor 25 network devices or servers for free with OpManager!
OpManager is web-based network management software that monitors 
network devices and physical & virtual servers, alerts via email & sms 
for fault. Monitor 25 devices for free with no restriction. Download now
http://ad.doubleclick.net/ddm/clk/292181274;119417398;o
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to