Source to kern/ns_timer.c


Enter a symbol's name here to quickly find it.

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the 'License').  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License."
 * 
 * @APPLE_LICENSE_HEADER_END@
 */

/*	@(#)ns_timer.c	1.0	12/8/87		(c) 1987 NeXT	*/

/* 
 * Copyright (c) 1992 NeXT, Inc.
 */ 

#import <sys/param.h>
#import <sys/kernel.h>
#import <bsd/sys/callout.h>
#import <kernserv/ns_timer.h>
#import <kernserv/clock_timer.h>
#import <bsd/machine/spl.h>
#import <kern/thread_call.h>

#if defined (__ppc__)
#import "machdep/ppc/longlong.h"
#elif defined (__i386__)
#import "machdep/i386/longlong.h"
#else
#error architecture not supported
#endif

/*
 * Micro-second Timer.
 */

/*
 *  Arrange that the function "proc" gets called in "time" nanoseconds.
 */
void ns_timeout(func proc, void *arg, ns_time_t time, int pri)
{
	int		s;
	tvalspec_t	deadline;
	extern
	    tvalspec_t	tick_stamp;

	s = splhigh();
	llp_div_l(&time, NSEC_PER_SEC, &deadline.tv_nsec);
	deadline.tv_sec = (unsigned int)time;
	ADD_TVALSPEC(&deadline, &tick_stamp);

	thread_call_func_delayed(
			(thread_call_func_t)proc,
			(thread_call_spec_t)arg, deadline);
	splx(s);
}

/*
 *  Arrange that the function "proc" gets called at "deadline" nanoseconds
 *  from boot.
 */
void ns_abstimeout(func proc, void *arg, ns_time_t time, int pri)
{
	int		s;
	tvalspec_t	deadline;

	s = splhigh();
	llp_div_l(&time, NSEC_PER_SEC, &deadline.tv_nsec);
	deadline.tv_sec = (unsigned int)time;

	thread_call_func_delayed(
			(thread_call_func_t)proc,
			(thread_call_spec_t)arg, deadline);
	splx(s);
}

/*
 * Remove something scheduled via ns_timeout or ns_abstimeout.
 */
boolean_t ns_untimeout(func proc, void *arg)
{
	thread_call_func_cancel(
			(thread_call_func_t)proc,
			(thread_call_spec_t)arg, FALSE);
		    
	return (TRUE);	/* XXX cheat */
}

void
ns_sleep(ns_time_t delay)
{
	int		s;
	extern void	wakeup(caddr_t chan);

	s = splhigh();
	ns_timeout((func)wakeup, &delay, delay, CALLOUT_PRI_SOFTINT1);
	/* make this uninterruptable */
	sleep((caddr_t)&delay, PZERO - 1);
	splx(s);
}

/*
 *  Conversion functions.  Loads o' fun.
 */
void
ns_time_to_timeval(ns_time_t nano_time, struct timeval *tvp)
{
	llp_div_l(&nano_time, 1000000000, (unsigned int *)&tvp->tv_usec);
	
	tvp->tv_sec = (unsigned long) nano_time;
	tvp->tv_usec /= 1000;
}

ns_time_t
timeval_to_ns_time(struct timeval *tvp)
{
	ns_time_t	a_time;

	a_time = (ns_time_t) tvp->tv_sec * 1000000ULL + tvp->tv_usec;
	a_time *= 1000ULL;

	return a_time;
}

/*
 * Return the best possible estimate of the time in the timeval
 * to which tvp points.
 */
void
microtime(struct timeval * tvp)
{
	tvalspec_t	now = clock_get_counter(Calendar);

	tvp->tv_sec = now.tv_sec;
	tvp->tv_usec = now.tv_nsec / NSEC_PER_USEC;
}

/*
 * microboot returns the number of microseconds since boot.
 */
void microboot(struct timeval *tvp)
{
	tvalspec_t	now = clock_get_counter(System);

	tvp->tv_sec = now.tv_sec;
	tvp->tv_usec = now.tv_nsec / NSEC_PER_USEC;
}