xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/prctl/prctl08.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 FUJITSU LIMITED. All rights reserved.
4  * Author: Yang Xu <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Test PR_GET_TIMERSLACK and PR_SET_TIMERSLACK of prctl(2).
11  *
12  * - Each thread has two associated timer slack values: a "default"
13  *   value, and a "current" value. PR_SET_TIMERSLACK sets the "current"
14  *   timer slack value for the calling thread.
15  *
16  * - When a new thread is created, the two timer slack values are made
17  *   the same as the "current" value of the creating thread.
18  *
19  * - The maximum timer slack value is ULONG_MAX. On 32bit machines, it
20  *   is a valid value(about 4s). On 64bit machines, it is about 500 years
21  *   and no person will set this over 4s.  prctl return value is int, so
22  *   we test themaximum value is INT_MAX.
23  *
24  * - we also check current value via /proc/self/timerslack_ns if it is
25  *   supported.
26  */
27 
28 #include <sys/prctl.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <linux/limits.h>
33 #include "lapi/syscalls.h"
34 #include "lapi/prctl.h"
35 #include "tst_test.h"
36 
37 #define PROC_TIMERSLACK_PATH "/proc/self/timerslack_ns"
38 
39 static void check_reset_timerslack(char *message);
40 static void check_get_timerslack(char *message, unsigned long value);
41 static void check_inherit_timerslack(char *message, unsigned long value);
42 static unsigned long origin_value;
43 
44 static struct tcase {
45 	void (*func_check)();
46 	unsigned long setvalue;
47 	unsigned long expvalue;
48 	char message[50];
49 } tcases[] = {
50 	{check_reset_timerslack, 0, 50000, "Reset"},
51 	{check_get_timerslack, 1, 1, "Min"},
52 	{check_get_timerslack, 70000, 70000, "Middle"},
53 	{check_get_timerslack, INT_MAX, INT_MAX, "Max"},
54 	{check_inherit_timerslack, 70000, 70000, "Child process"},
55 };
56 
57 static int proc_flag = 1;
58 
check_reset_timerslack(char * message)59 static void check_reset_timerslack(char *message)
60 {
61 	check_get_timerslack(message, origin_value);
62 }
63 
check_get_timerslack(char * message,unsigned long value)64 static void check_get_timerslack(char *message, unsigned long value)
65 {
66 	TEST(prctl(PR_GET_TIMERSLACK));
67 	if ((unsigned long)TST_RET == value)
68 		tst_res(TPASS, "%s prctl(PR_GET_TIMERSLACK) got %lu expectedly",
69 				message, value);
70 	else
71 		tst_res(TFAIL, "%s prctl(PR_GET_TIMERSLACK) expected %lu got %lu",
72 				message, value, TST_RET);
73 
74 	if (proc_flag)
75 		TST_ASSERT_INT(PROC_TIMERSLACK_PATH, value);
76 }
77 
check_inherit_timerslack(char * message,unsigned long value)78 static void check_inherit_timerslack(char *message, unsigned long value)
79 {
80 	int pid;
81 	unsigned long current_value;
82 	unsigned long default_value;
83 
84 	pid = SAFE_FORK();
85 	if (pid == 0) {
86 		current_value = prctl(PR_GET_TIMERSLACK);
87 		prctl(PR_SET_TIMERSLACK, 0);
88 		default_value = prctl(PR_GET_TIMERSLACK);
89 		if (current_value == value && default_value == value)
90 			tst_res(TPASS,
91 				"%s two timer slack values are made the same as the current value(%lu) of the creating thread.",
92 				message, value);
93 		else
94 			tst_res(TFAIL,
95 				"%s current_value is %lu, default value is %lu, the parent current value is %lu",
96 				message, current_value, default_value, value);
97 	}
98 
99 }
100 
verify_prctl(unsigned int n)101 static void verify_prctl(unsigned int n)
102 {
103 	struct tcase *tc = &tcases[n];
104 
105 	TEST(prctl(PR_SET_TIMERSLACK, tc->setvalue));
106 	if (TST_RET == -1) {
107 		tst_res(TFAIL | TTERRNO, "prctl(PR_SET_TIMERSLACK, %lu) failed",
108 					  tc->setvalue);
109 		return;
110 	}
111 
112 	tst_res(TPASS, "prctl(PR_SET_TIMERSLACK, %lu) succeed", tc->setvalue);
113 	tc->func_check(tc->message, tc->expvalue);
114 }
115 
setup(void)116 static void setup(void)
117 {
118 	if (access(PROC_TIMERSLACK_PATH, F_OK) == -1) {
119 		tst_res(TCONF, "proc doesn't support timerslack_ns interface");
120 		proc_flag = 0;
121 	}
122 
123 	TEST(prctl(PR_GET_TIMERSLACK));
124 	origin_value = TST_RET;
125 	tst_res(TINFO, "current timerslack value is %lu", origin_value);
126 }
127 
128 static struct tst_test test = {
129 	.setup = setup,
130 	.test = verify_prctl,
131 	.tcnt = ARRAY_SIZE(tcases),
132 	.forks_child = 1,
133 };
134