Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

VrCycleCount.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- */
00002 /*
00003  * Copyright 2001 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 /*
00023  *  Copyright 1997 Massachusetts Institute of Technology
00024  * 
00025  *  Permission to use, copy, modify, distribute, and sell this software and its
00026  *  documentation for any purpose is hereby granted without fee, provided that
00027  *  the above copyright notice appear in all copies and that both that
00028  *  copyright notice and this permission notice appear in supporting
00029  *  documentation, and that the name of M.I.T. not be used in advertising or
00030  *  publicity pertaining to distribution of the software without specific,
00031  *  written prior permission.  M.I.T. makes no representations about the
00032  *  suitability of this software for any purpose.  It is provided "as is"
00033  *  without express or implied warranty.
00034  * 
00035  */
00036 
00037 #ifndef _VRCYCLECOUNT_H_
00038 #define _VRCYCLECOUNT_H_
00039 
00040 extern "C" {
00041 #include <stdio.h>
00042 #ifdef THREADS
00043 #include<pthread.h>
00044 #endif
00045 }
00046 
00047 //brettv 6/24/99 I junked the old user-level perfmon stuff.
00048 //PERMON now requires the kernel driver to operation
00049 
00050 #ifdef PERFMON
00051 #if defined (__i386__)
00052 #include <libperfctr.h>
00053 #define PERF1_CODE p6_events[P6_DCU_MISS_OUTSTANDING]
00054 //#define PERF0_NAME "DCU miss cycles"
00055 #define PERF2_CODE p6_events[P6_RESOURCE_STALLS]
00056 //#define PERF1_NAME "Resource stalls"
00057 
00058 #define PERF1_NAME PERF1_CODE.desc
00059 #define PERF2_NAME PERF2_CODE.desc
00060 
00061 #define START_COUNTS() start_counters(PERF1_CODE.id,PERF2_CODE.id)
00062 #define STOP_COUNTS() perfctr_disable()
00063 #else
00064 //not supported
00065 #error PERMON only supported on x86
00066 /*alpha  #define CYCLE_COUNT() ({ volatile unsigned long time; \
00067              __asm__("rpcc %0" :"=r" (time)); \
00068              (unsigned long)((time >> 32) + (time & 0x00000000ffffffff)); })*/
00069 #endif //x86
00070 
00071 //Global counts:
00072 //-------------
00073 
00074 //Per module counts:
00075 //-----------------
00076 typedef struct {
00077   unsigned long long counter[3];
00078 } pmcs;
00079 
00080 class VrCycleCount {
00081 private:
00082   long totalSamples;
00083   pmcs total;
00084 
00085 #ifdef THREADS
00086   pthread_key_t mystart; 
00087   pthread_mutex_t mutex;
00088 #else
00089   pmcs start;
00090 #endif  
00091   //*** the rest of this stuff is Pspectra internal performance stuff
00092 public:
00093   //By occurrence:
00094   //--------------
00095   //no one computed the data ahead of mine, and I can skip it
00096   unsigned long long skippedData; //number of units skipped
00097 
00098   //couldn't mark data because there wasn't enough room in the downstream
00099   //buffer
00100   unsigned long long bufferFullOnWrite; //# of occurrences
00101 
00102   //data is computed (ready) but other threads won't know
00103   //  because we're using an oversimplified linked list.
00104   //(i.e. out of order completion of writing threads.)
00105   //if both this and blockOnMarkedData are high
00106   //more work should be done here to fix our writeLL data
00107   //structure
00108   unsigned long long WPdelayedUpdate; //#occurrences
00109 
00110   //no one has marked the data ahead of mine yet so I have to wait!
00111   //(i.e. I couldnt' skip data)
00112   unsigned long long blockOnUnmarkedData; //#occurrences
00113 
00114   //# of times work() didn't finish all its work
00115   unsigned long long uncompleteWork; //#occurrences
00116 
00117   //By duration:
00118   //--------------
00119   //cycles are kind of bogus right now -- should use perfctr stuff
00120   //FIX
00121 
00122   //the previous thread didn't finish data I need!
00123   unsigned long long blockOnMarkedData; //#cycles spent waiting
00124 
00125   //blocked in sync() 
00126   unsigned long long blockOnSync; //#cycles spent waiting
00127 
00128 public:
00129   /*** Performance monitoring procedures ***/
00130   void startCount() {
00131 
00132 #ifdef THREADS
00133     pmcs *p=(pmcs *) pthread_getspecific(mystart);
00134     if(p == 0) {
00135       //init thread specific data
00136       p=new pmcs;
00137       pthread_setspecific(mystart,(void *) p);
00138 
00139       if (0){   // FIXME -eb
00140         pthread_mutex_lock(&mutex);
00141         if(START_COUNTS()<0) {
00142           perror("VrCycleCount: could not start counts");
00143           fprintf(stderr,"Must be running on a system with the /dev/perfctr driver installed.\n");
00144           exit(-1);
00145         }
00146         pthread_mutex_unlock(&mutex);
00147       }
00148 
00149     } 
00150     else if (PARANOID && p->counter[0]!=0) {
00151       fprintf(stderr, "VrCycleCount(%p): counter already started! \n", this);
00152       abort ();
00153     }
00154 
00155 #else
00156 
00157     pmcs *p = &start;
00158     if(PARANOID && start.counter[0]) {
00159       fprintf(stderr, "VrCycleCount(%p): counter already started! \n", this);
00160       abort ();
00161     }
00162 
00163 #endif
00164 
00165     struct perfctr_state state;
00166     if( perfctr_read(&state) < 0 ) {
00167       perror("perfctr_read");
00168       exit(1);
00169     }
00170     p->counter[0] = state.counters.tsc.u64;
00171     p->counter[1] = state.counters.pmc[0].u64;
00172     p->counter[2] = state.counters.pmc[1].u64;
00173 }
00174 
00175   void stopCount() {
00176 #ifdef THREADS
00177     pmcs *p=(pmcs *) pthread_getspecific(mystart);
00178     if(PARANOID && (p == 0 || !p->counter[0])) {
00179       fprintf(stderr, "VrCycleCount(%p): counter not running! \n", this);
00180       exit(-1);
00181     }
00182 #else
00183     pmcs *p = &start;
00184     if(PARANOID && !start.counter[0]) {
00185       fprintf(stderr, "VrCycleCount: counter not running! \n");
00186       exit(-1);
00187     }
00188 #endif
00189 
00190     struct perfctr_state state;
00191     if (perfctr_read(&state) < 0 ) {
00192       perror("perfctr_read");
00193       exit(1);
00194     }
00195 
00196     MUTEX_LOCK(&mutex);
00197 
00198     if (PARANOID){
00199       if(state.counters.tsc.u64 < p->counter[0] ||
00200          state.counters.pmc[0].u64 < p->counter[1] ||
00201          state.counters.pmc[1].u64 < p->counter[2]) {
00202         fprintf(stderr, "Counters running backwards!\n");
00203         abort ();
00204       }
00205     }
00206 
00207     total.counter[0] += (state.counters.tsc.u64 - p->counter[0]);
00208     total.counter[1] += (state.counters.pmc[0].u64 - p->counter[1]);
00209     total.counter[2] += (state.counters.pmc[1].u64 - p->counter[2]);
00210 
00211     MUTEX_UNLOCK(&mutex);
00212 
00213 #ifdef THREADS
00214     p->counter[0]=0;
00215 #else
00216     start.counter[0] = 0;
00217 #endif
00218   }
00219 
00220   void resetCount() {
00221     for(int i=0;i<3;i++) {
00222       total.counter[i]=0;
00223     }    
00224     skippedData = bufferFullOnWrite = WPdelayedUpdate =
00225       blockOnUnmarkedData = uncompleteWork =
00226       blockOnMarkedData = blockOnSync = 0;
00227   }
00228 
00229   long long getTotalCycles() {return total.counter[0];}
00230 
00231   long long getTotalCycles(int measure) {
00232     if(measure < 3)
00233       return total.counter[measure];
00234     else
00235       return 0;
00236   }
00237 
00238   static char *measurementName(int n) {
00239     switch(n) {
00240     case 0:
00241       return "cycles";
00242     case 1:
00243       return PERF1_NAME;
00244     case 2:
00245       return PERF2_NAME;
00246     default:
00247       return NULL;
00248     }
00249   }
00250 
00251   void updateSamples(int n) {totalSamples += n;}
00252   long getTotalSamples() {return totalSamples;}
00253 
00254   void print_stats();
00255   VrCycleCount();
00256 };
00257 
00258 #endif //PERFMON
00259 #endif

Generated on Wed Mar 23 12:30:25 2005 for GNU Radio by  doxygen 1.4.0