1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright(c) 2022 Huawei Technologies Co., Ltd 4f08c3bdfSopenharmony_ci * Author: Li Mengfei <limengfei4@huawei.com> 5f08c3bdfSopenharmony_ci * Zhao Gongyi <zhaogongyi@huawei.com> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * 1. Create a high nice thread and a low nice thread, the main 12f08c3bdfSopenharmony_ci * thread wake them at the same time 13f08c3bdfSopenharmony_ci * 2. Both threads run on the same CPU 14f08c3bdfSopenharmony_ci * 3. Verify that the low nice thread executes more time than 15f08c3bdfSopenharmony_ci * the high nice thread 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#define _GNU_SOURCE 19f08c3bdfSopenharmony_ci#include <pthread.h> 20f08c3bdfSopenharmony_ci#include <sys/types.h> 21f08c3bdfSopenharmony_ci#include <stdio.h> 22f08c3bdfSopenharmony_ci#include "tst_test.h" 23f08c3bdfSopenharmony_ci#include "tst_safe_pthread.h" 24f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 25f08c3bdfSopenharmony_ci#include "tst_safe_clocks.h" 26f08c3bdfSopenharmony_ci#include "tst_timer.h" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistatic pthread_barrier_t barrier; 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic void set_nice(int nice_inc) 31f08c3bdfSopenharmony_ci{ 32f08c3bdfSopenharmony_ci int orig_nice; 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci orig_nice = SAFE_GETPRIORITY(PRIO_PROCESS, 0); 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci TEST(nice(nice_inc)); 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci if (TST_RET != (orig_nice + nice_inc)) { 39f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "nice(%d) returned %li, expected %i", 40f08c3bdfSopenharmony_ci nice_inc, TST_RET, orig_nice + nice_inc); 41f08c3bdfSopenharmony_ci } 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci if (TST_ERR) 44f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "nice(%d) failed", nice_inc); 45f08c3bdfSopenharmony_ci} 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic void do_something(void) 48f08c3bdfSopenharmony_ci{ 49f08c3bdfSopenharmony_ci volatile int number = 0; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci while (1) { 52f08c3bdfSopenharmony_ci number++; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci TEST(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)); 55f08c3bdfSopenharmony_ci if (TST_RET != 0) { 56f08c3bdfSopenharmony_ci tst_brk(TBROK | TRERRNO, 57f08c3bdfSopenharmony_ci "pthread_setcancelstate() failed"); 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci pthread_testcancel(); 60f08c3bdfSopenharmony_ci } 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void *thread_fn(void *arg) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci set_nice((intptr_t)arg); 66f08c3bdfSopenharmony_ci SAFE_PTHREAD_BARRIER_WAIT(&barrier); 67f08c3bdfSopenharmony_ci do_something(); 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci return NULL; 70f08c3bdfSopenharmony_ci} 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_cistatic void setup(void) 73f08c3bdfSopenharmony_ci{ 74f08c3bdfSopenharmony_ci size_t size; 75f08c3bdfSopenharmony_ci size_t i; 76f08c3bdfSopenharmony_ci int nrcpus = 1024; 77f08c3bdfSopenharmony_ci cpu_set_t *set; 78f08c3bdfSopenharmony_ci int some_cpu; 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci set = CPU_ALLOC(nrcpus); 81f08c3bdfSopenharmony_ci if (!set) 82f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "CPU_ALLOC()"); 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci size = CPU_ALLOC_SIZE(nrcpus); 85f08c3bdfSopenharmony_ci CPU_ZERO_S(size, set); 86f08c3bdfSopenharmony_ci if (sched_getaffinity(0, size, set) < 0) 87f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sched_getaffinity()"); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci for (i = 0; i < size * 8; i++) 90f08c3bdfSopenharmony_ci if (CPU_ISSET_S(i, size, set)) 91f08c3bdfSopenharmony_ci some_cpu = i; 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci CPU_ZERO_S(size, set); 94f08c3bdfSopenharmony_ci CPU_SET_S(some_cpu, size, set); 95f08c3bdfSopenharmony_ci if (sched_setaffinity(0, size, set) < 0) 96f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sched_setaffinity()"); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci CPU_FREE(set); 99f08c3bdfSopenharmony_ci} 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_cistatic void verify_nice(void) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci intptr_t nice_inc_high = -1; 104f08c3bdfSopenharmony_ci intptr_t nice_inc_low = -2; 105f08c3bdfSopenharmony_ci clockid_t nice_low_clockid, nice_high_clockid; 106f08c3bdfSopenharmony_ci struct timespec nice_high_ts, nice_low_ts; 107f08c3bdfSopenharmony_ci long long delta; 108f08c3bdfSopenharmony_ci pthread_t thread[2]; 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci SAFE_PTHREAD_BARRIER_INIT(&barrier, NULL, 3); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(&thread[0], NULL, thread_fn, 113f08c3bdfSopenharmony_ci (void *)nice_inc_high); 114f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(&thread[1], NULL, thread_fn, 115f08c3bdfSopenharmony_ci (void *)nice_inc_low); 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci SAFE_PTHREAD_BARRIER_WAIT(&barrier); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci sleep(tst_remaining_runtime()); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci TEST(pthread_getcpuclockid(thread[1], &nice_low_clockid)); 122f08c3bdfSopenharmony_ci if (TST_RET != 0) 123f08c3bdfSopenharmony_ci tst_brk(TBROK | TRERRNO, "clock_getcpuclockid() failed"); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci TEST(pthread_getcpuclockid(thread[0], &nice_high_clockid)); 126f08c3bdfSopenharmony_ci if (TST_RET != 0) 127f08c3bdfSopenharmony_ci tst_brk(TBROK | TRERRNO, "clock_getcpuclockid() failed"); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci SAFE_CLOCK_GETTIME(nice_low_clockid, &nice_low_ts); 130f08c3bdfSopenharmony_ci SAFE_CLOCK_GETTIME(nice_high_clockid, &nice_high_ts); 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci tst_res(TINFO, "Nice low thread CPU time: %ld.%09ld s", 133f08c3bdfSopenharmony_ci nice_low_ts.tv_sec, nice_low_ts.tv_nsec); 134f08c3bdfSopenharmony_ci tst_res(TINFO, "Nice high thread CPU time: %ld.%09ld s", 135f08c3bdfSopenharmony_ci nice_high_ts.tv_sec, nice_high_ts.tv_nsec); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci delta = tst_timespec_diff_ns(nice_low_ts, nice_high_ts); 138f08c3bdfSopenharmony_ci if (delta < 0) { 139f08c3bdfSopenharmony_ci tst_res(TFAIL, "executes less cycles than " 140f08c3bdfSopenharmony_ci "the high nice thread, delta: %lld ns", delta); 141f08c3bdfSopenharmony_ci } else { 142f08c3bdfSopenharmony_ci tst_res(TPASS, "executes more cycles than " 143f08c3bdfSopenharmony_ci "the high nice thread, delta: %lld ns", delta); 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci SAFE_PTHREAD_CANCEL(thread[0]); 147f08c3bdfSopenharmony_ci SAFE_PTHREAD_CANCEL(thread[1]); 148f08c3bdfSopenharmony_ci SAFE_PTHREAD_BARRIER_DESTROY(&barrier); 149f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(thread[0], NULL); 150f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(thread[1], NULL); 151f08c3bdfSopenharmony_ci} 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_cistatic struct tst_test test = { 154f08c3bdfSopenharmony_ci .setup = setup, 155f08c3bdfSopenharmony_ci .test_all = verify_nice, 156f08c3bdfSopenharmony_ci .needs_root = 1, 157f08c3bdfSopenharmony_ci .max_runtime = 3, 158f08c3bdfSopenharmony_ci}; 159