Reuse the same selftest for the original set_robust_list() syscall for
the new set_robust_list2() syscall. Use kselftest variants feature to
run the relevant tests for both interfaces. Create a new test case to
get different lists from the same task.

Signed-off-by: André Almeida <[email protected]>
---
 .../selftests/futex/functional/robust_list.c       | 133 ++++++++++++++++++---
 1 file changed, 117 insertions(+), 16 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/robust_list.c 
b/tools/testing/selftests/futex/functional/robust_list.c
index f4dd600b3d1f..587fb529d6ca 100644
--- a/tools/testing/selftests/futex/functional/robust_list.c
+++ b/tools/testing/selftests/futex/functional/robust_list.c
@@ -51,6 +51,7 @@
 
 #ifndef SYS_set_robust_list2
 # define SYS_set_robust_list2 473
+# define SYS_get_robust_list2 474
 
 enum robust_list_cmd {
        FUTEX_ROBUST_LIST_CMD_CREATE_64,
@@ -102,6 +103,12 @@ static int set_robust_list2(struct robust_list_head *head, 
enum robust_list_cmd
        return syscall(SYS_set_robust_list2, head, cmd, index, flags, 0, 0);
 }
 
+static int get_robust_list2(int pid, struct robust_list_head **head,
+                           unsigned int index, unsigned int flags)
+{
+       return syscall(SYS_get_robust_list2, pid, head, index, flags);
+}
+
 static bool robust_list2_support(void)
 {
        int ret = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 
0);
@@ -240,6 +247,23 @@ static int modify_list(struct robust_list_head *head, int 
index)
        return set_robust_list2(head, get_cmd_modify(), index, 0);
 }
 
+static int get_list(pid_t pid, struct robust_list_head **head, bool robust2, 
int index)
+{
+       int ret;
+
+       if (!robust2) {
+               size_t len_ptr;
+
+               ret = get_robust_list(pid, head, &len_ptr);
+               if (sizeof(**head) != len_ptr)
+                       return -EINVAL;
+
+               return ret;
+       }
+
+       return get_robust_list2(pid, head, index, 0);
+}
+
 /*
  * A basic (and incomplete) mutex lock function with robustness
  */
@@ -424,39 +448,44 @@ TEST(test_set_robust_list2_inval)
 /*
  * Test get_robust_list with pid = 0, getting the list of the running thread
  */
-TEST(test_get_robust_list_self)
+TEST_F(robust_api, test_get_robust_list_self)
 {
        struct robust_list_head head, head2, *get_head;
-       size_t head_size = sizeof(head), len_ptr;
-       int ret;
+       bool robust2 = variant->robust2;
+       int ret, index = 0;
 
-       ret = set_robust_list(&head, head_size);
+       ret = set_list(&head, robust2, 0);
        ASSERT_EQ(ret, 0);
 
-       ret = get_robust_list(0, &get_head, &len_ptr);
+       ret = get_list(0, &get_head, robust2, 0);
        ASSERT_EQ(ret, 0);
        ASSERT_EQ(get_head, &head);
-       ASSERT_EQ(head_size, len_ptr);
 
-       ret = set_robust_list(&head2, head_size);
-       ASSERT_EQ(ret, 0);
+       ret = set_list(&head2, robust2, &index);
+       ASSERT_GE(ret, 0);
 
-       ret = get_robust_list(0, &get_head, &len_ptr);
+       ret = get_list(0, &get_head, robust2, index);
        ASSERT_EQ(ret, 0);
        ASSERT_EQ(get_head, &head2);
-       ASSERT_EQ(head_size, len_ptr);
 }
 
+struct child_arg_struct {
+       struct robust_list_head *head;
+       bool robust2;
+};
+
 static int child_list(void *arg)
 {
        struct child_args *cargs = arg;
        struct __test_metadata *_metadata = cargs->_metadata;
-       struct robust_list_head *head = cargs->arg;
+       struct child_arg_struct *child_arg = (struct child_arg_struct *) 
cargs->arg;
+       struct robust_list_head *head = child_arg->head;
+       bool robust2 = child_arg->robust2;
        int ret;
 
        free(cargs);
 
-       ret = set_robust_list(head, sizeof(*head));
+       ret = set_list(head, robust2, 0);
        ASSERT_EQ(ret, 0)
                TH_LOG("set_robust_list error");
 
@@ -477,23 +506,26 @@ static int child_list(void *arg)
  * parent
  *   2) the child thread still alive when we try to get the list from it
  */
-TEST(test_get_robust_list_child)
+TEST_F(robust_api, test_get_robust_list_child)
 {
        struct robust_list_head head, *get_head;
+       bool robust2 = variant->robust2;
+       struct child_arg_struct child =
+               {.robust2 = robust2, .head = &head};
        int ret, wstatus;
-       size_t len_ptr;
        pid_t tid;
 
+
        ret = pthread_barrier_init(&barrier, NULL, 2);
        ret = pthread_barrier_init(&barrier2, NULL, 2);
        ASSERT_EQ(ret, 0);
 
-       tid = create_child(_metadata, &child_list, &head);
+       tid = create_child(_metadata, &child_list, &child);
        ASSERT_NE(tid, -1);
 
        pthread_barrier_wait(&barrier);
 
-       ret = get_robust_list(tid, &get_head, &len_ptr);
+       ret = get_list(tid, &get_head, robust2, 0);
        ASSERT_EQ(ret, 0);
        ASSERT_EQ(&head, get_head);
 
@@ -1171,4 +1203,73 @@ TEST(test_32bit_lists)
        munmap(locks, sizeof(*locks) * CHILD_NR);
 }
 
+/*
+ * Test setting and getting mutiples head lists
+ */
+TEST(set_and_get_robust2)
+{
+       struct robust_list_head *head = NULL, *heads;
+       int list_limit, ret, *index, i, j;
+
+       if (!robust_list2_support()) {
+               SKIP(return, "robust_list2 not supported\n");
+               return;
+       }
+
+       list_limit = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 
0, 0);
+       ASSERT_GT(list_limit, 1);
+
+       heads = malloc(list_limit * sizeof(*heads));
+       ASSERT_NE(heads, NULL);
+
+       index = malloc(list_limit * sizeof(*index));
+       ASSERT_NE(index, NULL);
+
+       /*
+        * Insert various elements into the lists
+        */
+       for (i = 0; i < list_limit; i++) {
+               ret = set_list(&heads[i], true, &index[i]);
+               ASSERT_GE(ret, 0);
+               ASSERT_EQ(i, index[i]);
+       }
+
+       for (i = 0; i < list_limit; i++) {
+               ret = get_list(0, &head, true, index[i]);
+               ASSERT_EQ(ret, 0);
+               ASSERT_EQ(head, &heads[i]);
+       }
+
+       /*
+        * Modify the list, adding the elements in the other ordering
+        */
+       for (i = 0, j = list_limit; i < list_limit; i++, j--) {
+               ret = modify_list(&heads[j], index[i]);
+               ASSERT_GE(ret, 0);
+       }
+
+       for (i = 0, j = list_limit; i < list_limit; i++, j--) {
+               ret = get_list(0, &head, true, index[i]);
+               ASSERT_EQ(ret, 0);
+               ASSERT_EQ(head, &heads[j]);
+       }
+
+       /*
+        * Delete all elements
+        */
+       for (i = 0; i < list_limit; i++) {
+               ret = modify_list(NULL, index[i]);
+               ASSERT_EQ(ret, 0);
+       }
+
+       for (i = 0; i < list_limit; i++) {
+               ret = get_list(0, &head, true, index[i]);
+               ASSERT_EQ(ret, 0);
+               ASSERT_EQ(head, NULL);
+       }
+
+       free(heads);
+       free(index);
+}
+
 TEST_HARNESS_MAIN

-- 
2.55.0


Reply via email to