PAPI  5.1.0.2
appio.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00029 #include <stdlib.h>
00030 #include <ctype.h>
00031 #include <string.h>
00032 #include <errno.h>
00033 #include <sys/select.h>
00034 #include <sys/types.h>
00035 #include <unistd.h>
00036 #include <sys/stat.h>
00037 
00038 /* Headers required by PAPI */
00039 #include "papi.h"
00040 #include "papi_internal.h"
00041 #include "papi_vector.h"
00042 #include "papi_memory.h"
00043 
00044 #include "appio.h"
00045 
00046 // The PIC test implies it's built for shared linkage
00047 #ifdef PIC
00048 #  include "dlfcn.h"
00049 #endif
00050 
00051 /*
00052 #pragma weak dlerror
00053 static void *_dlsym_fake(void *handle, const char* symbol) { (void) handle; (void) symbol; return NULL; }
00054 void *dlsym(void *handle, const char* symbol) __attribute__ ((weak, alias ("_dlsym_fake")));
00055 */
00056 
00057 papi_vector_t _appio_vector;
00058 
00059 /*********************************************************************
00060  * Private
00061  ********************************************************************/
00062 
00063 //#define APPIO_FOO 1
00064 
00065 static APPIO_native_event_entry_t * _appio_native_events;
00066 
00067 
00068 /* If you modify the appio_stats_t below, you MUST update APPIO_MAX_COUNTERS */
00069 static __thread long long _appio_register_current[APPIO_MAX_COUNTERS];
00070 typedef enum {
00071   READ_BYTES = 0,
00072   READ_CALLS,
00073   READ_ERR,
00074   READ_INTERRUPTED,
00075   READ_WOULD_BLOCK,
00076   READ_SHORT,
00077   READ_EOF,
00078   READ_BLOCK_SIZE,
00079   READ_USEC,
00080   WRITE_BYTES,
00081   WRITE_CALLS,
00082   WRITE_ERR,
00083   WRITE_SHORT,
00084   WRITE_INTERRUPTED,
00085   WRITE_WOULD_BLOCK,
00086   WRITE_BLOCK_SIZE,
00087   WRITE_USEC,
00088   OPEN_CALLS,
00089   OPEN_ERR,
00090   OPEN_FDS,
00091   SELECT_USEC,
00092   RECV_BYTES,
00093   RECV_CALLS,
00094   RECV_ERR,
00095   RECV_INTERRUPTED,
00096   RECV_WOULD_BLOCK,
00097   RECV_SHORT,
00098   RECV_EOF,
00099   RECV_BLOCK_SIZE,
00100   RECV_USEC,
00101   SOCK_READ_BYTES,
00102   SOCK_READ_CALLS,
00103   SOCK_READ_ERR,
00104   SOCK_READ_SHORT,
00105   SOCK_READ_WOULD_BLOCK,
00106   SOCK_READ_USEC,
00107   SOCK_WRITE_BYTES,
00108   SOCK_WRITE_CALLS,
00109   SOCK_WRITE_ERR,
00110   SOCK_WRITE_SHORT,
00111   SOCK_WRITE_WOULD_BLOCK,
00112   SOCK_WRITE_USEC,
00113   SEEK_CALLS,
00114   SEEK_ABS_STRIDE_SIZE,
00115   SEEK_USEC
00116 } _appio_stats_t ;
00117 
00118 static const struct appio_counters {
00119     const char *name;
00120     const char *description;
00121 } _appio_counter_info[APPIO_MAX_COUNTERS] = {
00122     { "READ_BYTES",      "Bytes read"},
00123     { "READ_CALLS",      "Number of read calls"},
00124     { "READ_ERR",        "Number of read calls that resulted in an error"},
00125     { "READ_INTERRUPTED","Number of read calls that timed out or were interruped"},
00126     { "READ_WOULD_BLOCK","Number of read calls that would have blocked"},
00127     { "READ_SHORT",      "Number of read calls that returned less bytes than requested"},
00128     { "READ_EOF",        "Number of read calls that returned an EOF"},
00129     { "READ_BLOCK_SIZE", "Average block size of reads"},
00130     { "READ_USEC",       "Real microseconds spent in reads"},
00131     { "WRITE_BYTES",     "Bytes written"},
00132     { "WRITE_CALLS",     "Number of write calls"},
00133     { "WRITE_ERR",       "Number of write calls that resulted in an error"},
00134     { "WRITE_SHORT",     "Number of write calls that wrote less bytes than requested"},
00135     { "WRITE_INTERRUPTED","Number of write calls that timed out or were interrupted"},
00136     { "WRITE_WOULD_BLOCK","Number of write calls that would have blocked"},
00137     { "WRITE_BLOCK_SIZE","Mean block size of writes"},
00138     { "WRITE_USEC",      "Real microseconds spent in writes"},
00139     { "OPEN_CALLS",      "Number of open calls"},
00140     { "OPEN_ERR",        "Number of open calls that resulted in an error"},
00141     { "OPEN_FDS",        "Number of currently open descriptors"},
00142     { "SELECT_USEC",     "Real microseconds spent in select calls"},
00143     { "RECV_BYTES",      "Bytes read in recv/recvmsg/recvfrom"},
00144     { "RECV_CALLS",      "Number of recv/recvmsg/recvfrom calls"},
00145     { "RECV_ERR",        "Number of recv/recvmsg/recvfrom calls that resulted in an error"},
00146     { "RECV_INTERRUPTED","Number of recv/recvmsg/recvfrom calls that timed out or were interruped"},
00147     { "RECV_WOULD_BLOCK","Number of recv/recvmsg/recvfrom calls that would have blocked"},
00148     { "RECV_SHORT",      "Number of recv/recvmsg/recvfrom calls that returned less bytes than requested"},
00149     { "RECV_EOF",        "Number of recv/recvmsg/recvfrom calls that returned an EOF"},
00150     { "RECV_BLOCK_SIZE", "Average block size of recv/recvmsg/recvfrom"},
00151     { "RECV_USEC",       "Real microseconds spent in recv/recvmsg/recvfrom"},
00152     { "SOCK_READ_BYTES", "Bytes read from socket"},
00153     { "SOCK_READ_CALLS", "Number of read calls on socket"},
00154     { "SOCK_READ_ERR",   "Number of read calls on socket that resulted in an error"},
00155     { "SOCK_READ_SHORT", "Number of read calls on socket that returned less bytes than requested"},
00156     { "SOCK_READ_WOULD_BLOCK", "Number of read calls on socket that would have blocked"},
00157     { "SOCK_READ_USEC",  "Real microseconds spent in read(s) on socket(s)"},
00158     { "SOCK_WRITE_BYTES","Bytes written to socket"},
00159     { "SOCK_WRITE_CALLS","Number of write calls to socket"},
00160     { "SOCK_WRITE_ERR",  "Number of write calls to socket that resulted in an error"},
00161     { "SOCK_WRITE_SHORT","Number of write calls to socket that wrote less bytes than requested"},
00162     { "SOCK_WRITE_WOULD_BLOCK","Number of write calls to socket that would have blocked"},
00163     { "SOCK_WRITE_USEC", "Real microseconds spent in write(s) to socket(s)"},
00164     { "SEEK_CALLS",      "Number of seek calls"},
00165     { "SEEK_ABS_STRIDE_SIZE", "Average absolute stride size of seeks"},
00166     { "SEEK_USEC",       "Real microseconds spent in seek calls"}
00167 };
00168 
00169 
00170 /*********************************************************************
00171  ***  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT ****
00172  ********************************************************************/
00173 
00174 int __close(int fd);
00175 int close(int fd) {
00176   int retval;
00177   SUBDBG("appio: intercepted close(%d)\n", fd);
00178   retval = __close(fd);
00179   if ((retval == 0) && (_appio_register_current[OPEN_FDS]>0)) _appio_register_current[OPEN_FDS]--;
00180   return retval;
00181 }
00182 
00183 int __open(const char *pathname, int flags, mode_t mode);
00184 int open(const char *pathname, int flags, mode_t mode) {
00185   int retval;
00186   SUBDBG("appio: intercepted open(%s,%d,%d)\n", pathname, flags, mode);
00187   retval = __open(pathname,flags,mode);
00188   _appio_register_current[OPEN_CALLS]++;
00189   if (retval < 0) _appio_register_current[OPEN_ERR]++;
00190   else _appio_register_current[OPEN_FDS]++;
00191   return retval;
00192 }
00193 
00194 /* we use timeval as a zero value timeout to select in read/write
00195    for polling if the operation would block */
00196 struct timeval zerotv; /* this has to be zero, so define it here */
00197 
00198 int __select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
00199 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
00200   int retval;
00201   SUBDBG("appio: intercepted select(%d,%p,%p,%p,%p)\n", nfds,readfds,writefds,exceptfds,timeout);
00202   long long start_ts = PAPI_get_real_usec();
00203   retval = __select(nfds,readfds,writefds,exceptfds,timeout);
00204   long long duration = PAPI_get_real_usec() - start_ts;
00205   _appio_register_current[SELECT_USEC] += duration;
00206   return retval;
00207 }
00208 
00209 off_t __lseek(int fd, off_t offset, int whence);
00210 off_t lseek(int fd, off_t offset, int whence) {
00211   off_t retval;
00212   SUBDBG("appio: intercepted lseek(%d,%ld,%d)\n", fd, offset, whence);
00213   long long start_ts = PAPI_get_real_usec();
00214   retval = __lseek(fd, offset, whence);
00215   long long duration = PAPI_get_real_usec() - start_ts;
00216   int n = _appio_register_current[SEEK_CALLS]++;
00217   _appio_register_current[SEEK_USEC] += duration;
00218   if (offset < 0) offset = -offset; // get abs offset
00219   _appio_register_current[SEEK_ABS_STRIDE_SIZE]= (n * _appio_register_current[SEEK_ABS_STRIDE_SIZE] + offset)/(n+1); // mean absolute stride size
00220   return retval;
00221 }
00222 
00223 extern int errno;
00224 ssize_t __read(int fd, void *buf, size_t count);
00225 ssize_t read(int fd, void *buf, size_t count) {
00226   int retval;
00227   SUBDBG("appio: intercepted read(%d,%p,%lu)\n", fd, buf, (unsigned long)count);
00228 
00229   struct stat st;
00230   int issocket = 0;
00231   if (fstat(fd, &st) == 0) {
00232     if ((st.st_mode & S_IFMT) == S_IFSOCK) issocket = 1;
00233   }
00234   // check if read would block on descriptor
00235   fd_set readfds;
00236   FD_ZERO(&readfds);
00237   FD_SET(fd, &readfds);
00238   int ready = __select(fd+1, &readfds, NULL, NULL, &zerotv);
00239   if (ready == 0) {
00240      _appio_register_current[READ_WOULD_BLOCK]++; 
00241      if (issocket) _appio_register_current[SOCK_READ_WOULD_BLOCK]++; 
00242   }
00243 
00244   long long start_ts = PAPI_get_real_usec();
00245   retval = __read(fd,buf, count);
00246   long long duration = PAPI_get_real_usec() - start_ts;
00247   int n = _appio_register_current[READ_CALLS]++; // read calls
00248   if (issocket) _appio_register_current[SOCK_READ_CALLS]++; // read calls
00249   if (retval > 0) {
00250     _appio_register_current[READ_BLOCK_SIZE]= (n * _appio_register_current[READ_BLOCK_SIZE] + count)/(n+1); // mean size
00251     _appio_register_current[READ_BYTES] += retval; // read bytes
00252     if (issocket) _appio_register_current[SOCK_READ_BYTES] += retval;
00253     if (retval < (int)count) {
00254        _appio_register_current[READ_SHORT]++; // read short
00255        if (issocket) _appio_register_current[SOCK_READ_SHORT]++; // read short
00256     }
00257     _appio_register_current[READ_USEC] += duration;
00258     if (issocket) _appio_register_current[SOCK_READ_USEC] += duration;
00259   }
00260   if (retval < 0) { 
00261     _appio_register_current[READ_ERR]++; // read err
00262     if (issocket) _appio_register_current[SOCK_READ_ERR]++; // read err
00263     if (EINTR == errno)
00264       _appio_register_current[READ_INTERRUPTED]++; // signal interrupted the read
00265     //if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
00266     //  _appio_register_current[READ_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
00267     //  if (issocket) _appio_register_current[SOCK_READ_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
00268     //}
00269   }
00270   if (retval == 0) _appio_register_current[READ_EOF]++; // read eof
00271   return retval;
00272 }
00273 
00274 size_t _IO_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
00275 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
00276   size_t retval;
00277   SUBDBG("appio: intercepted fread(%p,%lu,%lu,%p)\n", ptr, (unsigned long) size, (unsigned long) nmemb, (void*) stream);
00278   long long start_ts = PAPI_get_real_usec();
00279   retval = _IO_fread(ptr,size,nmemb,stream);
00280   long long duration = PAPI_get_real_usec() - start_ts;
00281   int n = _appio_register_current[READ_CALLS]++; // read calls
00282   if (retval > 0) {
00283     _appio_register_current[READ_BLOCK_SIZE]= (n * _appio_register_current[READ_BLOCK_SIZE]+ size*nmemb)/(n+1);//mean size
00284     _appio_register_current[READ_BYTES]+= retval * size; // read bytes
00285     if (retval < nmemb) _appio_register_current[READ_SHORT]++; // read short
00286     _appio_register_current[READ_USEC] += duration;
00287   }
00288 
00289   /* A value of zero returned means one of two things..*/
00290   if (retval == 0) {
00291      if (feof(stream)) _appio_register_current[READ_EOF]++; // read eof
00292      else _appio_register_current[READ_ERR]++; // read err
00293   }
00294   return retval;
00295 }
00296 
00297 ssize_t __write(int fd, const void *buf, size_t count);
00298 ssize_t write(int fd, const void *buf, size_t count) {
00299   int retval;
00300   SUBDBG("appio: intercepted write(%d,%p,%lu)\n", fd, buf, (unsigned long)count);
00301   struct stat st;
00302   int issocket = 0;
00303   if (fstat(fd, &st) == 0) {
00304     if ((st.st_mode & S_IFMT) == S_IFSOCK) issocket = 1;
00305   }
00306 
00307   // check if write would block on descriptor
00308   fd_set writefds;
00309   FD_ZERO(&writefds);
00310   FD_SET(fd, &writefds);
00311   int ready = __select(fd+1, NULL, &writefds, NULL, &zerotv);
00312   if (ready == 0) {
00313     _appio_register_current[WRITE_WOULD_BLOCK]++; 
00314     if (issocket) _appio_register_current[SOCK_WRITE_WOULD_BLOCK]++; 
00315   }
00316 
00317   long long start_ts = PAPI_get_real_usec();
00318   retval = __write(fd,buf, count);
00319   long long duration = PAPI_get_real_usec() - start_ts;
00320   int n = _appio_register_current[WRITE_CALLS]++; // write calls
00321   if (issocket) _appio_register_current[SOCK_WRITE_CALLS]++; // socket write
00322   if (retval >= 0) {
00323     _appio_register_current[WRITE_BLOCK_SIZE]= (n * _appio_register_current[WRITE_BLOCK_SIZE] + count)/(n+1); // mean size
00324     _appio_register_current[WRITE_BYTES]+= retval; // write bytes
00325     if (issocket) _appio_register_current[SOCK_WRITE_BYTES] += retval;
00326     if (retval < (int)count) {
00327       _appio_register_current[WRITE_SHORT]++; // short write
00328       if (issocket) _appio_register_current[SOCK_WRITE_SHORT]++; 
00329     }
00330     _appio_register_current[WRITE_USEC] += duration;
00331     if (issocket) _appio_register_current[SOCK_WRITE_USEC] += duration;
00332   }
00333   if (retval < 0) {
00334     _appio_register_current[WRITE_ERR]++; // err
00335     if (issocket) _appio_register_current[SOCK_WRITE_ERR]++;
00336     if (EINTR == errno)
00337       _appio_register_current[WRITE_INTERRUPTED]++; // signal interrupted the op
00338     //if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
00339     //  _appio_register_current[WRITE_WOULD_BLOCK]++; //op would block on descriptor marked as non-blocking
00340     //  if (issocket) _appio_register_current[SOCK_WRITE_WOULD_BLOCK]++;
00341     //}
00342   }
00343   return retval;
00344 }
00345 
00346 // The PIC test implies it's built for shared linkage
00347 #ifdef PIC
00348 static ssize_t (*__recv)(int sockfd, void *buf, size_t len, int flags) = NULL;
00349 ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
00350   int retval;
00351   SUBDBG("appio: intercepted recv(%d,%p,%lu,%d)\n", sockfd, buf, (unsigned long)len, flags);
00352   if (!__recv) __recv  = dlsym(RTLD_NEXT, "recv");
00353   if (!__recv) {
00354     fprintf(stderr, "appio,c Internal Error: Could not obtain handle for real recv\n");
00355     exit(1);
00356   }
00357   // check if recv would block on descriptor
00358   fd_set readfds;
00359   FD_ZERO(&readfds);
00360   FD_SET(sockfd, &readfds);
00361   int ready = __select(sockfd+1, &readfds, NULL, NULL, &zerotv);
00362   if (ready == 0) _appio_register_current[RECV_WOULD_BLOCK]++; 
00363 
00364   long long start_ts = PAPI_get_real_usec();
00365   retval = __recv(sockfd, buf, len, flags);
00366   long long duration = PAPI_get_real_usec() - start_ts;
00367   int n = _appio_register_current[RECV_CALLS]++; // read calls
00368   if (retval > 0) {
00369     _appio_register_current[RECV_BLOCK_SIZE]= (n * _appio_register_current[RECV_BLOCK_SIZE] + len)/(n+1); // mean size
00370     _appio_register_current[RECV_BYTES] += retval; // read bytes
00371     if (retval < (int)len) _appio_register_current[RECV_SHORT]++; // read short
00372     _appio_register_current[RECV_USEC] += duration;
00373   }
00374   if (retval < 0) { 
00375     _appio_register_current[RECV_ERR]++; // read err
00376     if (EINTR == errno)
00377       _appio_register_current[RECV_INTERRUPTED]++; // signal interrupted the read
00378     if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) 
00379       _appio_register_current[RECV_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
00380   }
00381   if (retval == 0) _appio_register_current[RECV_EOF]++; // read eof
00382   return retval;
00383 }
00384 #endif /* PIC */
00385 
00386 size_t _IO_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
00387 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
00388   size_t retval;
00389   SUBDBG("appio: intercepted fwrite(%p,%lu,%lu,%p)\n", ptr, (unsigned long) size, (unsigned long) nmemb, (void*) stream);
00390   long long start_ts = PAPI_get_real_usec();
00391   retval = _IO_fwrite(ptr,size,nmemb,stream);
00392   long long duration = PAPI_get_real_usec() - start_ts;
00393   int n = _appio_register_current[WRITE_CALLS]++; // write calls
00394   if (retval > 0) {
00395     _appio_register_current[WRITE_BLOCK_SIZE]= (n * _appio_register_current[WRITE_BLOCK_SIZE] + size*nmemb)/(n+1); // mean block size
00396     _appio_register_current[WRITE_BYTES]+= retval * size; // write bytes
00397     if (retval < nmemb) _appio_register_current[WRITE_SHORT]++; // short write
00398     _appio_register_current[WRITE_USEC] += duration;
00399   }
00400   if (retval == 0) _appio_register_current[WRITE_ERR]++; // err
00401   return retval;
00402 }
00403 
00404 
00405 /*********************************************************************
00406  ***************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *********
00407  *********************************************************************/
00408 
00409 /*
00410  * This is called whenever a thread is initialized
00411  */
00412 int
00413 _appio_init_thread( hwd_context_t *ctx )
00414 {
00415     ( void ) ctx;
00416     SUBDBG("_appio_init_thread %p\n", ctx);
00417     return PAPI_OK;
00418 }
00419 
00420 
00421 /* Initialize hardware counters, setup the function vector table
00422  * and get hardware information, this routine is called when the 
00423  * PAPI process is initialized (IE PAPI_library_init)
00424  */
00425 int
00426 _appio_init_component( int cidx  )
00427 {
00428 
00429     SUBDBG("_appio_component %d\n", cidx);
00430     _appio_native_events = (APPIO_native_event_entry_t *) papi_calloc(sizeof(APPIO_native_event_entry_t), APPIO_MAX_COUNTERS);
00431 
00432     if (_appio_native_events == NULL ) {
00433       PAPIERROR( "malloc():Could not get memory for events table" );
00434       return PAPI_ENOMEM;
00435     }
00436     int i;
00437     for (i=0; i<APPIO_MAX_COUNTERS; i++) {
00438       _appio_native_events[i].name = _appio_counter_info[i].name;
00439       _appio_native_events[i].description = _appio_counter_info[i].description;
00440       _appio_native_events[i].resources.selector = i + 1;
00441     }
00442   
00443     /* Export the total number of events available */
00444     _appio_vector.cmp_info.num_native_events = APPIO_MAX_COUNTERS;;
00445 
00446     /* Export the component id */
00447     _appio_vector.cmp_info.CmpIdx = cidx;
00448 
00449     return PAPI_OK;
00450 }
00451 
00452 
00453 /*
00454  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00455  * functions
00456  */
00457 int
00458 _appio_init_control_state( hwd_control_state_t *ctl )
00459 {
00460     ( void ) ctl;
00461 
00462     return PAPI_OK;
00463 }
00464 
00465 
00466 int
00467 _appio_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
00468 {
00469     ( void ) ctx;
00470 
00471     SUBDBG("_appio_start %p %p\n", ctx, ctl);
00472     APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
00473 
00474     /* this memset needs to move to thread_init */
00475     memset(_appio_register_current, 0, APPIO_MAX_COUNTERS * sizeof(_appio_register_current[0]));
00476 
00477     /* set initial values to 0 */
00478     memset(appio_ctl->values, 0, APPIO_MAX_COUNTERS*sizeof(appio_ctl->values[0]));
00479     
00480     return PAPI_OK;
00481 }
00482 
00483 
00484 int
00485 _appio_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00486     long long ** events, int flags )
00487 {
00488     (void) flags;
00489     (void) ctx;
00490 
00491     SUBDBG("_appio_read %p %p\n", ctx, ctl);
00492     APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
00493     int i;
00494 
00495     for ( i=0; i<appio_ctl->num_events; i++ ) {
00496             int index = appio_ctl->counter_bits[i];
00497             SUBDBG("event=%d, index=%d, val=%lld\n", i, index, _appio_register_current[index]);
00498             appio_ctl->values[index] = _appio_register_current[index];
00499     }
00500     *events = appio_ctl->values;
00501 
00502     return PAPI_OK;
00503 }
00504 
00505 
00506 int
00507 _appio_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00508 {
00509     (void) ctx;
00510 
00511     SUBDBG("_appio_stop ctx=%p ctl=%p\n", ctx, ctl);
00512     APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
00513     int i;
00514     for ( i=0; i<appio_ctl->num_events; i++ ) {
00515             int index = appio_ctl->counter_bits[i];
00516             SUBDBG("event=%d, index=%d, val=%lld\n", i, index, _appio_register_current[index]);
00517             appio_ctl->values[i] = _appio_register_current[index];
00518     }
00519 
00520     return PAPI_OK;
00521 }
00522 
00523 
00524 /*
00525  * Thread shutdown
00526  */
00527 int
00528 _appio_shutdown_thread( hwd_context_t *ctx )
00529 {
00530     ( void ) ctx;
00531 
00532     return PAPI_OK;
00533 }
00534 
00535 
00536 /*
00537  * Clean up what was setup in appio_init_component().
00538  */
00539 int
00540 _appio_shutdown_component( void )
00541 {
00542     return PAPI_OK;
00543 }
00544 
00545 
00546 /* This function sets various options in the component
00547  * The valid codes being passed in are PAPI_SET_DEFDOM,
00548  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and
00549  * PAPI_SET_INHERIT
00550  */
00551 int
00552 _appio_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
00553 {
00554     ( void ) ctx;
00555     ( void ) code;
00556     ( void ) option;
00557 
00558     return PAPI_OK;
00559 }
00560 
00561 
00562 int
00563 _appio_update_control_state( hwd_control_state_t *ctl,
00564         NativeInfo_t *native, int count, hwd_context_t *ctx )
00565 {
00566     ( void ) ctx;
00567     ( void ) ctl;
00568 
00569     SUBDBG("_appio_update_control_state ctx=%p ctl=%p num_events=%d\n", ctx, ctl, count);
00570     int i, index;
00571     APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
00572     (void) ctx;
00573 
00574     for ( i = 0; i < count; i++ ) {
00575         index = native[i].ni_event;
00576         appio_ctl->counter_bits[i] = index;
00577         native[i].ni_position = index;
00578     }
00579     appio_ctl->num_events = count;
00580 
00581     return PAPI_OK;
00582 }
00583 
00584 
00585 /*
00586  * This function has to set the bits needed to count different domains
00587  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00588  * By default return PAPI_EINVAL if none of those are specified
00589  * and PAPI_OK with success
00590  * PAPI_DOM_USER   is only user context is counted
00591  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00592  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00593  * PAPI_DOM_ALL    is all of the domains
00594  */
00595 int
00596 _appio_set_domain( hwd_control_state_t *ctl, int domain )
00597 {
00598     ( void ) ctl;
00599 
00600     int found = 0;
00601 
00602     if ( PAPI_DOM_USER & domain )   found = 1;
00603     if ( PAPI_DOM_KERNEL & domain ) found = 1;
00604     if ( PAPI_DOM_OTHER & domain )  found = 1;
00605 
00606     if ( !found )
00607         return PAPI_EINVAL;
00608 
00609     return PAPI_OK;
00610 }
00611 
00612 
00613 int
00614 _appio_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
00615 {
00616     ( void ) ctx;
00617     ( void ) ctl;
00618 
00619     return PAPI_OK;
00620 }
00621 
00622 
00623 /*
00624  * Native Event functions
00625  */
00626 int
00627 _appio_ntv_enum_events( unsigned int *EventCode, int modifier )
00628 {
00629     int index;
00630 
00631     switch ( modifier ) {
00632         case PAPI_ENUM_FIRST:
00633             *EventCode = 0;
00634             return PAPI_OK;
00635             break;
00636 
00637         case PAPI_ENUM_EVENTS:
00638             index = *EventCode;
00639             if ( index < APPIO_MAX_COUNTERS - 1 ) {
00640                 *EventCode = *EventCode + 1;
00641                 return PAPI_OK;
00642             } else {
00643                 return PAPI_ENOEVNT;
00644             }
00645             break;
00646 
00647         default:
00648             return PAPI_EINVAL;
00649             break;
00650     }
00651     return PAPI_EINVAL;
00652 }
00653 
00654 
00655 /*
00656  *
00657  */
00658 int
00659 _appio_ntv_name_to_code( char *name, unsigned int *EventCode )
00660 {
00661     int i;
00662 
00663     for ( i=0; i<APPIO_MAX_COUNTERS; i++) {
00664         if (strcmp(name, _appio_counter_info[i].name) == 0) {
00665             *EventCode = i;
00666             return PAPI_OK;
00667         }
00668     }
00669 
00670     return PAPI_ENOEVNT;
00671 }
00672 
00673 
00674 /*
00675  *
00676  */
00677 int
00678 _appio_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00679 {
00680     int index = EventCode;
00681 
00682     if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
00683         strncpy( name, _appio_counter_info[index].name, len );
00684         return PAPI_OK;
00685     }
00686 
00687     return PAPI_ENOEVNT;
00688 }
00689 
00690 
00691 /*
00692  *
00693  */
00694 int
00695 _appio_ntv_code_to_descr( unsigned int EventCode, char *desc, int len )
00696 {
00697     int index = EventCode;
00698 
00699     if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
00700         strncpy(desc, _appio_counter_info[index].description, len );
00701         return PAPI_OK;
00702     }
00703 
00704     return PAPI_ENOEVNT;
00705 }
00706 
00707 
00708 /*
00709  *
00710  */
00711 int
00712 _appio_ntv_code_to_bits( unsigned int EventCode, hwd_register_t *bits )
00713 {
00714     int index = EventCode;
00715 
00716     if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
00717         memcpy( ( APPIO_register_t * ) bits,
00718                 &( _appio_native_events[index].resources ),
00719                 sizeof ( APPIO_register_t ) );
00720         return PAPI_OK;
00721     }
00722 
00723     return PAPI_ENOEVNT;
00724 }
00725 
00726 
00727 /*
00728  *
00729  */
00730 papi_vector_t _appio_vector = {
00731     .cmp_info = {
00732         /* default component information (unspecified values are initialized to 0) */
00733         .name                  = "appio",
00734         .short_name            = "appio",
00735         .version               = "1.1.2.4",
00736         .CmpIdx                = 0,              /* set by init_component */
00737         .num_mpx_cntrs         = APPIO_MAX_COUNTERS,
00738         .num_cntrs             = APPIO_MAX_COUNTERS,
00739         .default_domain        = PAPI_DOM_USER,
00740         //.available_domains   = PAPI_DOM_USER,
00741         .default_granularity   = PAPI_GRN_THR,
00742         .available_granularities = PAPI_GRN_THR,
00743         .hardware_intr_sig     = PAPI_INT_SIGNAL,
00744 
00745         /* component specific cmp_info initializations */
00746         .fast_real_timer       = 0,
00747         .fast_virtual_timer    = 0,
00748         .attach                = 0,
00749         .attach_must_ptrace    = 0,
00750         .available_domains     = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00751     },
00752 
00753     /* sizes of framework-opaque component-private structures */
00754     .size = {
00755         .context               = sizeof ( APPIO_context_t ),
00756         .control_state         = sizeof ( APPIO_control_state_t ),
00757         .reg_value             = sizeof ( APPIO_register_t ),
00758         .reg_alloc             = sizeof ( APPIO_reg_alloc_t ),
00759     },
00760 
00761     /* function pointers in this component */
00762     .init_thread               = _appio_init_thread,
00763     .init_component            = _appio_init_component,
00764     .init_control_state        = _appio_init_control_state,
00765     .start                     = _appio_start,
00766     .stop                      = _appio_stop,
00767     .read                      = _appio_read,
00768     .shutdown_thread           = _appio_shutdown_thread,
00769     .shutdown_component        = _appio_shutdown_component,
00770     .ctl                       = _appio_ctl,
00771 
00772     .update_control_state      = _appio_update_control_state,
00773     .set_domain                = _appio_set_domain,
00774     .reset                     = _appio_reset,
00775 
00776     .ntv_enum_events           = _appio_ntv_enum_events,
00777     .ntv_name_to_code          = _appio_ntv_name_to_code,
00778     .ntv_code_to_name          = _appio_ntv_code_to_name,
00779     .ntv_code_to_descr         = _appio_ntv_code_to_descr,
00780     .ntv_code_to_bits          = _appio_ntv_code_to_bits
00781     /* .ntv_bits_to_info          = NULL, */
00782 };
00783 
00784 /* vim:set ts=4 sw=4 sts=4 et: */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines