|
Server : Apache/2.2.2 (Fedora) System : Linux App1.pathumtani.go.th 2.6.20-1.2320.fc5smp #1 SMP Tue Jun 12 19:40:16 EDT 2007 i686 User : apache ( 48) PHP Version : 5.2.9 Disable Function : NONE Directory : /usr/share/systemtap/tapset/LKET/ |
Upload File : |
// Copyright (C) 2005, 2006 IBM Corp.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.
%{
#include <linux/cpufreq.h>
#if defined(ASCII_TRACE)
#ifndef _FMT_
#define _FMT_ unsigned int
#endif
#else
#ifndef _FMT_
#define _FMT_ int64_t
#endif
#endif
#ifndef TIMING_GETCYCLES
#define TIMING_GETCYCLES 0x01
#endif
#ifndef TIMING_GETTIMEOFDAY
#define TIMING_GETTIMEOFDAY 0x02
#endif
#ifndef TIMING_SCHEDCLOCK
#define TIMING_SCHEDCLOCK 0x03
#endif
extern int _GROUP_CPUFREQ;
extern int _HOOKID_SWITCH_CPUFREQ;
extern long timing_method;
#ifndef _PFN_SCHEDCLOCK_TYPE
#define _PFN_SCHEDCLOCK_TYPE
typedef unsigned long long (* pfn_schedclock_type)(void);
#endif
extern pfn_schedclock_type pfn_schedclock;
%}
function lket_trace_header_init()
%{
/* header info for binary format*/
#if !defined(ASCII_TRACE)
#define MAGIC_NUMBER 0xAEFCDB6B
#define LKET_TRACE_VER_MAJOR 0x01
#define LKET_TRACE_VER_MINOR 0x01 /* used for user customization */
#define LITTLE_ENDIAN 0x01
#define BIG_ENDIAN 0x02
#define BITS_WIDTH 64 /* 32-bit or 64-bit environment*/
_stp_printf("%4b%2n%1b%1b%1b%1b%1b%4b", (_FMT_)MAGIC_NUMBER,
(_FMT_)LKET_TRACE_VER_MAJOR, (_FMT_)LKET_TRACE_VER_MINOR,
(_FMT_)BIG_ENDIAN, (_FMT_)timing_method,
(_FMT_)BITS_WIDTH, (_FMT_)__stp_estimate_cpufreq());
_stp_print_flush();
#endif
%}
function lket_trace_init()
{
lket_trace_header_init()
}
%{
#ifndef __LKET_TRACE__
#define __LKET_TRACE__
#define LKET_PKT_BT 2
#define MAX_FMT_LEN 128
char new_sysfmt[MAX_FMT_LEN] = "\n%d|%d|%d|%d|%d|%d|%d|%d";
#define NEW_SYSFMT_START 24
void fmt_change(char *oldfmt, char *newfmt, int newfmt_start)
{
char *old_ptr, *new_ptr;
old_ptr = oldfmt;
new_ptr = newfmt + newfmt_start;
while(*old_ptr != 0 && (new_ptr - newfmt) < MAX_FMT_LEN) {
if(*old_ptr != '%') {
*new_ptr++ = *old_ptr++;
continue;
} else {
*new_ptr++ = '|'; /* delimier to make it readable */
*new_ptr++ = *old_ptr++;
while( *old_ptr == 'L' || *old_ptr == 'l'
|| isdigit(*old_ptr) ) {
*new_ptr++ = *old_ptr++;
}
if( *old_ptr == 'b') {
if(isdigit(*(old_ptr-1))) {
if(*(old_ptr-1) == '1' ||
*(old_ptr-1) == '2' ||
*(old_ptr-1) == '3' ||
*(old_ptr-1) == '4') {
new_ptr--;
} else if(*(old_ptr-1) == '8') {
*--new_ptr='l';
*++new_ptr='l';
new_ptr++;
}
}
*new_ptr++ = 'd';
old_ptr++;
}
else if ( *old_ptr == 's') {
if(isdigit(*(old_ptr-1)) && *(old_ptr-1)=='0')
new_ptr--;
*new_ptr++ = 's';
old_ptr++;
} else
*new_ptr++ = *old_ptr++;
}
}
*new_ptr=0;
}
/* trace data in ASCII format
Format of the common prefix of the trace data:
groupid|subhookid|sec|usec|tgid|ppid|pid|cpuid|
*/
#if defined(ASCII_TRACE)
#define _lket_trace(GroupID, hookID, fmt, args...) do { \
struct timeval tv; \
do_gettimeofday (&tv); \
fmt_change(fmt, new_sysfmt, NEW_SYSFMT_START); \
_stp_printf(new_sysfmt, \
(_FMT_)GroupID, (_FMT_)hookID, (_FMT_)tv.tv_sec, (_FMT_)tv.tv_usec,\
(_FMT_)current->tgid, (_FMT_)current->parent->tgid,\
(_FMT_)current->pid, (_FMT_)current->thread_info->cpu, args);\
} while(0)
#else //binary trace
static inline int this_event_len(void)
{
return 0;
}
/* we use 2 bytes to store the length. */
#define _lket_trace(GroupID, hookID, fmt, args...) do { \
if(timing_method == TIMING_GETCYCLES) { \
_stp_printf("%2b%2n%8b%8b"fmt, (_FMT_)0, \
(_FMT_)get_cycles(), \
(_FMT_)((int64_t)current->pid << 32 | \
(int32_t)GroupID << 24 | (int32_t)hookID << 16 | \
(int16_t)current->thread_info->cpu << 8), \
args); \
} \
else if(timing_method == TIMING_GETTIMEOFDAY) { \
struct timeval tv; \
do_gettimeofday (&tv); \
_stp_printf("%2b%2n%8b%8b"fmt, (_FMT_)0, \
(_FMT_)(tv.tv_sec*1000000LL + tv.tv_usec), \
(_FMT_)((int64_t)current->pid << 32 | \
(int32_t)GroupID << 24 | (int32_t)hookID << 16 | \
(int16_t)current->thread_info->cpu << 8), \
args); \
} \
else { \
_stp_printf("%2b%2n%8b%8b"fmt, (_FMT_)0, \
(_FMT_)pfn_schedclock(), \
(_FMT_)((int64_t)current->pid << 32 | \
(int32_t)GroupID << 24 | (int32_t)hookID << 16 | \
(int16_t)current->thread_info->cpu << 8), \
args); \
} \
} while(0)
#endif
#endif
%}
function update_record()
%{
#if !defined(ASCII_TRACE)
_stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id());
char *total_length = &(pb->buf[0]);
*(int16_t *)total_length = pb->len - 4;
#endif
%}
%{
#ifdef CONFIG_CPU_FREQ
static int __lket_time_cpufreq_callback(struct notifier_block *self,
unsigned long state, void *vfreqs)
{
int cpu;
unsigned long flags;
struct cpufreq_freqs *freqs;
unsigned int freq_mhz;
stp_time_t *time;
switch (state) {
case CPUFREQ_POSTCHANGE:
case CPUFREQ_RESUMECHANGE:
_lket_trace(_GROUP_CPUFREQ, _HOOKID_SWITCH_CPUFREQ,
"%8b", __stp_estimate_cpufreq());
break;
}
return NOTIFY_OK;
}
#endif
%}