test_ipc.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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 <assert.h>
  20. #include <stdio.h>
  21. #include <kern/ipc.h>
  22. #include <kern/semaphore.h>
  23. #include <kern/spinlock.h>
  24. #include <kern/task.h>
  25. #include <kern/thread.h>
  26. #include <test/test.h>
  27. #include <vm/map.h>
  28. #include <vm/page.h>
  29. #define TEST_IPC_DATA_SIZE 128
  30. struct test_ipc_data
  31. {
  32. struct semaphore send_sem;
  33. struct semaphore recv_sem;
  34. struct ipc_iov_iter *iovs;
  35. struct ipc_vme_iter *pgs;
  36. struct task *receiver;
  37. ssize_t len;
  38. int nr_pages;
  39. };
  40. struct test_ipc_vars
  41. {
  42. char buf[TEST_IPC_DATA_SIZE];
  43. struct iovec iovs[2];
  44. struct ipc_msg_vme mp;
  45. };
  46. static struct test_ipc_data test_data;
  47. static void
  48. test_ipc_sender (void *arg)
  49. {
  50. _Auto data = (struct test_ipc_data *)arg;
  51. struct test_ipc_vars *vars;
  52. int error = vm_map_anon_alloc ((void **)&vars,
  53. vm_map_self (), PAGE_SIZE * 2);
  54. assert (! error);
  55. memset (vars->buf, '-', sizeof (vars->buf));
  56. size_t half = TEST_IPC_DATA_SIZE / 2;
  57. vars->iovs[0] = IOVEC (vars->buf, half);
  58. vars->iovs[1] = IOVEC (vars->buf + half, half);
  59. struct ipc_iov_iter it;
  60. ipc_iov_iter_init (&it, vars->iovs, 2);
  61. assert (!ipc_iov_iter_empty (&it));
  62. struct ipc_vme_iter pg;
  63. vars->mp = (struct ipc_msg_vme)
  64. {
  65. .addr = (uintptr_t)vars + PAGE_SIZE,
  66. .size = PAGE_SIZE,
  67. .prot = VM_PROT_RDWR,
  68. .max_prot = VM_PROT_RDWR,
  69. };
  70. ipc_vme_iter_init (&pg, &vars->mp, 1);
  71. *(char *)vars->mp.addr = '+';
  72. semaphore_wait (&data->send_sem);
  73. data->len = ipc_iov_iter_copy (data->receiver, data->iovs,
  74. &it, IPC_COPY_TO);
  75. data->nr_pages = ipc_vme_iter_copy (data->receiver, data->pgs,
  76. &pg, IPC_COPY_TO);
  77. semaphore_post (&data->recv_sem);
  78. semaphore_wait (&data->send_sem);
  79. }
  80. static void
  81. test_ipc_receiver (void *arg)
  82. {
  83. _Auto data = (struct test_ipc_data *)arg;
  84. struct
  85. {
  86. char buf[TEST_IPC_DATA_SIZE - 10];
  87. struct ipc_msg_vme mp;
  88. } *vars;
  89. int error = vm_map_anon_alloc ((void **)&vars, vm_map_self (), 1);
  90. assert (! error);
  91. vars->mp.addr = PAGE_SIZE * 10;
  92. struct ipc_iov_iter it;
  93. struct ipc_vme_iter pg;
  94. ipc_iov_iter_init_buf (&it, vars->buf, sizeof (vars->buf));
  95. assert (!ipc_iov_iter_empty (&it));
  96. ipc_vme_iter_init (&pg, &vars->mp, 1);
  97. assert (ipc_vme_iter_size (&pg) > 0);
  98. data->iovs = &it;
  99. data->pgs = &pg;
  100. data->receiver = task_self ();
  101. semaphore_post (&data->send_sem);
  102. semaphore_wait (&data->recv_sem);
  103. assert (data->len == sizeof (vars->buf));
  104. assert (vars->buf[0] == '-');
  105. assert (vars->buf[sizeof (vars->buf) - 1] == '-');
  106. assert (data->nr_pages == 1);
  107. assert (*(char *)vars->mp.addr == '+');
  108. *(char *)vars->mp.addr = '*';
  109. semaphore_post (&data->send_sem);
  110. }
  111. TEST_DEFERRED (ipc)
  112. {
  113. _Auto data = &test_data;
  114. semaphore_init (&data->send_sem, 0, 0xff);
  115. semaphore_init (&data->recv_sem, 0, 0xff);
  116. struct thread *sender, *receiver;
  117. int error = test_util_create_thr (&sender, test_ipc_sender,
  118. data, "ipc_sender");
  119. assert (! error);
  120. error = test_util_create_thr (&receiver, test_ipc_receiver,
  121. data, "ipc_receiver");
  122. assert (! error);
  123. thread_join (sender);
  124. thread_join (receiver);
  125. return (TEST_OK);
  126. }