MINI SHELL

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/runtime/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //usr/share/systemtap/runtime/stat-common.c
/* -*- linux-c -*- 
 * common stats functions for aggragations and maps
 * Copyright (C) 2005, 2006 Red Hat Inc.
 *
 * 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.
 */

#ifndef _STAT_COMMON_C_
#define _STAT_COMMON_C_
#include "stat.h"

static int needed_space(int64_t v)
{
	int space = 0;

	if (v == 0)
		return 1;

	if (v < 0) {
		space++;
		v = -v;
	}
	while (v) {
		/* v /= 10; */
		do_div (v, 10);
		space++;
	}
	return space;
}

static void reprint (int num, char *s)
{
	while (num > 0) {
		_stp_print_cstr (s);
		num--;
	}
}

/* implements a log base 2 function, or Most Significant Bit */
/* with bits from 1 (lsb) to 64 (msb) */
/* msb64(0) = 0 */
/* msb64(1) = 1 */
/* msb64(8) = 4 */
/* msb64(512) = 10 */

static int msb64(int64_t val)
{
  int res = 64;

  if (val == 0)
    return 0;

  /* shortcut. most values will be 16-bit */
  if (val & 0xffffffffffff0000ull) {
    if (!(val & 0xffffffff00000000ull)) {
      val <<= 32;
      res -= 32;
    }

    if (!(val & 0xffff000000000000ull)) {
      val <<= 16;
      res -= 16;
    }
  } else {
      val <<= 48;
      res -= 48;
  }

  if (!(val & 0xff00000000000000ull)) {
    val <<= 8;
    res -= 8;
  }

  if (!(val & 0xf000000000000000ull)) {
    val <<= 4;
    res -= 4;
  }

  if (!(val & 0xc000000000000000ull)) {
    val <<= 2;
    res -= 2;
  }

  if (!(val & 0x8000000000000000ull)) {
    val <<= 1;
    res -= 1;
  }

  return res;
}

#ifndef HIST_WIDTH
#define HIST_WIDTH 50
#endif

static void _stp_stat_print_histogram (Hist st, stat *sd)
{
	int scale, i, j, val_space, cnt_space, 
		low_bucket = -1, high_bucket = 0;
	int64_t val, v, max = 0;

	if (st->type != HIST_LOG && st->type != HIST_LINEAR)
		return;

	/* Get the maximum value, for scaling. Also calculate the low
	   and high values to bound the reporting range. */
	for (i = 0; i < st->buckets; i++) {
		if (sd->histogram[i] > 0 && low_bucket == -1)
			low_bucket = i;
		if (sd->histogram[i] > 0)
			high_bucket = i;
		if (sd->histogram[i] > max)
			max = sd->histogram[i];
	}

	/* Touch up the bucket margin to show up to two zero-slots on
	   either side of the data range, seems aesthetically pleasant. */
	for (i = 0; i < 2; i++) {
		if (low_bucket > 0)
			low_bucket--;
		
		if (high_bucket < (st->buckets-1))
			high_bucket++;
	}

	if (max <= HIST_WIDTH)
		scale = 1;
	else {
		int64_t tmp = max;
		int rem = do_div (tmp, HIST_WIDTH);
		scale = tmp;
		if (rem) scale++;
	}

	cnt_space = needed_space (max);
	if (st->type == HIST_LINEAR)
		val_space = needed_space (st->start +  st->interval * high_bucket);
	else
		val_space = needed_space (((int64_t)1) << high_bucket);
	//dbug ("max=%lld scale=%d val_space=%d\n", max, scale, val_space);

	/* print header */
	j = 0;
	if (val_space > 5)		/* 5 = sizeof("value") */
		j = val_space - 5;
	else
		val_space = 5;
	for ( i = 0; i < j; i++)
		_stp_print_cstr (" ");
	_stp_print_cstr("value |");
	reprint (HIST_WIDTH, "-");
	_stp_print_cstr (" count\n");
	if (st->type == HIST_LINEAR)
		val = st->start;
	else
		val = 0;
	for (i = 0; i < st->buckets; i++) {
		if (i >= low_bucket && i <= high_bucket) {
			reprint (val_space - needed_space(val), " ");
			_stp_printf("%lld", val);
			_stp_print_cstr (" |");
			
			/* v = s->histogram[i] / scale; */
			v = sd->histogram[i];
			do_div (v, scale);
		
			reprint (v, "@");
			reprint (HIST_WIDTH - v + 1 + cnt_space - needed_space(sd->histogram[i]), " ");
			_stp_printf ("%lld\n", sd->histogram[i]);
		}
		if (st->type == HIST_LINEAR) 
			val += st->interval;
		else if (val == 0)
			val = 1;
		else
			val *= 2;
	}
	_stp_print_cstr ("\n");
	_stp_print_flush();
}

static void _stp_stat_print_valtype (char *fmt, Hist st, stat *sd, int cpu)
{
	switch (*fmt) {
	case 'C':
		_stp_printf("%lld", sd->count);
		break;
	case 'm':
		_stp_printf("%lld", sd->min);
		break;
	case 'M':
		_stp_printf("%lld", sd->max);
		break;
	case 'S':
		_stp_printf("%lld", sd->sum);
		break;
	case 'A':
	{
		int64_t avg = 0;
		if (sd->count)
			avg = _stp_div64 (NULL, sd->sum, sd->count);
		_stp_printf("%lld", avg);
		break;
	}
	case 'H':
		_stp_stat_print_histogram (st, sd);
		_stp_print_flush();
		break;
	case 'c':
		_stp_printf("%d", cpu);
		break;
	}
}

static void __stp_stat_add (Hist st, stat *sd, int64_t val)
{
	int n;
	if (sd->count == 0) {
		sd->count = 1;
		sd->sum = sd->min = sd->max = val;
	} else {
		sd->count++;
		sd->sum += val;
		if (val > sd->max)
			sd->max = val;
		if (val < sd->min)
			sd->min = val;
	}
	switch (st->type) {
	case HIST_LOG:
		n = msb64 (val);
		if (n >= st->buckets)
			n = st->buckets - 1;
		sd->histogram[n]++;
		break;
	case HIST_LINEAR:
		if (val < st->start)
			val = st->start;
		else
			val -= st->start;
		do_div (val, st->interval);
		if (val >= st->buckets)
			val = st->buckets - 1;
		sd->histogram[val]++;
	default:
		break;
	}
}

#endif /* _STAT_COMMON_C_ */

Anon7 - 2021