memstatdump.c 7.79 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * memstatdump.c 
 * 
 * reads the detail output files into something that is perl-able
 * 
 * Author: bugnion 
 * Date: nov. 94 -...
 * 
 * Disclaimer: this is the grossest code ever written. Although it
 * does the job, I am sometimes not quite sure how and mainly what
 * possessed it to evolve in this direction, independently of my
 * will.
 *
 *******************************************************************/



#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#ifdef __alpha
#include <string.h>
#else
#include <bstring.h>
#endif
#include <malloc.h>
#include "memstatdump.h"

struct Context{
	int fd;
	VA addr;
	int remaining;
	int eof;
};

static void GetNextBucket( struct Context *cnt,uint *bucket);
static void CalcDiff(uint *buck1,uint *buck2, uint *buck3);

  
int fd;
VA simRecHighRes;
VA simRecLowRes;
int numCPUs;

SimRecHeader msHeader;
static int GetLog2(long x);

#ifdef __alpha
int VASizeLog2 = 44;
#else
int VASizeLog2 = 32;
#endif

int MemStatFileOpen(char *filename)
{
  char *fieldNames;
  char *start,*end;
  int count=0;
  fd = open(filename,O_RDONLY,0);
  if( fd < 0 ) {
    return fd;
  }
  if( read(fd,(char *) &msHeader,sizeof(msHeader))!=(int)sizeof(msHeader)) {
    fprintf(stderr,"read failed -bailing \n");
    exit(1);
  }
  if( msHeader.magic != SIMREC_MAGIC ) {    
	fprintf(stderr,"wrong magic number!\n");
        exit(1);
  }
  if (msHeader.version< 6) {
     fprintf(stderr,"wrong version number %d. Expecting 6 or greater \n",
             msHeader.version);
     exit(1);
  }
       
  fieldNames = (char *)malloc(msHeader.fieldNamesLen);
  if (read(fd,fieldNames,msHeader.fieldNamesLen)!=msHeader.fieldNamesLen) {
     fprintf(stderr,"read failed -bailing \n");
     exit(1);
  }   

  simRecHighRes = msHeader.highRes;
  simRecLowRes = msHeader.lowRes;
  if (1) {
    fprintf(stderr,"MemStat file: ");
    fprintf(stderr,"version=%i name=%s ",
	   msHeader.version,msHeader.tableName);
    fprintf(stderr,"  highRes=0x%lx lowRes=0x%lx fieldSize=%i bucketSize=%i\n",
            msHeader.highRes,
            msHeader.lowRes,msHeader.entrySize,msHeader.bucketSize);
    
    start = fieldNames;
    while (1) {
       end = start;
       while (*end && *end != ',') {
          end++;
       }
       if (!(*end)) {
          end = 0;
       } else { 
          *end = '\0';
       }
       printf("FIELD %d %s\n",count,start);
       if (!end) { break;}
       start = end+1;
       count++;
    }
  }
  return fd;
}

void MemStatFileIterate( void (*process)(VA,void *,Resolution))
{ 
  char bucket[1024];
  VA a;
  long rd,i,numChunks;
  int startEnd[2];
  Resolution resolution;

  numChunks = 1<<(VASizeLog2 - GetLog2(msHeader.lowRes)) ;

  /* lowRes */
  resolution = Low;
  for(a=0;a<numChunks;++a) {
    if( read(fd,bucket,msHeader.bucketSize)!=msHeader.bucketSize) {
      	   fprintf(stderr,"read failed at lowRes\n");
	   exit(1);
	 }
    process(a*msHeader.lowRes,bucket,resolution);
  }
  /* out of range */
  if( read(fd,bucket,(uint)msHeader.bucketSize)!=msHeader.bucketSize) {
     fprintf(stderr,"read failed at lowRes\n");
     process(0,bucket,resolution);
     exit(1);
  }
  process(0,bucket,resolution);

  /* highRes and detailRes*/
  while(( rd = read(fd,startEnd,8))==8 ) {
    if( !startEnd[0] && !startEnd[1] )  /* end of High Res Area */
      break;
    if( startEnd[1] < 0 ) {    /* detail resolution */       
      resolution = Detail;
      startEnd[1] *= -1;
    } else
      resolution = High;
    
    for(a=0;a<(VA)startEnd[1];++a) {
      rd = read(fd,bucket,(uint)msHeader.bucketSize);
      if( rd != msHeader.bucketSize ) {
	fprintf(stderr,"read failed at %08x %i out of %i\n",startEnd[0],
		a,startEnd[1]);
      }
      for(i=0;i<msHeader.bucketSize;++i)
		if( bucket[i] )
		  break;
      if( i !=msHeader.bucketSize ) {
		if( resolution==High )
		  process((VA)startEnd[0]+a*simRecHighRes,bucket,resolution);
		else
		  process((VA)startEnd[0]+a*4,bucket,resolution);
      }  
    }
  }
  close(fd);
}


void MemStatDiff(char *file1, char *file2,char *file3)
{
  char tableName1[24];
  struct Context cnt1,cnt2;
  int out[2],i;
  long numChunks;
  uint b1[1024];
  uint b2[1024];
  uint b3[1024];
  struct SimRecHeader hdr;
  if( MemStatFileOpen(file1)<0 ) {
	fprintf(stderr,"could not open %s\n",file1);
	return;
  }
  cnt1.fd = fd;
  if( MemStatFileOpen(file2)<0) {
	fprintf(stderr,"could not open %s\n",file2);
	return;
  }
  cnt2.fd = fd;

  fd = open(file3, O_RDWR|O_CREAT|O_TRUNC, 0666);
  if (fd < 0) {
	printf("Error in MemStatDiff\n");
	return;
  }

  /* for now, assume full compatibility */

  cnt1.eof = 0;
  cnt2.eof = 0;
  cnt1.remaining = 0;
  cnt2.remaining = 0;
  hdr.magic = SIMREC_MAGIC;
  hdr.version = 2;
  strncpy(hdr.tableName, tableName1, sizeof(hdr.tableName)-1);
  hdr.addrStart = 0;
  hdr.lowRes = simRecLowRes;
  hdr.highRes = simRecHighRes;
  hdr.bucketSize = msHeader.bucketSize;
  numChunks = 1<<(VASizeLog2 - GetLog2(msHeader.lowRes)) ;

  if (write(fd, (char *) &hdr, sizeof(hdr)) != sizeof(hdr)) 
	goto err;

  /* lowRes bucket  + out of bounds bucket */

  for( i=0;i<numChunks+ 1;++i) {
	if( read(cnt1.fd,b1,msHeader.bucketSize)!=msHeader.bucketSize)
	  goto err;
	if( read(cnt2.fd,b2,msHeader.bucketSize) != msHeader.bucketSize) 
	  goto err;
	CalcDiff(b1,b2,b3);
	if( write(fd,b3,msHeader.bucketSize) != msHeader.bucketSize)
	  goto err;
  }
  GetNextBucket(&cnt1,b1);
  GetNextBucket(&cnt2,b2);
  while( !cnt2.eof ) {
	while( !cnt2.eof && (cnt1.eof || cnt1.addr > cnt2.addr) ) {
/*	  printf("writing %08x %08x\n",cnt1.addr,cnt2.addr);  */
	  out[0] = cnt2.addr;
	  out[1] = (cnt2.remaining < 0 ? -1 : 1);
	  if( write(fd,out,8) !=8)
		goto err;
	  if( write(fd,b2,msHeader.bucketSize) != msHeader.bucketSize)
		goto err;
	  GetNextBucket(&cnt2,b2);
	}
	if( (!cnt1.eof) && (!cnt2.eof) ) {
	  if( cnt1.addr != cnt2.addr )
		printf("Address mismatch\n");
	  CalcDiff(b1,b2,b3);
	  out[0] = cnt2.addr;
	  out[1] = (cnt2.remaining < 0 ? -1 : 1);
/*	  printf("writing %08x %08x\n",cnt1.addr,cnt2.addr); */
	  if( write(fd,out,8) !=8)
		goto err;
	  if( write(fd,b3,msHeader.bucketSize) != msHeader.bucketSize)
		goto err;
	  GetNextBucket(&cnt1,b1);
	  GetNextBucket(&cnt2,b2);
	}
  }
  out[0] = 0;
  out[1] = 0;
  if( write(fd,out,8)!=8)
	goto err;
  close(fd);
  close(cnt1.fd);
  close(cnt2.fd);
  return;
  
err:
  printf("Errro in MemStatDiff");
}




int
GetLineFromFile(FILE * f, char *buffer, int bufsize)
{
    int i;
    int n;
 
    for (i = 0; i < bufsize-1; i++) {
	   n = fgetc(f);
	   if (n ==EOF) {
		  return 0;
	   }
	   buffer[i] = n;
	   if (n == '\n') break;
    }
    buffer[i] = '\000';
    return i+1;
}




static void
GetNextBucket(struct Context *cnt, uint *bucket)
{
  if( cnt->eof )
	printf("EOF, %i\n",cnt->fd);
  if( cnt->remaining > 0 )
	--cnt->remaining;
  if( cnt->remaining < 0 )
	++cnt->remaining;

  if( !cnt->remaining ) {
	if( read(cnt->fd,&cnt->addr,8)!=8)
	  goto err;
	if( !cnt->addr) {
	  cnt->eof = 1;
	  return;
	}
  } else {
	if( cnt->remaining < 0 )
	  cnt->addr += 4;
	else
	  cnt->addr += simRecHighRes;
  }
/*  printf("Getting %08x for %i\n",cnt->addr,cnt->fd); */
  if( read(cnt->fd,bucket,msHeader.bucketSize)!=msHeader.bucketSize)
	goto err;
  return;
err:
  printf("Error Getnextbucket %08x %i\n",cnt->addr,cnt->fd);
  exit(1);
}
 
	 


static void CalcDiff(uint *buck1,uint *buck2, uint *buck3)
{
    fprintf(stderr,"calcdiff not implemented \n");
}

static int GetLog2(long x)
{
   long i;
   int r=0;
   for(i=1;i<x;i*=2)
      r++;
   if( i !=  x ) { 
      fprintf(stderr,"Error: GetLog2(%i) is undefined \n",x);
      exit(1);
   }
   return r;
}