aboutsummaryrefslogtreecommitdiffstats
path: root/docker
diff options
context:
space:
mode:
Diffstat (limited to 'docker')
0 files changed, 0 insertions, 0 deletions
f='#n108'>108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
/*
 * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
 * Copyright (C) 2012-2014 Cisco Systems
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
 * Licensed under the GPL
 */

#include <stddef.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <kern_util.h>
#include <os.h>
#include <string.h>
#include <timer-internal.h>

static timer_t event_high_res_timer = 0;

static inline long long timeval_to_ns(const struct timeval *tv)
{
	return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
		tv->tv_usec * UM_NSEC_PER_USEC;
}

static inline long long timespec_to_ns(const struct timespec *ts)
{
	return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) +
		ts->tv_nsec;
}

long long os_persistent_clock_emulation (void) {
	struct timespec realtime_tp;

	clock_gettime(CLOCK_REALTIME, &realtime_tp);
	return timespec_to_ns(&realtime_tp);
}

/**
 * os_timer_create() - create an new posix (interval) timer
 */
int os_timer_create(void* timer) {

	timer_t* t = timer;

	if(t == NULL) {
		t = &event_high_res_timer;
	}

	if (timer_create(
		CLOCK_MONOTONIC,
		NULL,
		t) == -1) {
		return -1;
	}
	return 0;
}

int os_timer_set_interval(void* timer, void* i)
{
	struct itimerspec its;
	unsigned long long nsec;
	timer_t* t = timer;
	struct itimerspec* its_in = i;

	if(t == NULL) {
		t = &event_high_res_timer;
	}

	nsec = UM_NSEC_PER_SEC / UM_HZ;

	if(its_in != NULL) {
		its.it_value.tv_sec = its_in->it_value.tv_sec;
		its.it_value.tv_nsec = its_in->it_value.tv_nsec;
	} else {
		its.it_value.tv_sec = 0;
		its.it_value.tv_nsec = nsec;
	}

	its.it_interval.tv_sec = 0;
	its.it_interval.tv_nsec = nsec;

	if(timer_settime(*t, 0, &its, NULL) == -1) {
		return -errno;
	}

	return 0;
}

/**
 * os_timer_remain() - returns the remaining nano seconds of the given interval
 *                     timer
 * Because this is the remaining time of an interval timer, which correspondends
 * to HZ, this value can never be bigger than one second. Just
 * the nanosecond part of the timer is returned.
 * The returned time is relative to the start time of the interval timer.
 * Return an negative value in an error case.
 */
long os_timer_remain(void* timer)
{
	struct itimerspec its;
	timer_t* t = timer;

	if(t == NULL) {
		t = &event_high_res_timer;
	}

	if(timer_gettime(t, &its) == -1) {
		return -errno;
	}

	return its.it_value.tv_nsec;
}

int os_timer_one_shot(int ticks)
{
	struct itimerspec its;
	unsigned long long nsec;
	unsigned long sec;

    nsec = (ticks + 1);
    sec = nsec / UM_NSEC_PER_SEC;
	nsec = nsec % UM_NSEC_PER_SEC;

	its.it_value.tv_sec = nsec / UM_NSEC_PER_SEC;
	its.it_value.tv_nsec = nsec;

	its.it_interval.tv_sec = 0;
	its.it_interval.tv_nsec = 0; // we cheat here

	timer_settime(event_high_res_timer, 0, &its, NULL);
	return 0;
}

/**
 * os_timer_disable() - disable the posix (interval) timer
 * Returns the remaining interval timer time in nanoseconds
 */
long long os_timer_disable(void)
{
	struct itimerspec its;

	memset(&its, 0, sizeof(struct itimerspec));
	timer_settime(event_high_res_timer, 0, &its, &its);

	return its.it_value.tv_sec * UM_NSEC_PER_SEC + its.it_value.tv_nsec;
}

long long os_vnsecs(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&ts);
	return timespec_to_ns(&ts);
}

long long os_nsecs(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC,&ts);
	return timespec_to_ns(&ts);
}

/**
 * os_idle_sleep() - sleep for a given time of nsecs
 * @nsecs: nanoseconds to sleep
 */
void os_idle_sleep(unsigned long long nsecs)
{
	struct timespec ts;

	if (nsecs <= 0) {
		return;
	}

	ts = ((struct timespec) {
			.tv_sec  = nsecs / UM_NSEC_PER_SEC,
			.tv_nsec = nsecs % UM_NSEC_PER_SEC
	});

	/*
	 * Relay the signal if clock_nanosleep is interrupted.
	 */
	if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL)) {
		deliver_alarm();
	}
}