1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * Description:
6f08c3bdfSopenharmony_ci * Verify the basic function of sigsuspend():
7f08c3bdfSopenharmony_ci * 1) sigsuspend() can replace process's current signal mask
8f08c3bdfSopenharmony_ci *    by the specified signal mask and suspend the process
9f08c3bdfSopenharmony_ci *    execution until the delivery of a signal.
10f08c3bdfSopenharmony_ci * 2) sigsuspend() should return after the execution of signal
11f08c3bdfSopenharmony_ci *    handler and restore the previous signal mask.
12f08c3bdfSopenharmony_ci */
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ci#include <errno.h>
15f08c3bdfSopenharmony_ci#include <unistd.h>
16f08c3bdfSopenharmony_ci#include <string.h>
17f08c3bdfSopenharmony_ci#include <signal.h>
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci#include "tst_test.h"
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic sigset_t signalset, sigset1, sigset2;
22f08c3bdfSopenharmony_cistatic volatile sig_atomic_t alarm_num;
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistatic void sig_handler(int sig)
25f08c3bdfSopenharmony_ci{
26f08c3bdfSopenharmony_ci	alarm_num = sig;
27f08c3bdfSopenharmony_ci}
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_cistatic void verify_sigsuspend(void)
30f08c3bdfSopenharmony_ci{
31f08c3bdfSopenharmony_ci	alarm_num = 0;
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci	SAFE_SIGFILLSET(&sigset2);
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci	alarm(1);
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ci	/* Unblock SIGALRM */
38f08c3bdfSopenharmony_ci	TEST(sigsuspend(&signalset));
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci	alarm(0);
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci	if (TST_RET != -1 || TST_ERR != EINTR) {
43f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
44f08c3bdfSopenharmony_ci			"sigsuspend() returned value %ld", TST_RET);
45f08c3bdfSopenharmony_ci		return;
46f08c3bdfSopenharmony_ci	}
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci	if (alarm_num != SIGALRM) {
49f08c3bdfSopenharmony_ci		tst_res(TFAIL, "sigsuspend() didn't unblock SIGALRM");
50f08c3bdfSopenharmony_ci		return;
51f08c3bdfSopenharmony_ci	}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	SAFE_SIGPROCMASK(0, NULL, &sigset2);
54f08c3bdfSopenharmony_ci	if (memcmp(&sigset1, &sigset2, sizeof(unsigned long))) {
55f08c3bdfSopenharmony_ci		tst_res(TFAIL, "sigsuspend() failed to "
56f08c3bdfSopenharmony_ci			"restore the previous signal mask");
57f08c3bdfSopenharmony_ci		return;
58f08c3bdfSopenharmony_ci	}
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	tst_res(TPASS, "sigsuspend() succeeded");
61f08c3bdfSopenharmony_ci}
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_cistatic void setup(void)
64f08c3bdfSopenharmony_ci{
65f08c3bdfSopenharmony_ci	SAFE_SIGEMPTYSET(&signalset);
66f08c3bdfSopenharmony_ci	SAFE_SIGEMPTYSET(&sigset1);
67f08c3bdfSopenharmony_ci	SAFE_SIGADDSET(&sigset1, SIGALRM);
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	struct sigaction sa_new = {
70f08c3bdfSopenharmony_ci		.sa_handler = sig_handler,
71f08c3bdfSopenharmony_ci	};
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	SAFE_SIGACTION(SIGALRM, &sa_new, 0);
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	/* Block SIGALRM */
76f08c3bdfSopenharmony_ci	SAFE_SIGPROCMASK(SIG_SETMASK, &sigset1, NULL);
77f08c3bdfSopenharmony_ci}
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_cistatic struct tst_test test = {
80f08c3bdfSopenharmony_ci	.setup = setup,
81f08c3bdfSopenharmony_ci	.test_all = verify_sigsuspend,
82f08c3bdfSopenharmony_ci};
83