1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd 4f08c3bdfSopenharmony_ci * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Authors: 7f08c3bdfSopenharmony_ci * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, 8f08c3bdfSopenharmony_ci * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, 9f08c3bdfSopenharmony_ci * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> 10f08c3bdfSopenharmony_ci */ 11f08c3bdfSopenharmony_ci 12f08c3bdfSopenharmony_ci#include <limits.h> 13f08c3bdfSopenharmony_ci#include <errno.h> 14f08c3bdfSopenharmony_ci 15f08c3bdfSopenharmony_ci#include "tst_test.h" 16f08c3bdfSopenharmony_ci#include "tst_safe_posix_ipc.h" 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_cistatic int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1; 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include "mq.h" 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#define USER_DATA 0x12345678 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic char *str_debug; 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_cistatic volatile sig_atomic_t notified, cmp_ok; 27f08c3bdfSopenharmony_cistatic siginfo_t info; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistruct test_case { 30f08c3bdfSopenharmony_ci int *fd; 31f08c3bdfSopenharmony_ci int already_registered; 32f08c3bdfSopenharmony_ci int notify; 33f08c3bdfSopenharmony_ci int ret; 34f08c3bdfSopenharmony_ci int err; 35f08c3bdfSopenharmony_ci}; 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cistatic struct test_case tcase[] = { 38f08c3bdfSopenharmony_ci { 39f08c3bdfSopenharmony_ci .fd = &fd, 40f08c3bdfSopenharmony_ci .notify = SIGEV_NONE, 41f08c3bdfSopenharmony_ci .ret = 0, 42f08c3bdfSopenharmony_ci .err = 0, 43f08c3bdfSopenharmony_ci }, 44f08c3bdfSopenharmony_ci { 45f08c3bdfSopenharmony_ci .fd = &fd, 46f08c3bdfSopenharmony_ci .notify = SIGEV_SIGNAL, 47f08c3bdfSopenharmony_ci .ret = 0, 48f08c3bdfSopenharmony_ci .err = 0, 49f08c3bdfSopenharmony_ci }, 50f08c3bdfSopenharmony_ci { 51f08c3bdfSopenharmony_ci .fd = &fd, 52f08c3bdfSopenharmony_ci .notify = SIGEV_THREAD, 53f08c3bdfSopenharmony_ci .ret = 0, 54f08c3bdfSopenharmony_ci .err = 0, 55f08c3bdfSopenharmony_ci }, 56f08c3bdfSopenharmony_ci { 57f08c3bdfSopenharmony_ci .fd = &fd_invalid, 58f08c3bdfSopenharmony_ci .notify = SIGEV_NONE, 59f08c3bdfSopenharmony_ci .ret = -1, 60f08c3bdfSopenharmony_ci .err = EBADF, 61f08c3bdfSopenharmony_ci }, 62f08c3bdfSopenharmony_ci { 63f08c3bdfSopenharmony_ci .fd = &fd_maxint, 64f08c3bdfSopenharmony_ci .notify = SIGEV_NONE, 65f08c3bdfSopenharmony_ci .ret = -1, 66f08c3bdfSopenharmony_ci .err = EBADF, 67f08c3bdfSopenharmony_ci }, 68f08c3bdfSopenharmony_ci { 69f08c3bdfSopenharmony_ci .fd = &fd_root, 70f08c3bdfSopenharmony_ci .notify = SIGEV_NONE, 71f08c3bdfSopenharmony_ci .ret = -1, 72f08c3bdfSopenharmony_ci .err = EBADF, 73f08c3bdfSopenharmony_ci }, 74f08c3bdfSopenharmony_ci { 75f08c3bdfSopenharmony_ci .fd = &fd, 76f08c3bdfSopenharmony_ci .notify = SIGEV_NONE, 77f08c3bdfSopenharmony_ci .already_registered = 1, 78f08c3bdfSopenharmony_ci .ret = -1, 79f08c3bdfSopenharmony_ci .err = EBUSY, 80f08c3bdfSopenharmony_ci }, 81f08c3bdfSopenharmony_ci}; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_cistatic void sigfunc(int signo LTP_ATTRIBUTE_UNUSED, siginfo_t *si, 84f08c3bdfSopenharmony_ci void *data LTP_ATTRIBUTE_UNUSED) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci if (str_debug) 87f08c3bdfSopenharmony_ci memcpy(&info, si, sizeof(info)); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci cmp_ok = si->si_code == SI_MESGQ && 90f08c3bdfSopenharmony_ci si->si_signo == SIGUSR1 && 91f08c3bdfSopenharmony_ci si->si_value.sival_int == USER_DATA && 92f08c3bdfSopenharmony_ci si->si_pid == getpid() && si->si_uid == getuid(); 93f08c3bdfSopenharmony_ci notified = 1; 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void tfunc(union sigval sv) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci cmp_ok = sv.sival_int == USER_DATA; 99f08c3bdfSopenharmony_ci notified = 1; 100f08c3bdfSopenharmony_ci} 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_cistatic void do_test(unsigned int i) 103f08c3bdfSopenharmony_ci{ 104f08c3bdfSopenharmony_ci struct sigaction sigact; 105f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 106f08c3bdfSopenharmony_ci struct sigevent ev; 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci ev.sigev_notify = tc->notify; 109f08c3bdfSopenharmony_ci notified = cmp_ok = 1; 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci switch (tc->notify) { 112f08c3bdfSopenharmony_ci case SIGEV_SIGNAL: 113f08c3bdfSopenharmony_ci notified = cmp_ok = 0; 114f08c3bdfSopenharmony_ci ev.sigev_signo = SIGUSR1; 115f08c3bdfSopenharmony_ci ev.sigev_value.sival_int = USER_DATA; 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci memset(&sigact, 0, sizeof(sigact)); 118f08c3bdfSopenharmony_ci sigact.sa_sigaction = sigfunc; 119f08c3bdfSopenharmony_ci sigact.sa_flags = SA_SIGINFO; 120f08c3bdfSopenharmony_ci if (sigaction(SIGUSR1, &sigact, NULL) == -1) { 121f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "sigaction failed"); 122f08c3bdfSopenharmony_ci return; 123f08c3bdfSopenharmony_ci } 124f08c3bdfSopenharmony_ci break; 125f08c3bdfSopenharmony_ci case SIGEV_THREAD: 126f08c3bdfSopenharmony_ci notified = cmp_ok = 0; 127f08c3bdfSopenharmony_ci ev.sigev_notify_function = tfunc; 128f08c3bdfSopenharmony_ci ev.sigev_notify_attributes = NULL; 129f08c3bdfSopenharmony_ci ev.sigev_value.sival_int = USER_DATA; 130f08c3bdfSopenharmony_ci break; 131f08c3bdfSopenharmony_ci } 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci if (tc->already_registered && mq_notify(*tc->fd, &ev) == -1) { 134f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "mq_notify(%d, %p) failed", fd, &ev); 135f08c3bdfSopenharmony_ci return; 136f08c3bdfSopenharmony_ci } 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci TEST(mq_notify(*tc->fd, &ev)); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci if (TST_RET < 0) { 141f08c3bdfSopenharmony_ci if (tc->err != TST_ERR) 142f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 143f08c3bdfSopenharmony_ci "mq_notify failed unexpectedly, expected %s", 144f08c3bdfSopenharmony_ci tst_strerrno(tc->err)); 145f08c3bdfSopenharmony_ci else 146f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "mq_notify failed expectedly"); 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci /* unregister notification */ 149f08c3bdfSopenharmony_ci if (*tc->fd == fd) 150f08c3bdfSopenharmony_ci mq_notify(*tc->fd, NULL); 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci return; 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci TEST(mq_timedsend(*tc->fd, smsg, MSG_LENGTH, 0, 156f08c3bdfSopenharmony_ci &((struct timespec){0}))); 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci if (*tc->fd == fd) 159f08c3bdfSopenharmony_ci cleanup_queue(fd); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci if (TST_RET < 0) { 162f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "mq_timedsend failed"); 163f08c3bdfSopenharmony_ci return; 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci while (!notified) 167f08c3bdfSopenharmony_ci usleep(10000); 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci if (str_debug && tc->notify == SIGEV_SIGNAL) { 170f08c3bdfSopenharmony_ci tst_res(TINFO, "si_code E:%d,\tR:%d", 171f08c3bdfSopenharmony_ci info.si_code, SI_MESGQ); 172f08c3bdfSopenharmony_ci tst_res(TINFO, "si_signo E:%d,\tR:%d", 173f08c3bdfSopenharmony_ci info.si_signo, SIGUSR1); 174f08c3bdfSopenharmony_ci tst_res(TINFO, "si_value E:0x%x,\tR:0x%x", 175f08c3bdfSopenharmony_ci info.si_value.sival_int, USER_DATA); 176f08c3bdfSopenharmony_ci tst_res(TINFO, "si_pid E:%d,\tR:%d", 177f08c3bdfSopenharmony_ci info.si_pid, getpid()); 178f08c3bdfSopenharmony_ci tst_res(TINFO, "si_uid E:%d,\tR:%d", 179f08c3bdfSopenharmony_ci info.si_uid, getuid()); 180f08c3bdfSopenharmony_ci } 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci if (TST_RET < 0) { 183f08c3bdfSopenharmony_ci if (tc->err != TST_ERR) 184f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 185f08c3bdfSopenharmony_ci "mq_timedsend failed unexpectedly, expected %s", 186f08c3bdfSopenharmony_ci tst_strerrno(tc->err)); 187f08c3bdfSopenharmony_ci else 188f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "mq_timedsend failed expectedly"); 189f08c3bdfSopenharmony_ci return; 190f08c3bdfSopenharmony_ci } 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci if (tc->ret != TST_RET) { 193f08c3bdfSopenharmony_ci tst_res(TFAIL, "mq_timedsend returned %ld, expected %d", 194f08c3bdfSopenharmony_ci TST_RET, tc->ret); 195f08c3bdfSopenharmony_ci return; 196f08c3bdfSopenharmony_ci } 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci tst_res(TPASS, "mq_notify and mq_timedsend exited expectedly"); 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_cistatic struct tst_test test = { 202f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcase), 203f08c3bdfSopenharmony_ci .test = do_test, 204f08c3bdfSopenharmony_ci .options = (struct tst_option[]) { 205f08c3bdfSopenharmony_ci {"d", &str_debug, "Print debug messages"}, 206f08c3bdfSopenharmony_ci {} 207f08c3bdfSopenharmony_ci }, 208f08c3bdfSopenharmony_ci .setup = setup_common, 209f08c3bdfSopenharmony_ci .cleanup = cleanup_common, 210f08c3bdfSopenharmony_ci}; 211