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