cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nanosleep.c (4052B)


      1/* Make sure timers don't return early
      2 *              by: john stultz (johnstul@us.ibm.com)
      3 *		    John Stultz (john.stultz@linaro.org)
      4 *              (C) Copyright IBM 2012
      5 *              (C) Copyright Linaro 2013 2015
      6 *              Licensed under the GPLv2
      7 *
      8 *  To build:
      9 *	$ gcc nanosleep.c -o nanosleep -lrt
     10 *
     11 *   This program is free software: you can redistribute it and/or modify
     12 *   it under the terms of the GNU General Public License as published by
     13 *   the Free Software Foundation, either version 2 of the License, or
     14 *   (at your option) any later version.
     15 *
     16 *   This program is distributed in the hope that it will be useful,
     17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 *   GNU General Public License for more details.
     20 */
     21
     22#include <errno.h>
     23#include <stdio.h>
     24#include <stdlib.h>
     25#include <time.h>
     26#include <sys/time.h>
     27#include <sys/timex.h>
     28#include <string.h>
     29#include <signal.h>
     30#include "../kselftest.h"
     31
     32#define NSEC_PER_SEC 1000000000ULL
     33
     34#define CLOCK_REALTIME			0
     35#define CLOCK_MONOTONIC			1
     36#define CLOCK_PROCESS_CPUTIME_ID	2
     37#define CLOCK_THREAD_CPUTIME_ID		3
     38#define CLOCK_MONOTONIC_RAW		4
     39#define CLOCK_REALTIME_COARSE		5
     40#define CLOCK_MONOTONIC_COARSE		6
     41#define CLOCK_BOOTTIME			7
     42#define CLOCK_REALTIME_ALARM		8
     43#define CLOCK_BOOTTIME_ALARM		9
     44#define CLOCK_HWSPECIFIC		10
     45#define CLOCK_TAI			11
     46#define NR_CLOCKIDS			12
     47
     48#define UNSUPPORTED 0xf00f
     49
     50char *clockstring(int clockid)
     51{
     52	switch (clockid) {
     53	case CLOCK_REALTIME:
     54		return "CLOCK_REALTIME";
     55	case CLOCK_MONOTONIC:
     56		return "CLOCK_MONOTONIC";
     57	case CLOCK_PROCESS_CPUTIME_ID:
     58		return "CLOCK_PROCESS_CPUTIME_ID";
     59	case CLOCK_THREAD_CPUTIME_ID:
     60		return "CLOCK_THREAD_CPUTIME_ID";
     61	case CLOCK_MONOTONIC_RAW:
     62		return "CLOCK_MONOTONIC_RAW";
     63	case CLOCK_REALTIME_COARSE:
     64		return "CLOCK_REALTIME_COARSE";
     65	case CLOCK_MONOTONIC_COARSE:
     66		return "CLOCK_MONOTONIC_COARSE";
     67	case CLOCK_BOOTTIME:
     68		return "CLOCK_BOOTTIME";
     69	case CLOCK_REALTIME_ALARM:
     70		return "CLOCK_REALTIME_ALARM";
     71	case CLOCK_BOOTTIME_ALARM:
     72		return "CLOCK_BOOTTIME_ALARM";
     73	case CLOCK_TAI:
     74		return "CLOCK_TAI";
     75	};
     76	return "UNKNOWN_CLOCKID";
     77}
     78
     79/* returns 1 if a <= b, 0 otherwise */
     80static inline int in_order(struct timespec a, struct timespec b)
     81{
     82	if (a.tv_sec < b.tv_sec)
     83		return 1;
     84	if (a.tv_sec > b.tv_sec)
     85		return 0;
     86	if (a.tv_nsec > b.tv_nsec)
     87		return 0;
     88	return 1;
     89}
     90
     91struct timespec timespec_add(struct timespec ts, unsigned long long ns)
     92{
     93	ts.tv_nsec += ns;
     94	while (ts.tv_nsec >= NSEC_PER_SEC) {
     95		ts.tv_nsec -= NSEC_PER_SEC;
     96		ts.tv_sec++;
     97	}
     98	return ts;
     99}
    100
    101int nanosleep_test(int clockid, long long ns)
    102{
    103	struct timespec now, target, rel;
    104
    105	/* First check abs time */
    106	if (clock_gettime(clockid, &now))
    107		return UNSUPPORTED;
    108	target = timespec_add(now, ns);
    109
    110	if (clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL))
    111		return UNSUPPORTED;
    112	clock_gettime(clockid, &now);
    113
    114	if (!in_order(target, now))
    115		return -1;
    116
    117	/* Second check reltime */
    118	clock_gettime(clockid, &now);
    119	rel.tv_sec = 0;
    120	rel.tv_nsec = 0;
    121	rel = timespec_add(rel, ns);
    122	target = timespec_add(now, ns);
    123	clock_nanosleep(clockid, 0, &rel, NULL);
    124	clock_gettime(clockid, &now);
    125
    126	if (!in_order(target, now))
    127		return -1;
    128	return 0;
    129}
    130
    131int main(int argc, char **argv)
    132{
    133	long long length;
    134	int clockid, ret;
    135
    136	for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
    137
    138		/* Skip cputime clockids since nanosleep won't increment cputime */
    139		if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
    140				clockid == CLOCK_THREAD_CPUTIME_ID ||
    141				clockid == CLOCK_HWSPECIFIC)
    142			continue;
    143
    144		printf("Nanosleep %-31s ", clockstring(clockid));
    145		fflush(stdout);
    146
    147		length = 10;
    148		while (length <= (NSEC_PER_SEC * 10)) {
    149			ret = nanosleep_test(clockid, length);
    150			if (ret == UNSUPPORTED) {
    151				printf("[UNSUPPORTED]\n");
    152				goto next;
    153			}
    154			if (ret < 0) {
    155				printf("[FAILED]\n");
    156				return ksft_exit_fail();
    157			}
    158			length *= 100;
    159		}
    160		printf("[OK]\n");
    161next:
    162		ret = 0;
    163	}
    164	return ksft_exit_pass();
    165}