Commit bd0527dc authored by Matthias Braun's avatar Matthias Braun
Browse files

rework architecture specific timer code

[r26081]
parent 80d22a2b
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief OS abstraction from time measurement
* @author Sebastian Hack, Michael Beck, Matthias Braun
* @version $Id$
*/
#include "config.h"
#include <stdio.h>
#include "stat_timing.h" #include "stat_timing.h"
#include <stdio.h>
#ifdef __linux__
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
/* define GNU macro for processor affinity stuff if on linux */
#if defined __linux__ && !defined __USE_GNU
#define __USE_GNU
#endif
#include <sched.h>
/* we can only use the scheduling stuff, if that macro is defined in unistd.h */ /* we can only use the scheduling stuff, if that macro is defined in unistd.h */
#if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1 #if defined(_XOPEN_REALTIME) && _XOPEN_REALTIME != -1
timing_sched_env_t *timing_sched_get(timing_sched_env_t *env) #define HAVE_IMPL
static int in_max_prio = 0;
static cpu_set_t affinity;
static int scheduler;
static struct sched_param sched_params;
void timing_enter_max_prio(void)
{ {
int res; int res;
int new_scheduler = SCHED_FIFO;
struct sched_param new_sched_params;
cpu_set_t new_affinity;
#ifdef __linux__ if (in_max_prio)
res = sched_getaffinity(0, sizeof(env->affinity), &env->affinity); return;
if (res < 0)
return NULL;
#endif
env->scheduler = sched_getscheduler(0); /* remember old scheduler settings */
if (env->scheduler < 0) res = sched_getaffinity(0, sizeof(affinity), &affinity);
return NULL; if (res < 0)
return;
scheduler = sched_getscheduler(0);
if (scheduler < 0)
return;
res = sched_getparam(0, &sched_params);
if (res < 0)
return;
res = sched_getparam(0, &env->params); /* set high prio */
CPU_ZERO(&new_affinity);
CPU_SET(0, &new_affinity);
res = sched_setaffinity(0, sizeof(new_affinity), &new_affinity);
if (res < 0) if (res < 0)
return NULL; return;
new_scheduler = SCHED_FIFO;
sched_params.sched_priority = sched_get_priority_max(new_scheduler);
sched_setscheduler(0, new_scheduler, &new_sched_params);
if (res < 0)
return;
return env; in_max_prio = 1;
} }
int timing_sched_set(const timing_sched_env_t *env) void timing_leave_max_prio(void)
{ {
int res; int res;
#ifdef __linux__ if (!in_max_prio)
res = sched_setaffinity(0, sizeof(env->affinity), &env->affinity); return;
/* restore old settings */
res = sched_setaffinity(0, sizeof(affinity), &affinity);
if (res < 0) if (res < 0)
return 0; return;
#endif
res = sched_setscheduler(0, env->scheduler, &env->params); sched_setscheduler(0, scheduler, &sched_params);
if (res < 0) if (res < 0)
return 0; return;
return 1; in_max_prio = 0;
} }
timing_sched_env_t *timing_sched_prepare_max_prio(timing_sched_env_t *env)
{
int policy = SCHED_FIFO;
#ifdef __linux__
CPU_ZERO(&env->affinity);
CPU_SET(0, &env->affinity);
#endif #endif
env->scheduler = policy; #endif
env->params.sched_priority = sched_get_priority_max(policy);
return env;
}
#else
timing_sched_env_t *timing_sched_get(timing_sched_env_t *env) #ifndef HAVE_IMPL
{
(void) env; /* dummy implementation */
return NULL;
}
int timing_sched_set(const timing_sched_env_t *env) void timing_enter_max_prio(void)
{ {
(void) env;
return 0;
} }
timing_sched_env_t *timing_sched_prepare_max_prio(timing_sched_env_t *env) void timing_leave_max_prio(void)
{ {
return env;
} }
#endif /* _POSIX_PRIORITY_SCHEDULING */ #endif
#ifndef _TICKS_H
#define _TICKS_H
/* /*
* To use the Pentium RDTSC timer * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
* define TIMING_USE_RDTSC when including *
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/ */
#define TIMING_USE_RDTSC
#if defined(_WIN32)
#ifdef TIMING_USE_RDTSC /**
* @file
* @brief OS abstraction from time measurement
* @author Sebastian Hack, Michael Beck, Matthias Braun
* @version $Id$
*/
#ifndef FIRM_STAT_TIMING_H
#define FIRM_STAT_TIMING_H
typedef unsigned __int64 timing_ticks_t; #ifdef __i386__
__inline timing_ticks_t __timing_ticks(void) { __asm { rdtsc } } #ifdef __GNUC__
#define timing_ticks(t) ((t) = __timing_ticks())
#define timing_ticks_init(t) ((t) = 0)
#define timing_ticks_cmp(a, b, cmp) ((a) cmp (b))
#define timing_ticks_sub(r, a) ((r) = (r) - (a))
#define timing_ticks_add(r, a) ((r) = (r) + (a))
#define timing_ticks_ulong(t) ((unsigned long) (t))
#define timing_ticks_dbl(t) ((double) (t))
typedef unsigned long long timing_ticks_t;
static inline timing_ticks_t __timing_ticks(void) { timing_ticks_t result; __asm__ __volatile__ ("rdtsc" : "=A" (result)); return result; }
#else #else
#error NOT IMPLEMENTED YET #if define _MSC_VER
#endif /* TIMING_USE_RDTSC */ /* win32 implementation using rdtsc */
typedef unsigned __int64 timing_ticks_t;
typedef struct { static __inline timing_ticks_t __timing_ticks(void) { __asm { rdtsc } }
int dummy; #else
} timing_sched_env_t; #error need a 64bit int type
#else /* POSIX/Linux stuff */
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
/* define GNU macro for processor affinity stuff if on linux */
#if defined __linux__ && !defined __USE_GNU
#define __USE_GNU
#endif
#include <sched.h>
typedef struct {
#ifdef _POSIX_PRIORITY_SCHEDULING
struct sched_param params;
#endif #endif
int scheduler;
#ifdef __linux__
cpu_set_t affinity;
#endif #endif
} timing_sched_env_t;
/* only use rdtsc on GNU C with x86 */ #define timing_ticks(t) ((t) = __timing_ticks())
#if defined TIMING_USE_RDTSC && defined __GNUC__ && defined __i386__
typedef unsigned long long timing_ticks_t;
#define timing_ticks(t) __asm__ __volatile__ ("rdtsc" : "=A" (t))
#define timing_ticks_init(t) ((t) = 0) #define timing_ticks_init(t) ((t) = 0)
#define timing_ticks_cmp(a, b, cmp) ((a) cmp (b)) #define timing_ticks_cmp(a, b, cmp) ((a) cmp (b))
#define timing_ticks_sub(r, a) ((r) = (r) - (a)) #define timing_ticks_sub(r, a) ((r) = (r) - (a))
...@@ -66,7 +50,9 @@ typedef unsigned long long timing_ticks_t; ...@@ -66,7 +50,9 @@ typedef unsigned long long timing_ticks_t;
#define timing_ticks_ulong(t) ((unsigned long) (t)) #define timing_ticks_ulong(t) ((unsigned long) (t))
#define timing_ticks_dbl(t) ((double) (t)) #define timing_ticks_dbl(t) ((double) (t))
#else #else /* !__i386__ */
#include <sys/time.h>
typedef struct timeval timing_ticks_t; typedef struct timeval timing_ticks_t;
#define timing_ticks(t) (gettimeofday(&(t), NULL)) #define timing_ticks(t) (gettimeofday(&(t), NULL))
...@@ -104,27 +90,9 @@ typedef struct timeval timing_ticks_t; ...@@ -104,27 +90,9 @@ typedef struct timeval timing_ticks_t;
#define timing_ticks_ulong(t) ((unsigned long) ((t).tv_usec + 1000000 * (t).tv_sec)) #define timing_ticks_ulong(t) ((unsigned long) ((t).tv_usec + 1000000 * (t).tv_sec))
#define timing_ticks_dbl(t) (((t).tv_usec + 1000000.0 * (t).tv_sec)) #define timing_ticks_dbl(t) (((t).tv_usec + 1000000.0 * (t).tv_sec))
#endif /* TIMING_USE_RDTSC ... */ #endif
#endif /* _WIN32 */
/**
* Set the current schedule parameters.
* @return 1, if succeeded, 0 if not (see errno, for details).
*/
int timing_sched_set(const timing_sched_env_t *env);
/**
* Get the schedule parameters.
* @return 1, if succeeded, 0 if not (see errno, for details).
*/
timing_sched_env_t *timing_sched_get(timing_sched_env_t *env);
/** void timing_enter_max_prio(void);
* Prepare schedule parameters which limit the process on one CPU void timing_leave_max_prio(void);
* and set the maximum task priority.
* @return The paramter @p env.
*/
timing_sched_env_t *timing_sched_prepare_max_prio(timing_sched_env_t *env);
#endif /* _TICKS_H */ #endif
...@@ -63,12 +63,10 @@ static FILE* stat_ev_file = NULL; ...@@ -63,12 +63,10 @@ static FILE* stat_ev_file = NULL;
#endif /* FIRM_HAVE_LIBZ */ #endif /* FIRM_HAVE_LIBZ */
int stat_ev_enabled = 0; int stat_ev_enabled = 0;
int stat_ev_timer_sp = 0; int stat_ev_timer_sp = 0;
timing_ticks_t stat_ev_timer_elapsed[MAX_TIMER]; timing_ticks_t stat_ev_timer_elapsed[MAX_TIMER];
timing_ticks_t stat_ev_timer_start[MAX_TIMER]; timing_ticks_t stat_ev_timer_start[MAX_TIMER];
timing_sched_env_t stat_ev_sched_rt;
timing_sched_env_t stat_ev_sched_normal;
#ifdef FIRM_HAVE_REGEX #ifdef FIRM_HAVE_REGEX
#include <regex.h> #include <regex.h>
...@@ -139,8 +137,6 @@ void stat_ev_begin(const char *prefix, const char *filt) ...@@ -139,8 +137,6 @@ void stat_ev_begin(const char *prefix, const char *filt)
} }
stat_ev_enabled = stat_ev_file != NULL; stat_ev_enabled = stat_ev_file != NULL;
timing_sched_get(&stat_ev_sched_normal);
timing_sched_prepare_max_prio(&stat_ev_sched_rt);
} }
void stat_ev_end(void) void stat_ev_end(void)
......
...@@ -55,22 +55,20 @@ ...@@ -55,22 +55,20 @@
#include <stdio.h> #include <stdio.h>
#include "stat_timing.h" #include "stat_timing.h"
extern void stat_ev_printf(char ev_type, const char *key, const char *fmt, ...); extern void stat_ev_printf(char ev_type, const char *key, const char *fmt, ...);
extern int stat_ev_enabled; extern int stat_ev_enabled;
extern int stat_ev_timer_sp; extern int stat_ev_timer_sp;
extern timing_ticks_t stat_ev_timer_elapsed[]; extern timing_ticks_t stat_ev_timer_elapsed[];
extern timing_ticks_t stat_ev_timer_start[]; extern timing_ticks_t stat_ev_timer_start[];
extern timing_sched_env_t stat_ev_sched_rt;
extern timing_sched_env_t stat_ev_sched_normal;
static inline __attribute__((unused)) void stat_ev_tim_push(void) { static inline __attribute__((unused)) void stat_ev_tim_push(void) {
timing_ticks_t temp; timing_ticks_t temp;
int sp = stat_ev_timer_sp++; int sp = stat_ev_timer_sp++;
timing_ticks(temp); timing_ticks(temp);
if (sp == 0) if (sp == 0) {
timing_sched_set(&stat_ev_sched_rt); timing_enter_max_prio();
else { } else {
timing_ticks_sub(temp, stat_ev_timer_start[sp - 1]); timing_ticks_sub(temp, stat_ev_timer_start[sp - 1]);
timing_ticks_add(stat_ev_timer_elapsed[sp - 1], temp); timing_ticks_add(stat_ev_timer_elapsed[sp - 1], temp);
} }
...@@ -87,10 +85,11 @@ static inline __attribute__((unused)) void stat_ev_tim_pop(const char *name) { ...@@ -87,10 +85,11 @@ static inline __attribute__((unused)) void stat_ev_tim_pop(const char *name) {
timing_ticks_add(stat_ev_timer_elapsed[sp], temp); timing_ticks_add(stat_ev_timer_elapsed[sp], temp);
if (name != NULL && stat_ev_enabled) if (name != NULL && stat_ev_enabled)
stat_ev_printf('E', name, "%g", timing_ticks_dbl(stat_ev_timer_elapsed[sp])); stat_ev_printf('E', name, "%g", timing_ticks_dbl(stat_ev_timer_elapsed[sp]));
if (sp == 0) if (sp == 0) {
timing_sched_set(&stat_ev_sched_normal); timing_leave_max_prio();
else } else {
timing_ticks(stat_ev_timer_start[sp - 1]); timing_ticks(stat_ev_timer_start[sp - 1]);
}
} }
#define stat_ev_ctx_push_fmt(key, fmt, value) \ #define stat_ev_ctx_push_fmt(key, fmt, value) \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment