/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */
/*
 * $Id: nanosleep_benchmark.c,v 1.2 2003/06/30 02:20:07 rocko Exp $
 *
 * Copyright (c) 2000, 2001 by Shiman Associates Inc. and Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions: The above
 * copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the names of the authors or
 * copyright holders shall not be used in advertising or otherwise to
 * promote the sale, use or other dealings in this Software without
 * prior written authorization from the authors or copyright holders,
 * as applicable.
 *
 * All trademarks and registered trademarks mentioned herein are the
 * property of their respective owners. No right, title or interest in
 * or to any trademark, service mark, logo or trade name of the
 * authors or copyright holders or their licensors is granted.
 *
 */

#include <stdio.h>

#ifdef _POSIX_C_SOURCE
#include <sys/time.h>
#include <time.h>
#include <limits.h>
#include <sys/times.h>
#if _POSIX_C_SOURCE < 199309L || _NO_CLOCK_GETTIME
#include <unistd.h>
#endif /* needs unistd.h */
#endif /* POSIX */

#include "mas/mas_common.h"
#include "nanosleep_benchmark.h"

#define NSBENCH_TESTS    10

/***************************************************************************
 * mas_benchmark_nanosleep
 *
 * arguments:
 *    1. 32-bit unsigned microseconds
 *
 *  Empirically estimates the resolution we're getting out of
 *  nanosleep(), all the while watching the CPU usage to make sure
 *  the nanosleep() implementation isn't busy-waiting to give us that
 *  resolution. 
 *
 * returns: error
 *
 ***************************************************************************/
int32
mas_benchmark_nanosleep(struct mas_benchmark* benchmarks, int number,
			unsigned start, unsigned end, int output)
{
#ifdef _POSIX_C_SOURCE
    u_int32  sleep_for_ns;
    int      foundit = 0;
    int      entries = 0;
    u_int32  slept_avg_ns;
    u_int32  pre_sleep_usec_ts  = 0;
    u_int32  post_sleep_usec_ts = 0;
    int      i;
    struct tms pre_sleep_times;
    struct tms post_sleep_times;
    u_int32  avg_cpu_use;
    int step = (end - start)/number;

    /* range from 1ms to 100ms, step 1ms */
    for (sleep_for_ns = start; sleep_for_ns <= end; sleep_for_ns += step)
    {
	slept_avg_ns = 0;

	times(&pre_sleep_times);
	for (i=0; i<NSBENCH_TESTS; i++) /* each test 10 times */
	{
	    masc_get_short_usec_ts( &pre_sleep_usec_ts );
	    masc_nanosleep(sleep_for_ns);
	    masc_get_short_usec_ts ( &post_sleep_usec_ts );
	    slept_avg_ns += 1000*min((post_sleep_usec_ts -
				    pre_sleep_usec_ts), 999999)/NSBENCH_TESTS;
	}
	times(&post_sleep_times);
	/* this is system + user space CPU time */
	avg_cpu_use = ( post_sleep_times.tms_utime -
			 pre_sleep_times.tms_utime )
	    + ( post_sleep_times.tms_stime -
		pre_sleep_times.tms_stime );
	avg_cpu_use = (avg_cpu_use * CLOCKS_PER_SEC) / NSBENCH_TESTS;
	
	if (output) fprintf(stderr, "%u %u %u\n", sleep_for_ns, avg_cpu_use,
			   slept_avg_ns); 
	
	if (entries < number)
	{
	    benchmarks[entries].value = sleep_for_ns;
	    benchmarks[entries].cpu_time = avg_cpu_use;
	    benchmarks[entries].wall_clock_time = slept_avg_ns;
	}

	entries++;
    }
#else /* ! _POSIX_SOURCE */
    return -1;
#endif /* _POSIX_SOURCE */
    
}


