1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * timerfd() test by Davide Libenzi (test app for timerfd) 4f08c3bdfSopenharmony_ci * Copyright (C) 2007 Davide Libenzi 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Davide Libenzi <davidel@xmailserver.org> 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * Description: 9f08c3bdfSopenharmony_ci * Test timerfd with the flags: 10f08c3bdfSopenharmony_ci * 1) CLOCK_MONOTONIC 11f08c3bdfSopenharmony_ci * 2) CLOCK_REALTIME 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * HISTORY 14f08c3bdfSopenharmony_ci * 28/05/2008 Initial contribution by Davide Libenzi <davidel@xmailserver.org> 15f08c3bdfSopenharmony_ci * 28/05/2008 Integrated to LTP by Subrata Modak <subrata@linux.vnet.ibm.com> 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#define _GNU_SOURCE 19f08c3bdfSopenharmony_ci#include <poll.h> 20f08c3bdfSopenharmony_ci#include "time64_variants.h" 21f08c3bdfSopenharmony_ci#include "tst_timer.h" 22f08c3bdfSopenharmony_ci#include "tst_safe_timerfd.h" 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic struct tcase { 25f08c3bdfSopenharmony_ci int id; 26f08c3bdfSopenharmony_ci char const *name; 27f08c3bdfSopenharmony_ci} tcases[] = { 28f08c3bdfSopenharmony_ci {CLOCK_MONOTONIC, "CLOCK MONOTONIC"}, 29f08c3bdfSopenharmony_ci {CLOCK_REALTIME, "CLOCK REALTIME"}, 30f08c3bdfSopenharmony_ci}; 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic struct time64_variants variants[] = { 33f08c3bdfSopenharmony_ci#if (__NR_timerfd_gettime != __LTP__NR_INVALID_SYSCALL) 34f08c3bdfSopenharmony_ci { .clock_gettime = sys_clock_gettime, .tfd_gettime = sys_timerfd_gettime, .tfd_settime = sys_timerfd_settime, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"}, 35f08c3bdfSopenharmony_ci#endif 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci#if (__NR_timerfd_gettime64 != __LTP__NR_INVALID_SYSCALL) 38f08c3bdfSopenharmony_ci { .clock_gettime = sys_clock_gettime64, .tfd_gettime = sys_timerfd_gettime64, .tfd_settime = sys_timerfd_settime64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, 39f08c3bdfSopenharmony_ci#endif 40f08c3bdfSopenharmony_ci}; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cistatic unsigned long long getustime(int clockid) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 45f08c3bdfSopenharmony_ci struct tst_ts tp = {.type = tv->ts_type, }; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci if (tv->clock_gettime((clockid_t) clockid, tst_ts_get(&tp))) { 48f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "clock_gettime() failed"); 49f08c3bdfSopenharmony_ci return 0; 50f08c3bdfSopenharmony_ci } 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci return 1000000ULL * tst_ts_get_sec(tp) + tst_ts_get_nsec(tp) / 1000; 53f08c3bdfSopenharmony_ci} 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistatic void settime(int tfd, struct tst_its *tmr, int tflags, 56f08c3bdfSopenharmony_ci unsigned long long tvalue, int tinterval) 57f08c3bdfSopenharmony_ci{ 58f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci tst_its_set_value_from_us(tmr, tvalue); 61f08c3bdfSopenharmony_ci tst_its_set_interval_from_us(tmr, tinterval); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci if (tv->tfd_settime(tfd, tflags, tst_its_get(tmr), NULL)) 64f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "timerfd_settime() failed"); 65f08c3bdfSopenharmony_ci} 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_cistatic void waittmr(int tfd, unsigned int exp_ticks) 68f08c3bdfSopenharmony_ci{ 69f08c3bdfSopenharmony_ci uint64_t ticks; 70f08c3bdfSopenharmony_ci struct pollfd pfd; 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci pfd.fd = tfd; 73f08c3bdfSopenharmony_ci pfd.events = POLLIN; 74f08c3bdfSopenharmony_ci pfd.revents = 0; 75f08c3bdfSopenharmony_ci if (poll(&pfd, 1, -1) < 0) { 76f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "poll() failed"); 77f08c3bdfSopenharmony_ci return; 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci if ((pfd.revents & POLLIN) == 0) { 80f08c3bdfSopenharmony_ci tst_res(TFAIL, "no ticks happened"); 81f08c3bdfSopenharmony_ci return; 82f08c3bdfSopenharmony_ci } 83f08c3bdfSopenharmony_ci SAFE_READ(0, tfd, &ticks, sizeof(ticks)); 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci if (ticks != exp_ticks) { 86f08c3bdfSopenharmony_ci tst_res(TFAIL, "got %u tick(s) expected %u", 87f08c3bdfSopenharmony_ci (unsigned int)ticks, exp_ticks); 88f08c3bdfSopenharmony_ci } else { 89f08c3bdfSopenharmony_ci tst_res(TPASS, "got %u tick(s)", exp_ticks); 90f08c3bdfSopenharmony_ci } 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic void run(unsigned int n) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 96f08c3bdfSopenharmony_ci int tfd; 97f08c3bdfSopenharmony_ci unsigned long long tnow; 98f08c3bdfSopenharmony_ci uint64_t uticks; 99f08c3bdfSopenharmony_ci struct tst_its tmr = {.type = tv->ts_type, }; 100f08c3bdfSopenharmony_ci struct tcase *clks = &tcases[n]; 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci tst_res(TINFO, "testing %s", clks->name); 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci tfd = SAFE_TIMERFD_CREATE(clks->id, 0); 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci tst_res(TINFO, "relative timer (100 ms)"); 107f08c3bdfSopenharmony_ci settime(tfd, &tmr, 0, 100 * 1000, 0); 108f08c3bdfSopenharmony_ci waittmr(tfd, 1); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci tst_res(TINFO, "absolute timer (100 ms)"); 111f08c3bdfSopenharmony_ci tnow = getustime(clks->id); 112f08c3bdfSopenharmony_ci settime(tfd, &tmr, TFD_TIMER_ABSTIME, tnow + 100 * 1000, 0); 113f08c3bdfSopenharmony_ci waittmr(tfd, 1); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci tst_res(TINFO, "sequential timer (50 ms)"); 116f08c3bdfSopenharmony_ci tnow = getustime(clks->id); 117f08c3bdfSopenharmony_ci settime(tfd, &tmr, TFD_TIMER_ABSTIME, tnow + 50 * 1000, 50 * 1000); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci memset(&tmr, 0, sizeof(tmr)); 120f08c3bdfSopenharmony_ci tmr.type = tv->ts_type; 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci if (tv->tfd_gettime(tfd, tst_its_get(&tmr))) 123f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "timerfd_gettime() failed"); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci if (tst_its_get_value_sec(tmr) != 0 || tst_its_get_value_nsec(tmr) > 50 * 1000000) 126f08c3bdfSopenharmony_ci tst_res(TFAIL, "Timer read back value not relative"); 127f08c3bdfSopenharmony_ci else 128f08c3bdfSopenharmony_ci tst_res(TPASS, "Timer read back value is relative"); 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci usleep(160000); 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci waittmr(tfd, 3); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci tst_res(TINFO, "testing with O_NONBLOCK"); 135f08c3bdfSopenharmony_ci settime(tfd, &tmr, 0, 100 * 1000, 0); 136f08c3bdfSopenharmony_ci waittmr(tfd, 1); 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci SAFE_FCNTL(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci TEST(read(tfd, &uticks, sizeof(uticks))); 141f08c3bdfSopenharmony_ci if (TST_RET > 0) 142f08c3bdfSopenharmony_ci tst_res(TFAIL, "timer ticks not zero"); 143f08c3bdfSopenharmony_ci else if (TST_ERR != EAGAIN) 144f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "read should fail with EAGAIN got"); 145f08c3bdfSopenharmony_ci else 146f08c3bdfSopenharmony_ci tst_res(TPASS | TERRNO, "read failed with"); 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci SAFE_CLOSE(tfd); 149f08c3bdfSopenharmony_ci} 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_cistatic void setup(void) 152f08c3bdfSopenharmony_ci{ 153f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc); 154f08c3bdfSopenharmony_ci} 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_cistatic struct tst_test test = { 157f08c3bdfSopenharmony_ci .test = run, 158f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 159f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 160f08c3bdfSopenharmony_ci .setup = setup, 161f08c3bdfSopenharmony_ci}; 162