Blame src/components/appio/appio.c

Packit Service a1973e
/****************************/
Packit Service a1973e
/* THIS IS OPEN SOURCE CODE */
Packit Service a1973e
/****************************/
Packit Service a1973e
Packit Service a1973e
/**
Packit Service a1973e
 * @file    appio.c
Packit Service a1973e
 *
Packit Service a1973e
 * @author  Philip Mucci
Packit Service a1973e
 *          phil.mucci@samaratechnologygroup.com
Packit Service a1973e
 *
Packit Service a1973e
 * @author  Tushar Mohan
Packit Service a1973e
 *          tusharmohan@gmail.com
Packit Service a1973e
 *
Packit Service a1973e
 * Credit to: 
Packit Service a1973e
 *          Jose Pedro Oliveira
Packit Service a1973e
 *          jpo@di.uminho.pt
Packit Service a1973e
 * whose code in the linux net component was used as a template for
Packit Service a1973e
 * many sections of code in this component.
Packit Service a1973e
 *
Packit Service a1973e
 * @ingroup papi_components
Packit Service a1973e
 *
Packit Service a1973e
 * @brief appio component
Packit Service a1973e
 *  This file contains the source code for a component that enables
Packit Service a1973e
 *  PAPI to access application level file and socket I/O information.
Packit Service a1973e
 *  It does this through function replacement in the first person and
Packit Service a1973e
 *  by trapping syscalls in the third person.
Packit Service a1973e
 */
Packit Service a1973e
Packit Service a1973e
#include <stdlib.h>
Packit Service a1973e
#include <ctype.h>
Packit Service a1973e
#include <string.h>
Packit Service a1973e
#include <errno.h>
Packit Service a1973e
#include <sys/select.h>
Packit Service a1973e
#include <sys/types.h>
Packit Service a1973e
#include <unistd.h>
Packit Service a1973e
#include <sys/stat.h>
Packit Service a1973e
Packit Service a1973e
/* Headers required by PAPI */
Packit Service a1973e
#include "papi.h"
Packit Service a1973e
#include "papi_internal.h"
Packit Service a1973e
#include "papi_vector.h"
Packit Service a1973e
#include "papi_memory.h"
Packit Service a1973e
Packit Service a1973e
#include "appio.h"
Packit Service a1973e
Packit Service a1973e
// The PIC test implies it's built for shared linkage
Packit Service a1973e
#ifdef PIC
Packit Service a1973e
#  include "dlfcn.h"
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
#pragma weak dlerror
Packit Service a1973e
static void *_dlsym_fake(void *handle, const char* symbol) { (void) handle; (void) symbol; return NULL; }
Packit Service a1973e
void *dlsym(void *handle, const char* symbol) __attribute__ ((weak, alias ("_dlsym_fake")));
Packit Service a1973e
*/
Packit Service a1973e
Packit Service a1973e
papi_vector_t _appio_vector;
Packit Service a1973e
Packit Service a1973e
/*********************************************************************
Packit Service a1973e
 * Private
Packit Service a1973e
 ********************************************************************/
Packit Service a1973e
Packit Service a1973e
//#define APPIO_FOO 1
Packit Service a1973e
Packit Service a1973e
static APPIO_native_event_entry_t * _appio_native_events;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* If you modify the appio_stats_t below, you MUST update APPIO_MAX_COUNTERS */
Packit Service a1973e
static __thread long long _appio_register_current[APPIO_MAX_COUNTERS];
Packit Service a1973e
typedef enum {
Packit Service a1973e
  READ_BYTES = 0,
Packit Service a1973e
  READ_CALLS,
Packit Service a1973e
  READ_ERR,
Packit Service a1973e
  READ_INTERRUPTED,
Packit Service a1973e
  READ_WOULD_BLOCK,
Packit Service a1973e
  READ_SHORT,
Packit Service a1973e
  READ_EOF,
Packit Service a1973e
  READ_BLOCK_SIZE,
Packit Service a1973e
  READ_USEC,
Packit Service a1973e
  WRITE_BYTES,
Packit Service a1973e
  WRITE_CALLS,
Packit Service a1973e
  WRITE_ERR,
Packit Service a1973e
  WRITE_SHORT,
Packit Service a1973e
  WRITE_INTERRUPTED,
Packit Service a1973e
  WRITE_WOULD_BLOCK,
Packit Service a1973e
  WRITE_BLOCK_SIZE,
Packit Service a1973e
  WRITE_USEC,
Packit Service a1973e
  OPEN_CALLS,
Packit Service a1973e
  OPEN_ERR,
Packit Service a1973e
  OPEN_FDS,
Packit Service a1973e
  SELECT_USEC,
Packit Service a1973e
  RECV_BYTES,
Packit Service a1973e
  RECV_CALLS,
Packit Service a1973e
  RECV_ERR,
Packit Service a1973e
  RECV_INTERRUPTED,
Packit Service a1973e
  RECV_WOULD_BLOCK,
Packit Service a1973e
  RECV_SHORT,
Packit Service a1973e
  RECV_EOF,
Packit Service a1973e
  RECV_BLOCK_SIZE,
Packit Service a1973e
  RECV_USEC,
Packit Service a1973e
  SOCK_READ_BYTES,
Packit Service a1973e
  SOCK_READ_CALLS,
Packit Service a1973e
  SOCK_READ_ERR,
Packit Service a1973e
  SOCK_READ_SHORT,
Packit Service a1973e
  SOCK_READ_WOULD_BLOCK,
Packit Service a1973e
  SOCK_READ_USEC,
Packit Service a1973e
  SOCK_WRITE_BYTES,
Packit Service a1973e
  SOCK_WRITE_CALLS,
Packit Service a1973e
  SOCK_WRITE_ERR,
Packit Service a1973e
  SOCK_WRITE_SHORT,
Packit Service a1973e
  SOCK_WRITE_WOULD_BLOCK,
Packit Service a1973e
  SOCK_WRITE_USEC,
Packit Service a1973e
  SEEK_CALLS,
Packit Service a1973e
  SEEK_ABS_STRIDE_SIZE,
Packit Service a1973e
  SEEK_USEC
Packit Service a1973e
} _appio_stats_t ;
Packit Service a1973e
Packit Service a1973e
static const struct appio_counters {
Packit Service a1973e
    const char *name;
Packit Service a1973e
    const char *description;
Packit Service a1973e
} _appio_counter_info[APPIO_MAX_COUNTERS] = {
Packit Service a1973e
    { "READ_BYTES",      "Bytes read"},
Packit Service a1973e
    { "READ_CALLS",      "Number of read calls"},
Packit Service a1973e
    { "READ_ERR",        "Number of read calls that resulted in an error"},
Packit Service a1973e
    { "READ_INTERRUPTED","Number of read calls that timed out or were interruped"},
Packit Service a1973e
    { "READ_WOULD_BLOCK","Number of read calls that would have blocked"},
Packit Service a1973e
    { "READ_SHORT",      "Number of read calls that returned less bytes than requested"},
Packit Service a1973e
    { "READ_EOF",        "Number of read calls that returned an EOF"},
Packit Service a1973e
    { "READ_BLOCK_SIZE", "Average block size of reads"},
Packit Service a1973e
    { "READ_USEC",       "Real microseconds spent in reads"},
Packit Service a1973e
    { "WRITE_BYTES",     "Bytes written"},
Packit Service a1973e
    { "WRITE_CALLS",     "Number of write calls"},
Packit Service a1973e
    { "WRITE_ERR",       "Number of write calls that resulted in an error"},
Packit Service a1973e
    { "WRITE_SHORT",     "Number of write calls that wrote less bytes than requested"},
Packit Service a1973e
    { "WRITE_INTERRUPTED","Number of write calls that timed out or were interrupted"},
Packit Service a1973e
    { "WRITE_WOULD_BLOCK","Number of write calls that would have blocked"},
Packit Service a1973e
    { "WRITE_BLOCK_SIZE","Mean block size of writes"},
Packit Service a1973e
    { "WRITE_USEC",      "Real microseconds spent in writes"},
Packit Service a1973e
    { "OPEN_CALLS",      "Number of open calls"},
Packit Service a1973e
    { "OPEN_ERR",        "Number of open calls that resulted in an error"},
Packit Service a1973e
    { "OPEN_FDS",        "Number of currently open descriptors"},
Packit Service a1973e
    { "SELECT_USEC",     "Real microseconds spent in select calls"},
Packit Service a1973e
    { "RECV_BYTES",      "Bytes read in recv/recvmsg/recvfrom"},
Packit Service a1973e
    { "RECV_CALLS",      "Number of recv/recvmsg/recvfrom calls"},
Packit Service a1973e
    { "RECV_ERR",        "Number of recv/recvmsg/recvfrom calls that resulted in an error"},
Packit Service a1973e
    { "RECV_INTERRUPTED","Number of recv/recvmsg/recvfrom calls that timed out or were interruped"},
Packit Service a1973e
    { "RECV_WOULD_BLOCK","Number of recv/recvmsg/recvfrom calls that would have blocked"},
Packit Service a1973e
    { "RECV_SHORT",      "Number of recv/recvmsg/recvfrom calls that returned less bytes than requested"},
Packit Service a1973e
    { "RECV_EOF",        "Number of recv/recvmsg/recvfrom calls that returned an EOF"},
Packit Service a1973e
    { "RECV_BLOCK_SIZE", "Average block size of recv/recvmsg/recvfrom"},
Packit Service a1973e
    { "RECV_USEC",       "Real microseconds spent in recv/recvmsg/recvfrom"},
Packit Service a1973e
    { "SOCK_READ_BYTES", "Bytes read from socket"},
Packit Service a1973e
    { "SOCK_READ_CALLS", "Number of read calls on socket"},
Packit Service a1973e
    { "SOCK_READ_ERR",   "Number of read calls on socket that resulted in an error"},
Packit Service a1973e
    { "SOCK_READ_SHORT", "Number of read calls on socket that returned less bytes than requested"},
Packit Service a1973e
    { "SOCK_READ_WOULD_BLOCK", "Number of read calls on socket that would have blocked"},
Packit Service a1973e
    { "SOCK_READ_USEC",  "Real microseconds spent in read(s) on socket(s)"},
Packit Service a1973e
    { "SOCK_WRITE_BYTES","Bytes written to socket"},
Packit Service a1973e
    { "SOCK_WRITE_CALLS","Number of write calls to socket"},
Packit Service a1973e
    { "SOCK_WRITE_ERR",  "Number of write calls to socket that resulted in an error"},
Packit Service a1973e
    { "SOCK_WRITE_SHORT","Number of write calls to socket that wrote less bytes than requested"},
Packit Service a1973e
    { "SOCK_WRITE_WOULD_BLOCK","Number of write calls to socket that would have blocked"},
Packit Service a1973e
    { "SOCK_WRITE_USEC", "Real microseconds spent in write(s) to socket(s)"},
Packit Service a1973e
    { "SEEK_CALLS",      "Number of seek calls"},
Packit Service a1973e
    { "SEEK_ABS_STRIDE_SIZE", "Average absolute stride size of seeks"},
Packit Service a1973e
    { "SEEK_USEC",       "Real microseconds spent in seek calls"}
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*********************************************************************
Packit Service a1973e
 ***  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT ****
Packit Service a1973e
 ********************************************************************/
Packit Service a1973e
Packit Service a1973e
int __close(int fd);
Packit Service a1973e
int close(int fd) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted close(%d)\n", fd);
Packit Service a1973e
  retval = __close(fd);
Packit Service a1973e
  if ((retval == 0) && (_appio_register_current[OPEN_FDS]>0)) _appio_register_current[OPEN_FDS]--;
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int __open(const char *pathname, int flags, mode_t mode);
Packit Service a1973e
int open(const char *pathname, int flags, mode_t mode) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted open(%s,%d,%d)\n", pathname, flags, mode);
Packit Service a1973e
  retval = __open(pathname,flags,mode);
Packit Service a1973e
  _appio_register_current[OPEN_CALLS]++;
Packit Service a1973e
  if (retval < 0) _appio_register_current[OPEN_ERR]++;
Packit Service a1973e
  else _appio_register_current[OPEN_FDS]++;
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* we use timeval as a zero value timeout to select in read/write
Packit Service a1973e
   for polling if the operation would block */
Packit Service a1973e
struct timeval zerotv; /* this has to be zero, so define it here */
Packit Service a1973e
Packit Service a1973e
int __select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
Packit Service a1973e
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted select(%d,%p,%p,%p,%p)\n", nfds,readfds,writefds,exceptfds,timeout);
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = __select(nfds,readfds,writefds,exceptfds,timeout);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  _appio_register_current[SELECT_USEC] += duration;
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
off_t __lseek(int fd, off_t offset, int whence);
Packit Service a1973e
off_t lseek(int fd, off_t offset, int whence) {
Packit Service a1973e
  off_t retval;
Packit Service a1973e
  SUBDBG("appio: intercepted lseek(%d,%ld,%d)\n", fd, offset, whence);
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = __lseek(fd, offset, whence);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[SEEK_CALLS]++;
Packit Service a1973e
  _appio_register_current[SEEK_USEC] += duration;
Packit Service a1973e
  if (offset < 0) offset = -offset; // get abs offset
Packit Service a1973e
  _appio_register_current[SEEK_ABS_STRIDE_SIZE]= (n * _appio_register_current[SEEK_ABS_STRIDE_SIZE] + offset)/(n+1); // mean absolute stride size
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
extern int errno;
Packit Service a1973e
ssize_t __read(int fd, void *buf, size_t count);
Packit Service a1973e
ssize_t read(int fd, void *buf, size_t count) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted read(%d,%p,%lu)\n", fd, buf, (unsigned long)count);
Packit Service a1973e
Packit Service a1973e
  struct stat st;
Packit Service a1973e
  int issocket = 0;
Packit Service a1973e
  if (fstat(fd, &st) == 0) {
Packit Service a1973e
    if ((st.st_mode & S_IFMT) == S_IFSOCK) issocket = 1;
Packit Service a1973e
  }
Packit Service a1973e
  // check if read would block on descriptor
Packit Service a1973e
  fd_set readfds;
Packit Service a1973e
  FD_ZERO(&readfds);
Packit Service a1973e
  FD_SET(fd, &readfds);
Packit Service a1973e
  int ready = __select(fd+1, &readfds, NULL, NULL, &zerotv);
Packit Service a1973e
  if (ready == 0) {
Packit Service a1973e
     _appio_register_current[READ_WOULD_BLOCK]++; 
Packit Service a1973e
     if (issocket) _appio_register_current[SOCK_READ_WOULD_BLOCK]++; 
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = __read(fd,buf, count);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[READ_CALLS]++; // read calls
Packit Service a1973e
  if (issocket) _appio_register_current[SOCK_READ_CALLS]++; // read calls
Packit Service a1973e
  if (retval > 0) {
Packit Service a1973e
    _appio_register_current[READ_BLOCK_SIZE]= (n * _appio_register_current[READ_BLOCK_SIZE] + count)/(n+1); // mean size
Packit Service a1973e
    _appio_register_current[READ_BYTES] += retval; // read bytes
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_READ_BYTES] += retval;
Packit Service a1973e
    if (retval < (int)count) {
Packit Service a1973e
       _appio_register_current[READ_SHORT]++; // read short
Packit Service a1973e
       if (issocket) _appio_register_current[SOCK_READ_SHORT]++; // read short
Packit Service a1973e
    }
Packit Service a1973e
    _appio_register_current[READ_USEC] += duration;
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_READ_USEC] += duration;
Packit Service a1973e
  }
Packit Service a1973e
  if (retval < 0) { 
Packit Service a1973e
    _appio_register_current[READ_ERR]++; // read err
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_READ_ERR]++; // read err
Packit Service a1973e
    if (EINTR == errno)
Packit Service a1973e
      _appio_register_current[READ_INTERRUPTED]++; // signal interrupted the read
Packit Service a1973e
    //if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
Packit Service a1973e
    //  _appio_register_current[READ_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
Packit Service a1973e
    //  if (issocket) _appio_register_current[SOCK_READ_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
Packit Service a1973e
    //}
Packit Service a1973e
  }
Packit Service a1973e
  if (retval == 0) _appio_register_current[READ_EOF]++; // read eof
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
size_t _IO_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Packit Service a1973e
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
Packit Service a1973e
  size_t retval;
Packit Service a1973e
  SUBDBG("appio: intercepted fread(%p,%lu,%lu,%p)\n", ptr, (unsigned long) size, (unsigned long) nmemb, (void*) stream);
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = _IO_fread(ptr,size,nmemb,stream);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[READ_CALLS]++; // read calls
Packit Service a1973e
  if (retval > 0) {
Packit Service a1973e
    _appio_register_current[READ_BLOCK_SIZE]= (n * _appio_register_current[READ_BLOCK_SIZE]+ size*nmemb)/(n+1);//mean size
Packit Service a1973e
    _appio_register_current[READ_BYTES]+= retval * size; // read bytes
Packit Service a1973e
    if (retval < nmemb) _appio_register_current[READ_SHORT]++; // read short
Packit Service a1973e
    _appio_register_current[READ_USEC] += duration;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  /* A value of zero returned means one of two things..*/
Packit Service a1973e
  if (retval == 0) {
Packit Service a1973e
     if (feof(stream)) _appio_register_current[READ_EOF]++; // read eof
Packit Service a1973e
     else _appio_register_current[READ_ERR]++; // read err
Packit Service a1973e
  }
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
ssize_t __write(int fd, const void *buf, size_t count);
Packit Service a1973e
ssize_t write(int fd, const void *buf, size_t count) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted write(%d,%p,%lu)\n", fd, buf, (unsigned long)count);
Packit Service a1973e
  struct stat st;
Packit Service a1973e
  int issocket = 0;
Packit Service a1973e
  if (fstat(fd, &st) == 0) {
Packit Service a1973e
    if ((st.st_mode & S_IFMT) == S_IFSOCK) issocket = 1;
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  // check if write would block on descriptor
Packit Service a1973e
  fd_set writefds;
Packit Service a1973e
  FD_ZERO(&writefds);
Packit Service a1973e
  FD_SET(fd, &writefds);
Packit Service a1973e
  int ready = __select(fd+1, NULL, &writefds, NULL, &zerotv);
Packit Service a1973e
  if (ready == 0) {
Packit Service a1973e
    _appio_register_current[WRITE_WOULD_BLOCK]++; 
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_WRITE_WOULD_BLOCK]++; 
Packit Service a1973e
  }
Packit Service a1973e
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = __write(fd,buf, count);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[WRITE_CALLS]++; // write calls
Packit Service a1973e
  if (issocket) _appio_register_current[SOCK_WRITE_CALLS]++; // socket write
Packit Service a1973e
  if (retval >= 0) {
Packit Service a1973e
    _appio_register_current[WRITE_BLOCK_SIZE]= (n * _appio_register_current[WRITE_BLOCK_SIZE] + count)/(n+1); // mean size
Packit Service a1973e
    _appio_register_current[WRITE_BYTES]+= retval; // write bytes
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_WRITE_BYTES] += retval;
Packit Service a1973e
    if (retval < (int)count) {
Packit Service a1973e
      _appio_register_current[WRITE_SHORT]++; // short write
Packit Service a1973e
      if (issocket) _appio_register_current[SOCK_WRITE_SHORT]++; 
Packit Service a1973e
    }
Packit Service a1973e
    _appio_register_current[WRITE_USEC] += duration;
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_WRITE_USEC] += duration;
Packit Service a1973e
  }
Packit Service a1973e
  if (retval < 0) {
Packit Service a1973e
    _appio_register_current[WRITE_ERR]++; // err
Packit Service a1973e
    if (issocket) _appio_register_current[SOCK_WRITE_ERR]++;
Packit Service a1973e
    if (EINTR == errno)
Packit Service a1973e
      _appio_register_current[WRITE_INTERRUPTED]++; // signal interrupted the op
Packit Service a1973e
    //if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) {
Packit Service a1973e
    //  _appio_register_current[WRITE_WOULD_BLOCK]++; //op would block on descriptor marked as non-blocking
Packit Service a1973e
    //  if (issocket) _appio_register_current[SOCK_WRITE_WOULD_BLOCK]++;
Packit Service a1973e
    //}
Packit Service a1973e
  }
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
// The PIC test implies it's built for shared linkage
Packit Service a1973e
#ifdef PIC
Packit Service a1973e
static ssize_t (*__recv)(int sockfd, void *buf, size_t len, int flags) = NULL;
Packit Service a1973e
ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
Packit Service a1973e
  int retval;
Packit Service a1973e
  SUBDBG("appio: intercepted recv(%d,%p,%lu,%d)\n", sockfd, buf, (unsigned long)len, flags);
Packit Service a1973e
  if (!__recv) __recv  = dlsym(RTLD_NEXT, "recv");
Packit Service a1973e
  if (!__recv) {
Packit Service a1973e
    fprintf(stderr, "appio,c Internal Error: Could not obtain handle for real recv\n");
Packit Service a1973e
    exit(1);
Packit Service a1973e
  }
Packit Service a1973e
  // check if recv would block on descriptor
Packit Service a1973e
  fd_set readfds;
Packit Service a1973e
  FD_ZERO(&readfds);
Packit Service a1973e
  FD_SET(sockfd, &readfds);
Packit Service a1973e
  int ready = __select(sockfd+1, &readfds, NULL, NULL, &zerotv);
Packit Service a1973e
  if (ready == 0) _appio_register_current[RECV_WOULD_BLOCK]++; 
Packit Service a1973e
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = __recv(sockfd, buf, len, flags);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[RECV_CALLS]++; // read calls
Packit Service a1973e
  if (retval > 0) {
Packit Service a1973e
    _appio_register_current[RECV_BLOCK_SIZE]= (n * _appio_register_current[RECV_BLOCK_SIZE] + len)/(n+1); // mean size
Packit Service a1973e
    _appio_register_current[RECV_BYTES] += retval; // read bytes
Packit Service a1973e
    if (retval < (int)len) _appio_register_current[RECV_SHORT]++; // read short
Packit Service a1973e
    _appio_register_current[RECV_USEC] += duration;
Packit Service a1973e
  }
Packit Service a1973e
  if (retval < 0) { 
Packit Service a1973e
    _appio_register_current[RECV_ERR]++; // read err
Packit Service a1973e
    if (EINTR == errno)
Packit Service a1973e
      _appio_register_current[RECV_INTERRUPTED]++; // signal interrupted the read
Packit Service a1973e
    if ((EAGAIN == errno) || (EWOULDBLOCK == errno)) 
Packit Service a1973e
      _appio_register_current[RECV_WOULD_BLOCK]++; //read would block on descriptor marked as non-blocking
Packit Service a1973e
  }
Packit Service a1973e
  if (retval == 0) _appio_register_current[RECV_EOF]++; // read eof
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
#endif /* PIC */
Packit Service a1973e
Packit Service a1973e
size_t _IO_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
Packit Service a1973e
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
Packit Service a1973e
  size_t retval;
Packit Service a1973e
  SUBDBG("appio: intercepted fwrite(%p,%lu,%lu,%p)\n", ptr, (unsigned long) size, (unsigned long) nmemb, (void*) stream);
Packit Service a1973e
  long long start_ts = PAPI_get_real_usec();
Packit Service a1973e
  retval = _IO_fwrite(ptr,size,nmemb,stream);
Packit Service a1973e
  long long duration = PAPI_get_real_usec() - start_ts;
Packit Service a1973e
  int n = _appio_register_current[WRITE_CALLS]++; // write calls
Packit Service a1973e
  if (retval > 0) {
Packit Service a1973e
    _appio_register_current[WRITE_BLOCK_SIZE]= (n * _appio_register_current[WRITE_BLOCK_SIZE] + size*nmemb)/(n+1); // mean block size
Packit Service a1973e
    _appio_register_current[WRITE_BYTES]+= retval * size; // write bytes
Packit Service a1973e
    if (retval < nmemb) _appio_register_current[WRITE_SHORT]++; // short write
Packit Service a1973e
    _appio_register_current[WRITE_USEC] += duration;
Packit Service a1973e
  }
Packit Service a1973e
  if (retval == 0) _appio_register_current[WRITE_ERR]++; // err
Packit Service a1973e
  return retval;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*********************************************************************
Packit Service a1973e
 ***************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *********
Packit Service a1973e
 *********************************************************************/
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * This is called whenever a thread is initialized
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_init_thread( hwd_context_t *ctx )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
    SUBDBG("_appio_init_thread %p\n", ctx);
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* Initialize hardware counters, setup the function vector table
Packit Service a1973e
 * and get hardware information, this routine is called when the 
Packit Service a1973e
 * PAPI process is initialized (IE PAPI_library_init)
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_init_component( int cidx  )
Packit Service a1973e
{
Packit Service a1973e
Packit Service a1973e
    SUBDBG("_appio_component %d\n", cidx);
Packit Service a1973e
    _appio_native_events = (APPIO_native_event_entry_t *) papi_calloc(APPIO_MAX_COUNTERS, sizeof(APPIO_native_event_entry_t));
Packit Service a1973e
Packit Service a1973e
    if (_appio_native_events == NULL ) {
Packit Service a1973e
      PAPIERROR( "malloc():Could not get memory for events table" );
Packit Service a1973e
      return PAPI_ENOMEM;
Packit Service a1973e
    }
Packit Service a1973e
    int i;
Packit Service a1973e
    for (i=0; i
Packit Service a1973e
      _appio_native_events[i].name = _appio_counter_info[i].name;
Packit Service a1973e
      _appio_native_events[i].description = _appio_counter_info[i].description;
Packit Service a1973e
      _appio_native_events[i].resources.selector = i + 1;
Packit Service a1973e
    }
Packit Service a1973e
  
Packit Service a1973e
    /* Export the total number of events available */
Packit Service a1973e
    _appio_vector.cmp_info.num_native_events = APPIO_MAX_COUNTERS;;
Packit Service a1973e
Packit Service a1973e
    /* Export the component id */
Packit Service a1973e
    _appio_vector.cmp_info.CmpIdx = cidx;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Control of counters (Reading/Writing/Starting/Stopping/Setup)
Packit Service a1973e
 * functions
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_init_control_state( hwd_control_state_t *ctl )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctl;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_appio_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
Packit Service a1973e
    SUBDBG("_appio_start %p %p\n", ctx, ctl);
Packit Service a1973e
    APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
Packit Service a1973e
Packit Service a1973e
    /* this memset needs to move to thread_init */
Packit Service a1973e
    memset(_appio_register_current, 0, APPIO_MAX_COUNTERS * sizeof(_appio_register_current[0]));
Packit Service a1973e
Packit Service a1973e
    /* set initial values to 0 */
Packit Service a1973e
    memset(appio_ctl->values, 0, APPIO_MAX_COUNTERS*sizeof(appio_ctl->values[0]));
Packit Service a1973e
    
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_appio_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
Packit Service a1973e
    long long ** events, int flags )
Packit Service a1973e
{
Packit Service a1973e
    (void) flags;
Packit Service a1973e
    (void) ctx;
Packit Service a1973e
Packit Service a1973e
    SUBDBG("_appio_read %p %p\n", ctx, ctl);
Packit Service a1973e
    APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
Packit Service a1973e
    int i;
Packit Service a1973e
Packit Service a1973e
    for ( i=0; i<appio_ctl->num_events; i++ ) {
Packit Service a1973e
            int index = appio_ctl->counter_bits[i];
Packit Service a1973e
            SUBDBG("event=%d, index=%d, val=%lld\n", i, index, _appio_register_current[index]);
Packit Service a1973e
            appio_ctl->values[index] = _appio_register_current[index];
Packit Service a1973e
    }
Packit Service a1973e
    *events = appio_ctl->values;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_appio_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit Service a1973e
{
Packit Service a1973e
    (void) ctx;
Packit Service a1973e
Packit Service a1973e
    SUBDBG("_appio_stop ctx=%p ctl=%p\n", ctx, ctl);
Packit Service a1973e
    APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
Packit Service a1973e
    int i;
Packit Service a1973e
    for ( i=0; i<appio_ctl->num_events; i++ ) {
Packit Service a1973e
            int index = appio_ctl->counter_bits[i];
Packit Service a1973e
            SUBDBG("event=%d, index=%d, val=%lld\n", i, index, _appio_register_current[index]);
Packit Service a1973e
            appio_ctl->values[i] = _appio_register_current[index];
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Thread shutdown
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_shutdown_thread( hwd_context_t *ctx )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Clean up what was setup in appio_init_component().
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_shutdown_component( void )
Packit Service a1973e
{
Packit Service a1973e
    papi_free( _appio_native_events );
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/* This function sets various options in the component
Packit Service a1973e
 * The valid codes being passed in are PAPI_SET_DEFDOM,
Packit Service a1973e
 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and
Packit Service a1973e
 * PAPI_SET_INHERIT
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
    ( void ) code;
Packit Service a1973e
    ( void ) option;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_appio_update_control_state( hwd_control_state_t *ctl,
Packit Service a1973e
        NativeInfo_t *native, int count, hwd_context_t *ctx )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
    ( void ) ctl;
Packit Service a1973e
Packit Service a1973e
    SUBDBG("_appio_update_control_state ctx=%p ctl=%p num_events=%d\n", ctx, ctl, count);
Packit Service a1973e
    int i, index;
Packit Service a1973e
    APPIO_control_state_t *appio_ctl = (APPIO_control_state_t *) ctl;
Packit Service a1973e
    (void) ctx;
Packit Service a1973e
Packit Service a1973e
    for ( i = 0; i < count; i++ ) {
Packit Service a1973e
        index = native[i].ni_event;
Packit Service a1973e
        appio_ctl->counter_bits[i] = index;
Packit Service a1973e
        native[i].ni_position = index;
Packit Service a1973e
    }
Packit Service a1973e
    appio_ctl->num_events = count;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * This function has to set the bits needed to count different domains
Packit Service a1973e
 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
Packit Service a1973e
 * By default return PAPI_EINVAL if none of those are specified
Packit Service a1973e
 * and PAPI_OK with success
Packit Service a1973e
 * PAPI_DOM_USER   is only user context is counted
Packit Service a1973e
 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
Packit Service a1973e
 * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
Packit Service a1973e
 * PAPI_DOM_ALL    is all of the domains
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_set_domain( hwd_control_state_t *ctl, int domain )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctl;
Packit Service a1973e
Packit Service a1973e
    int found = 0;
Packit Service a1973e
Packit Service a1973e
    if ( PAPI_DOM_USER == domain )   found = 1;
Packit Service a1973e
Packit Service a1973e
    if ( !found )
Packit Service a1973e
        return PAPI_EINVAL;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
_appio_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
Packit Service a1973e
{
Packit Service a1973e
    ( void ) ctx;
Packit Service a1973e
    ( void ) ctl;
Packit Service a1973e
Packit Service a1973e
    return PAPI_OK;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Native Event functions
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ntv_enum_events( unsigned int *EventCode, int modifier )
Packit Service a1973e
{
Packit Service a1973e
    int index;
Packit Service a1973e
Packit Service a1973e
    switch ( modifier ) {
Packit Service a1973e
        case PAPI_ENUM_FIRST:
Packit Service a1973e
            *EventCode = 0;
Packit Service a1973e
            return PAPI_OK;
Packit Service a1973e
            break;
Packit Service a1973e
Packit Service a1973e
        case PAPI_ENUM_EVENTS:
Packit Service a1973e
            index = *EventCode;
Packit Service a1973e
            if ( index < APPIO_MAX_COUNTERS - 1 ) {
Packit Service a1973e
                *EventCode = *EventCode + 1;
Packit Service a1973e
                return PAPI_OK;
Packit Service a1973e
            } else {
Packit Service a1973e
                return PAPI_ENOEVNT;
Packit Service a1973e
            }
Packit Service a1973e
            break;
Packit Service a1973e
Packit Service a1973e
        default:
Packit Service a1973e
            return PAPI_EINVAL;
Packit Service a1973e
            break;
Packit Service a1973e
    }
Packit Service a1973e
    return PAPI_EINVAL;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ntv_name_to_code( const char *name, unsigned int *EventCode )
Packit Service a1973e
{
Packit Service a1973e
    int i;
Packit Service a1973e
Packit Service a1973e
    for ( i=0; i
Packit Service a1973e
        if (strcmp(name, _appio_counter_info[i].name) == 0) {
Packit Service a1973e
            *EventCode = i;
Packit Service a1973e
            return PAPI_OK;
Packit Service a1973e
        }
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ntv_code_to_name( unsigned int EventCode, char *name, int len )
Packit Service a1973e
{
Packit Service a1973e
    int index = EventCode;
Packit Service a1973e
Packit Service a1973e
    if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
Packit Service a1973e
        strncpy( name, _appio_counter_info[index].name, len );
Packit Service a1973e
        return PAPI_OK;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ntv_code_to_descr( unsigned int EventCode, char *desc, int len )
Packit Service a1973e
{
Packit Service a1973e
    int index = EventCode;
Packit Service a1973e
Packit Service a1973e
    if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
Packit Service a1973e
        strncpy(desc, _appio_counter_info[index].description, len );
Packit Service a1973e
        return PAPI_OK;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
_appio_ntv_code_to_bits( unsigned int EventCode, hwd_register_t *bits )
Packit Service a1973e
{
Packit Service a1973e
    int index = EventCode;
Packit Service a1973e
Packit Service a1973e
    if ( index >= 0 && index < APPIO_MAX_COUNTERS ) {
Packit Service a1973e
        memcpy( ( APPIO_register_t * ) bits,
Packit Service a1973e
                &( _appio_native_events[index].resources ),
Packit Service a1973e
                sizeof ( APPIO_register_t ) );
Packit Service a1973e
        return PAPI_OK;
Packit Service a1973e
    }
Packit Service a1973e
Packit Service a1973e
    return PAPI_ENOEVNT;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 *
Packit Service a1973e
 */
Packit Service a1973e
papi_vector_t _appio_vector = {
Packit Service a1973e
    .cmp_info = {
Packit Service a1973e
        /* default component information (unspecified values are initialized to 0) */
Packit Service a1973e
        .name                  = "appio",
Packit Service a1973e
        .short_name            = "appio",
Packit Service a1973e
        .version               = "1.1.2.4",
Packit Service a1973e
        .CmpIdx                = 0,              /* set by init_component */
Packit Service a1973e
        .num_mpx_cntrs         = APPIO_MAX_COUNTERS,
Packit Service a1973e
        .num_cntrs             = APPIO_MAX_COUNTERS,
Packit Service a1973e
        .default_domain        = PAPI_DOM_USER,
Packit Service a1973e
        .available_domains   = PAPI_DOM_USER,
Packit Service a1973e
        .default_granularity   = PAPI_GRN_THR,
Packit Service a1973e
        .available_granularities = PAPI_GRN_THR,
Packit Service a1973e
        .hardware_intr_sig     = PAPI_INT_SIGNAL,
Packit Service a1973e
Packit Service a1973e
        /* component specific cmp_info initializations */
Packit Service a1973e
        .fast_real_timer       = 0,
Packit Service a1973e
        .fast_virtual_timer    = 0,
Packit Service a1973e
        .attach                = 0,
Packit Service a1973e
        .attach_must_ptrace    = 0,
Packit Service a1973e
    },
Packit Service a1973e
Packit Service a1973e
    /* sizes of framework-opaque component-private structures */
Packit Service a1973e
    .size = {
Packit Service a1973e
        .context               = sizeof ( APPIO_context_t ),
Packit Service a1973e
        .control_state         = sizeof ( APPIO_control_state_t ),
Packit Service a1973e
        .reg_value             = sizeof ( APPIO_register_t ),
Packit Service a1973e
        .reg_alloc             = sizeof ( APPIO_reg_alloc_t ),
Packit Service a1973e
    },
Packit Service a1973e
Packit Service a1973e
    /* function pointers in this component */
Packit Service a1973e
    .init_thread               = _appio_init_thread,
Packit Service a1973e
    .init_component            = _appio_init_component,
Packit Service a1973e
    .init_control_state        = _appio_init_control_state,
Packit Service a1973e
    .start                     = _appio_start,
Packit Service a1973e
    .stop                      = _appio_stop,
Packit Service a1973e
    .read                      = _appio_read,
Packit Service a1973e
    .shutdown_thread           = _appio_shutdown_thread,
Packit Service a1973e
    .shutdown_component        = _appio_shutdown_component,
Packit Service a1973e
    .ctl                       = _appio_ctl,
Packit Service a1973e
Packit Service a1973e
    .update_control_state      = _appio_update_control_state,
Packit Service a1973e
    .set_domain                = _appio_set_domain,
Packit Service a1973e
    .reset                     = _appio_reset,
Packit Service a1973e
Packit Service a1973e
    .ntv_enum_events           = _appio_ntv_enum_events,
Packit Service a1973e
    .ntv_name_to_code          = _appio_ntv_name_to_code,
Packit Service a1973e
    .ntv_code_to_name          = _appio_ntv_code_to_name,
Packit Service a1973e
    .ntv_code_to_descr         = _appio_ntv_code_to_descr,
Packit Service a1973e
    .ntv_code_to_bits          = _appio_ntv_code_to_bits
Packit Service a1973e
    /* .ntv_bits_to_info          = NULL, */
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
/* vim:set ts=4 sw=4 sts=4 et: */