//-----------------------------------------------------------------------------
// Copyright © 2006 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/time
// purpose	Support daemon startup
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#include "time_lib.h"

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	timer_mod_set_usec
// macro	timer_mod_set_sec
// macro	time_mod_set_msec
// macro	time_mod_set_nsec
//
// purpose	Set the interval timer to signal the alarm at expiration based
//		on a fixed repeating modulo time interval and an offset within
//		the repeating interval, both with 64 bit integer values.  If
//		the requested offset is greater than the offset of the current
//		time within the current cycle, the expiration will be in the
//		current cycle.
//
// arguments	1 (timeus_t) repeating modulus in microseconds
//		2 (timeus_t) offset in modulus in microseconds
//
// returns	(int) -1 : error
//		(int)  0 : OK
//-----------------------------------------------------------------------------
#define timer_mod_set_sec(m,o) timer_mod_set_usec((timeus_t)(m)*1000000UL,(timeus_t)(o)*1000000UL)
#define timer_mod_set_msec(m,o) timer_mod_set_usec((timeus_t)(m)*1000UL,(timeus_t)(p)*1000UL)
#define timer_mod_set_nsec(m,o) timer_mod_set_usec(((timeus_t)(m)+999UL)/1000UL,((timeus_t)(o)+999UL)/1000UL)
int
timer_mod_set_usec (
    timeus_t	arg_modulo
    ,
    timeus_t	arg_offset
    )
__PROTO_END__
{
    timeus_t	time64		;
    struct itimerval	timeit		;

    if ( arg_modulo > 0 ) {
	gettimeofday( & ( timeit.it_value ), NULL );
	time64 = timeit.it_value.tv_sec;
	time64 *= (timeus_t) 1000000;
	time64 += (long) ( timeit.it_value.tv_usec );
	time64 = arg_modulo - ( ( time64 - arg_offset ) % arg_modulo );
	if ( time64 == 0 ) time64 = arg_modulo;
    } else {
	time64 = arg_offset;
    }
    timeit.it_interval.tv_sec = 0;
    timeit.it_interval.tv_usec = 0;
    timeit.it_value.tv_sec = time64 / (timeus_t) 1000000;
    timeit.it_value.tv_usec = time64 % (timeus_t) 1000000;
    return setitimer( ITIMER_REAL, & timeit, NULL );
}

