2006-08-31 10:27:20 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2006 Mozilla Corporation
|
|
|
|
|
* Copyright © 2006 Red Hat, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
|
|
|
* and its documentation for any purpose is hereby granted without
|
|
|
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
|
|
|
* and that both that copyright notice and this permission notice
|
|
|
|
|
* appear in supporting documentation, and that the name of
|
|
|
|
|
* the authors not be used in advertising or publicity pertaining to
|
|
|
|
|
* distribution of the software without specific, written prior
|
|
|
|
|
* permission. The authors make no representations about the
|
|
|
|
|
* suitability of this software for any purpose. It is provided "as
|
|
|
|
|
* is" without express or implied warranty.
|
|
|
|
|
*
|
|
|
|
|
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
|
* FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL,
|
|
|
|
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
|
|
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
|
|
|
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*
|
|
|
|
|
* Authors: Vladimir Vukicevic <vladimir@pobox.com>
|
|
|
|
|
* Carl Worth <cworth@cworth.org>
|
|
|
|
|
*/
|
|
|
|
|
|
2006-09-06 01:37:13 -07:00
|
|
|
/* Portions of this file come from liboil:
|
|
|
|
|
*
|
|
|
|
|
* LIBOIL - Library of Optimized Inner Loops
|
|
|
|
|
* Copyright (c) 2003,2004 David A. Schleef <ds@schleef.org>
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
2006-08-31 10:27:20 -07:00
|
|
|
#include <signal.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <unistd.h>
|
2006-09-05 22:36:56 -07:00
|
|
|
#ifdef _POSIX_PRIORITY_SCHEDULING
|
|
|
|
|
#include <sched.h>
|
|
|
|
|
#endif
|
2006-08-31 10:27:20 -07:00
|
|
|
|
2006-08-31 10:39:24 -07:00
|
|
|
#include "cairo-perf.h"
|
2006-08-31 10:27:20 -07:00
|
|
|
|
|
|
|
|
/* timers */
|
|
|
|
|
|
2006-09-06 01:37:13 -07:00
|
|
|
#if defined(__i386__) || defined(__amd64__)
|
|
|
|
|
static inline unsigned long
|
|
|
|
|
oil_profile_stamp_rdtsc (void)
|
|
|
|
|
{
|
|
|
|
|
unsigned long ts;
|
|
|
|
|
__asm__ __volatile__("rdtsc\n" : "=a" (ts) : : "edx");
|
|
|
|
|
return ts;
|
|
|
|
|
}
|
|
|
|
|
#define OIL_STAMP oil_profile_stamp_rdtsc
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__powerpc__) || defined(__PPC__) || defined(__ppc__)
|
|
|
|
|
static inline cairo_perf_ticks_t
|
|
|
|
|
oil_profile_stamp_tb(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned long ts;
|
|
|
|
|
__asm__ __volatile__("mftb %0\n" : "=r" (ts));
|
|
|
|
|
return ts;
|
|
|
|
|
}
|
|
|
|
|
#define OIL_STAMP oil_profile_stamp_tb
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__alpha__)
|
|
|
|
|
static inline cairo_perf_ticks_t
|
|
|
|
|
oil_profile_stamp_alpha(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned int ts;
|
|
|
|
|
__asm__ __volatile__ ("rpcc %0\n" : "=r"(ts));
|
|
|
|
|
return ts;
|
|
|
|
|
}
|
|
|
|
|
#define OIL_STAMP oil_profile_stamp_alpha
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__s390__)
|
|
|
|
|
static cairo_perf_ticks_t
|
|
|
|
|
oil_profile_stamp_s390(void)
|
|
|
|
|
{
|
|
|
|
|
uint64_t ts;
|
|
|
|
|
__asm__ __volatile__ ("STCK %0\n" : : "m" (ts));
|
|
|
|
|
return ts;
|
|
|
|
|
}
|
|
|
|
|
#define OIL_STAMP oil_profile_stamp_s390
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-09-05 22:58:33 -07:00
|
|
|
typedef struct _cairo_perf_timer
|
2006-09-05 22:48:38 -07:00
|
|
|
{
|
2006-09-06 01:37:13 -07:00
|
|
|
#ifdef OIL_STAMP
|
|
|
|
|
cairo_perf_ticks_t start;
|
|
|
|
|
cairo_perf_ticks_t stop;
|
|
|
|
|
#else
|
|
|
|
|
struct timeval tv_start;
|
|
|
|
|
struct timeval tv_stop;
|
|
|
|
|
#endif
|
2006-09-05 22:58:33 -07:00
|
|
|
} cairo_perf_timer_t;
|
|
|
|
|
|
|
|
|
|
static cairo_perf_timer_t timer;
|
2006-09-05 22:48:38 -07:00
|
|
|
|
2006-10-05 15:14:14 -07:00
|
|
|
static cairo_perf_timer_synchronize_t cairo_perf_timer_synchronize = NULL;
|
|
|
|
|
static void *cairo_perf_timer_synchronize_closure = NULL;
|
2006-09-09 20:17:08 -07:00
|
|
|
void
|
2006-10-05 15:14:14 -07:00
|
|
|
cairo_perf_timer_set_synchronize (cairo_perf_timer_synchronize_t synchronize,
|
|
|
|
|
void *closure)
|
2006-09-09 20:17:08 -07:00
|
|
|
{
|
2006-10-05 15:14:14 -07:00
|
|
|
cairo_perf_timer_synchronize = synchronize;
|
|
|
|
|
cairo_perf_timer_synchronize_closure = closure;
|
2006-09-09 20:17:08 -07:00
|
|
|
}
|
|
|
|
|
|
2006-10-05 15:07:52 -07:00
|
|
|
void
|
|
|
|
|
cairo_perf_timer_start (void) {
|
2006-10-05 15:14:14 -07:00
|
|
|
if (cairo_perf_timer_synchronize)
|
|
|
|
|
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
|
2006-10-05 15:07:52 -07:00
|
|
|
#ifdef OIL_STAMP
|
|
|
|
|
timer.start = OIL_STAMP ();
|
|
|
|
|
#else
|
|
|
|
|
gettimeofday (&timer.tv_start, NULL);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-31 10:27:20 -07:00
|
|
|
void
|
2006-09-05 22:58:33 -07:00
|
|
|
cairo_perf_timer_stop (void) {
|
2006-10-05 15:14:14 -07:00
|
|
|
if (cairo_perf_timer_synchronize)
|
|
|
|
|
cairo_perf_timer_synchronize (cairo_perf_timer_synchronize_closure);
|
2006-09-06 01:37:13 -07:00
|
|
|
#ifdef OIL_STAMP
|
|
|
|
|
timer.stop = OIL_STAMP ();
|
|
|
|
|
#else
|
|
|
|
|
gettimeofday (&timer.tv_stop, NULL);
|
|
|
|
|
#endif
|
2006-08-31 10:27:20 -07:00
|
|
|
}
|
|
|
|
|
|
2006-09-06 00:15:49 -07:00
|
|
|
cairo_perf_ticks_t
|
2006-09-05 22:58:33 -07:00
|
|
|
cairo_perf_timer_elapsed (void) {
|
2006-09-06 01:37:13 -07:00
|
|
|
cairo_perf_ticks_t ticks;
|
2006-08-31 10:27:20 -07:00
|
|
|
|
2006-09-06 01:37:13 -07:00
|
|
|
#ifdef OIL_STAMP
|
2006-09-06 05:07:08 -07:00
|
|
|
/* Handle 32-bit wraparound of timer value */
|
|
|
|
|
if (timer.stop < timer.start)
|
|
|
|
|
timer.stop += 0x100000000ll;
|
2006-09-06 01:37:13 -07:00
|
|
|
ticks = (timer.stop - timer.start);
|
|
|
|
|
#else
|
|
|
|
|
ticks = (timer.tv_stop.tv_sec - timer.tv_start.tv_sec) * 1000000;
|
|
|
|
|
ticks += (timer.tv_stop.tv_usec - timer.tv_start.tv_usec);
|
|
|
|
|
#endif
|
2006-08-31 10:27:20 -07:00
|
|
|
|
2006-09-06 01:37:13 -07:00
|
|
|
return ticks;
|
2006-09-06 00:15:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_perf_ticks_t
|
|
|
|
|
cairo_perf_ticks_per_second (void) {
|
2006-09-06 01:37:13 -07:00
|
|
|
#ifdef OIL_STAMP
|
|
|
|
|
static cairo_perf_ticks_t tps = 0;
|
|
|
|
|
/* XXX: This is obviously not stable in light of changing CPU speed. */
|
|
|
|
|
if (tps == 0) {
|
|
|
|
|
struct timeval tv_start, tv_stop;
|
|
|
|
|
double tv_elapsed;
|
|
|
|
|
cairo_perf_timer_start ();
|
|
|
|
|
gettimeofday (&tv_start, NULL);
|
2006-09-06 03:32:07 -07:00
|
|
|
usleep (20000);
|
2006-09-06 01:37:13 -07:00
|
|
|
cairo_perf_timer_stop ();
|
|
|
|
|
gettimeofday (&tv_stop, NULL);
|
|
|
|
|
tv_elapsed = ((tv_stop.tv_sec - tv_start.tv_sec) +
|
|
|
|
|
+ (tv_stop.tv_usec - tv_start.tv_usec) / 1000000.0);
|
|
|
|
|
tps = round (cairo_perf_timer_elapsed () / tv_elapsed);
|
|
|
|
|
}
|
|
|
|
|
return tps;
|
|
|
|
|
#else
|
|
|
|
|
/* For gettimeofday the units are micro-seconds */
|
2006-09-06 00:15:49 -07:00
|
|
|
return 1000000;
|
2006-09-06 01:37:13 -07:00
|
|
|
#endif
|
2006-08-31 10:27:20 -07:00
|
|
|
}
|
|
|
|
|
|
2006-09-05 22:36:56 -07:00
|
|
|
/* yield */
|
|
|
|
|
|
|
|
|
|
void
|
2006-09-05 22:58:33 -07:00
|
|
|
cairo_perf_yield (void) {
|
2006-09-05 22:36:56 -07:00
|
|
|
#ifdef _POSIX_PRIORITY_SCHEDULING
|
|
|
|
|
sched_yield ();
|
|
|
|
|
#endif
|
|
|
|
|
}
|