test_ipc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (c) 2022 Agustina Arzille.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * This test module tests IPC between threads of different tasks.
  18. */
  19. #include <stdio.h>
  20. #include <kern/ipc.h>
  21. #include <kern/semaphore.h>
  22. #include <kern/spinlock.h>
  23. #include <kern/task.h>
  24. #include <kern/thread.h>
  25. #include <test/test.h>
  26. #include <vm/map.h>
  27. #include <vm/page.h>
  28. #define TEST_IPC_DATA_SIZE 128
  29. struct test_ipc_data
  30. {
  31. struct semaphore send_sem;
  32. struct semaphore recv_sem;
  33. struct ipc_iov_iter *iovs;
  34. struct ipc_vme_iter *pgs;
  35. struct task *receiver;
  36. ssize_t len;
  37. int nr_pages;
  38. };
  39. struct test_ipc_vars
  40. {
  41. char buf[TEST_IPC_DATA_SIZE];
  42. struct iovec iovs[2];
  43. struct ipc_msg_vme mp;
  44. };
  45. static struct test_ipc_data test_data;
  46. static void
  47. test_ipc_sender (void *arg)
  48. {
  49. _Auto data = (struct test_ipc_data *)arg;
  50. struct test_ipc_vars *vars;
  51. int error = vm_map_anon_alloc ((void **)&vars,
  52. vm_map_self (), PAGE_SIZE * 2);
  53. test_assert_zero (error);
  54. memset (vars->buf, '-', sizeof (vars->buf));
  55. size_t half = TEST_IPC_DATA_SIZE / 2;
  56. vars->iovs[0] = IOVEC (vars->buf, half);
  57. vars->iovs[1] = IOVEC (vars->buf + half, half);
  58. struct ipc_iov_iter it;
  59. ipc_iov_iter_init (&it, vars->iovs, 2);
  60. test_assert_zero (ipc_iov_iter_empty (&it));
  61. struct ipc_vme_iter pg;
  62. vars->mp = (struct ipc_msg_vme)
  63. {
  64. .addr = (uintptr_t)vars + PAGE_SIZE,
  65. .size = PAGE_SIZE,
  66. .prot = VM_PROT_RDWR,
  67. .max_prot = VM_PROT_RDWR,
  68. };
  69. ipc_vme_iter_init (&pg, &vars->mp, 1);
  70. *(char *)vars->mp.addr = '+';
  71. semaphore_wait (&data->send_sem);
  72. data->len = ipc_iov_iter_copy (data->receiver, data->iovs,
  73. &it, IPC_COPY_TO);
  74. data->nr_pages = ipc_vme_iter_copy (data->receiver, data->pgs,
  75. &pg, IPC_COPY_TO);
  76. semaphore_post (&data->recv_sem);
  77. semaphore_wait (&data->send_sem);
  78. }
  79. static void
  80. test_ipc_receiver (void *arg)
  81. {
  82. _Auto data = (struct test_ipc_data *)arg;
  83. struct
  84. {
  85. char buf[TEST_IPC_DATA_SIZE - 10];
  86. struct ipc_msg_vme mp;
  87. } *vars;
  88. int error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), 1);
  89. test_assert_zero (error);
  90. vars->mp.addr = PAGE_SIZE * 10;
  91. struct ipc_iov_iter it;
  92. struct ipc_vme_iter pg;
  93. ipc_iov_iter_init_buf (&it, vars->buf, sizeof (vars->buf));
  94. test_assert_zero (ipc_iov_iter_empty (&it));
  95. ipc_vme_iter_init (&pg, &vars->mp, 1);
  96. test_assert_gt (ipc_vme_iter_size (&pg), 0);
  97. data->iovs = &it;
  98. data->pgs = &pg;
  99. data->receiver = task_self ();
  100. semaphore_post (&data->send_sem);
  101. semaphore_wait (&data->recv_sem);
  102. test_assert_eq (data->len, sizeof (vars->buf));
  103. test_assert_eq (vars->buf[0], '-');
  104. test_assert_eq (vars->buf[sizeof (vars->buf) - 1], '-');
  105. test_assert_eq (data->nr_pages, 1);
  106. test_assert_eq (*(char *)vars->mp.addr, '+');
  107. *(char *)vars->mp.addr = '*';
  108. semaphore_post (&data->send_sem);
  109. }
  110. TEST_DEFERRED (ipc)
  111. {
  112. _Auto data = &test_data;
  113. semaphore_init (&data->send_sem, 0, 0xff);
  114. semaphore_init (&data->recv_sem, 0, 0xff);
  115. struct thread *sender, *receiver;
  116. int error = test_util_create_thr (&sender, test_ipc_sender,
  117. data, "ipc_sender");
  118. test_assert_zero (error);
  119. error = test_util_create_thr (&receiver, test_ipc_receiver,
  120. data, "ipc_receiver");
  121. test_assert_zero (error);
  122. thread_join (sender);
  123. thread_join (receiver);
  124. return (TEST_OK);
  125. }