1
1

Per the MemPin RFC, submit the component source files, and update the memchecker macros.

This commit was SVN r27508.
Этот коммит содержится в:
Shiqing Fan 2012-10-27 02:48:20 +00:00
родитель 8677693d9a
Коммит 12c3c743de
28 изменённых файлов: 2254 добавлений и 34 удалений

Просмотреть файл

@ -23,6 +23,7 @@ headers += \
ompi/constants.h \
ompi/types.h \
ompi/memchecker.h \
ompi/memchecker_rw_check.h \
ompi/totalview.h
nodist_headers += \

424
ompi/include/ompi/memchecker_rw_check.h Обычный файл
Просмотреть файл

@ -0,0 +1,424 @@
/*
* Copyright (c) 2010 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_MEMCHECKER_RW_CHECK_H
#define OMPI_MEMCHECKER_RW_CHECK_H
#include "ompi_config.h"
#include "opal/util/output.h"
#include "opal/mca/memchecker/base/base.h"
#include "opal/mca/memchecker/memchecker.h"
/* better to include this file directly into ompi/include/ompi/memchecker.h
* or merge it in opal/mca/memchecker/*
*/
/* phase 0 check memory state definition */
#define MEMCHECKER_WATCH_READ 0 /* check phase 0: mem not readable. check phase 1: watch mem read */
#define MEMCHECKER_WATCH_WRITE 1 /* check phase 0: mem not writable. check phase 1: watch mem write */
#define MEMCHECKER_WATCH_RW 2 /* check phase 0: mem not writable or readable. check phase 1: watch mem write and read operation */
/* phase 1 check memory state definition */
#define MEMCHECKER_MEM_NOT_READABLE 0
#define MEMCHECKER_MEM_NOT_WRITABLE 1
#define MEMCHECKER_MEM_NOT_ACCESSABLE 2
/* memchecker check phases */
#define MEMCHECKER_PRE_COMM_PHASE 0 /* Pre-communication check phase */
#define MEMCHECKER_POST_COMM_PHASE 1 /* Post-communication check phase */
/* definitions for printing callback in MemPin */
#define MEMPIN_CALLBACK_PRINT_SOURCE 0
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_1 1
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_2 2
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_3 3
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_4 4
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_5 5
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_ALL 100
/* bit operation macros */
#define BITS_PER_BYTE 8
#define BIT_SET1(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] |= (1<<((pos)%BITS_PER_BYTE)))
#define BIT_SET0(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] &= ~(1<<((pos)%BITS_PER_BYTE)))
#define BIT_TEST(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] & (1<<((pos)%BITS_PER_BYTE)))
#define BIT_FLIP(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] ^= (1<<((pos)%BITS_PER_BYTE)))
static inline int memchecker_rw_check_show_state()
{
size_t i, j;
for( i = 0;i < memchecker_num_mem;i++ ) {
char *shadow_bits;
char tmp[3];
shadow_bits = (char *)malloc(memchecker_rw_check[i].len*3);
/* memset always gets seg fault under pin, so use a loop to initialize the bits. */
for (j = 0; j < memchecker_rw_check[i].len*3; j++) {
shadow_bits[j] = ' ';
}
shadow_bits[memchecker_rw_check[i].len*3] = '\0';
for( j = 0; j < memchecker_rw_check[i].len; j++ ) {
if(BIT_TEST(memchecker_rw_check[i].rw_flag, 2*j)) {
shadow_bits[3*j] = '1';
} else {
shadow_bits[3*j] = '0';
}
if(BIT_TEST(memchecker_rw_check[i].rw_flag, 2*j+1)) {
shadow_bits[3*j+1] = '1';
} else {
shadow_bits[3*j+1] = '0';
}
}
opal_output(0, "---- memory state bits at %0x:", memchecker_rw_check[i].addr);
opal_output(0,"%s", shadow_bits);
free(shadow_bits);
}
return OMPI_SUCCESS;
}
/*
* two phases of checks:
* pre-comm check phase : for non-blocking send/recv buffer accessibility
* post-comm check phase: watch on the received buffers, whether they are used correctly
*/
static int memchecker_rw_check_cb(void *addr, size_t size, int offset, int is_write, void *result)
{
int ret = OMPI_SUCCESS;
unsigned int i, pos, rd_err, wr_err;
if(!memchecker_enable_check) {
return OMPI_SUCCESS;
}
if( offset >= 0 ) {
pos = 0;
} else {
pos = -offset;
}
/* opal_output(0, "checking phase:%d", memchecker_phase); */
/* memchecker_rw_check_show_state(); */
switch( memchecker_phase ) {
case MEMCHECKER_PRE_COMM_PHASE:
rd_err = 0;
wr_err = 0;
for( i = 0; i < size; i++ ) {
if(is_write) {
/* is it a write operation on a un-writable region? */
if( BIT_TEST((*(memchecker_rw_check_t *)result).rw_flag, (pos+i)*2+1) ) {
wr_err++;
}
} else {
/* is it a read operation on a un-readable region? */
if( BIT_TEST((*(memchecker_rw_check_t *)result).rw_flag, (pos+i)*2) ) {
rd_err++;
}
}
}
if (rd_err > 0) {
opal_output(0, "memchecker: invalid read of size %d at %0x.\n", rd_err, addr);
/* return and print 5 levels callstack */
ret = MEMPIN_CALLBACK_PRINT_CALLSTACK_5;
}
if (wr_err > 0) {
opal_output(0, "memchecker: invalid write of size %d at %0x.\n", wr_err, addr);
/* return and print 5 levels callstack */
ret = MEMPIN_CALLBACK_PRINT_CALLSTACK_5;
}
break;
case MEMCHECKER_POST_COMM_PHASE:
/* opal_output(0, "<debug> [%d]: %0x\n", pos/4, (*(memchecker_rw_check_t *)result).rw_flag[pos/4]); */
for( i = 0; i < size; i++ ) {
/* opal_output(0, "<debug> offset: %d, pos: %d\n", offset, pos+i); */
if(is_write) {
if( !BIT_TEST((*(memchecker_rw_check_t *)result).rw_flag, (pos+i)*2) ) {
opal_output(0, "memchecker: write before read at %0x:%d\n", (size_t)addr, pos+i);
/* set error flag */
BIT_SET1((*(memchecker_rw_check_t *)result).rw_flag, (pos+i)*2+1);
/* return and print 5 levels callstack */
ret = MEMPIN_CALLBACK_PRINT_CALLSTACK_5;
}
} else {
/* set read flag */
BIT_SET1((*(memchecker_rw_check_t *)result).rw_flag, (pos+i)*2);
}
}
break;
case 2:/* for other checks */
default:
break;
}
/* opal_output(0, "<debug> [%d]: %0x\n", pos/4, (*(memchecker_rw_check_t *)result).rw_flag[pos/4]); */
/* memchecker_rw_check_show_state(); */
return ret;
}
static inline int memchecker_reg_mem_rw_check(void *addr, size_t count, ompi_datatype_t *datatype, int watch_type)
{
if (!opal_memchecker_base_runindebugger() ||
(addr == NULL) || (count == 0) ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
unsigned int i;
size_t len = count*(datatype->super.true_ub - datatype->super.true_lb);
void *tmp = realloc(memchecker_rw_check, (memchecker_num_mem+1)*sizeof(memchecker_rw_check_t));
if(!tmp) {
/* error output */
opal_output(0, "memchecker: memory allocation error. number of entries: %d\n", memchecker_num_mem);
}
memchecker_rw_check = (memchecker_rw_check_t *) tmp;
(memchecker_rw_check[memchecker_num_mem]).addr = addr;
(memchecker_rw_check[memchecker_num_mem]).rw_flag = (char *) malloc(len*2);
(memchecker_rw_check[memchecker_num_mem]).datatype = datatype;
(memchecker_rw_check[memchecker_num_mem]).len = len;
/* initialize the rw flags according to the watch_type*/
memset((memchecker_rw_check[memchecker_num_mem]).rw_flag, 0, len*2);
if (memchecker_phase == MEMCHECKER_PRE_COMM_PHASE) {
if( watch_type == MEMCHECKER_WATCH_READ ) {
for( i = 0; i < len; i++) {
BIT_SET1((memchecker_rw_check[memchecker_num_mem]).rw_flag, i*2);
}
} else if( watch_type == MEMCHECKER_WATCH_WRITE ) {
for( i = 0; i < len; i++) {
BIT_SET1((memchecker_rw_check[memchecker_num_mem]).rw_flag, i*2+1);
}
} else if( watch_type == MEMCHECKER_WATCH_RW ) {
for( i = 0; i < len; i++) {
BIT_SET1((memchecker_rw_check[memchecker_num_mem]).rw_flag, i*2);
BIT_SET1((memchecker_rw_check[memchecker_num_mem]).rw_flag, i*2+1);
}
} else {
/* unknow watch type */
opal_output(0, "memchecker: unknow watch type.\n");
}
}
if ( OMPI_SUCCESS ==
opal_memchecker_base_reg_mem_watch(addr, len, MEMCHECKER_WATCH_RW, (void *) &memchecker_rw_check_cb,
(void *) &memchecker_rw_check[memchecker_num_mem]) ) {
memchecker_num_mem++;
}
/* opal_output(0, "memchecker: number of mem: %d, read: %d; write: %d\n", memchecker_num_mem, read_cnt, write_cnt); */
return OMPI_SUCCESS;
}
static inline int memchecker_unreg_mem_rw_check(void *addr, size_t count, ompi_datatype_t *datatype)
{
if (!opal_memchecker_base_runindebugger() ||
(addr == NULL) || (count == 0) ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
size_t len = count*(datatype->super.true_ub - datatype->super.true_lb);
if ( OMPI_SUCCESS == opal_memchecker_base_unreg_mem_watch(addr, len) && memchecker_num_mem > 0) {
memchecker_num_mem--;
}
/* opal_output(0, "memchecker: number of mem: %d, read: %d; write: %d\n", memchecker_num_mem, read_cnt, write_cnt); */
return OMPI_SUCCESS;
}
static inline int memchecker_rw_enable_check()
{
memchecker_enable_check = true;
return OMPI_SUCCESS;
}
static inline int memchecker_rw_disable_check()
{
memchecker_enable_check = false;
return OMPI_SUCCESS;
}
static inline int memchecker_check_phase(int phase)
{
if (!opal_memchecker_base_runindebugger() ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
/* when changing to phase 0, we don't explicitly reset the bits. */
/* otherwise, communication is finished, reset all memory bits, */
if(phase == 1) {
unsigned int i;
memchecker_phase = phase;
if( memchecker_num_mem > 0 ) {
for( i = 0;i < memchecker_num_mem; i++ ) {
memset(memchecker_rw_check[i].rw_flag, 0, memchecker_rw_check[i].len*2);
}
}
}
return OMPI_SUCCESS;
}
static inline int memchecker_clear_mem_state(void *addr, size_t count, ompi_datatype_t *datatype)
{
if (!opal_memchecker_base_runindebugger() ||
(addr == NULL) || (count == 0) ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
/* opal_output(0, "memchecker warning: before clear state"); */
/* memchecker_rw_check_show_state(); */
size_t len = count*(datatype->super.true_ub - datatype->super.true_lb);
size_t index[10];
unsigned int i;
index[0]=-1;
if ( OMPI_SUCCESS != opal_memchecker_base_search_mem_index(addr, len, index) ) {
return -1;
}
if(index[0] == -1) {
/* opal_output(0, "memchecker warning: <clear mem state>"); */
/* opal_output(0, "memchecker warning: no memory entry found for address: %0x, with size %d.\n", addr, len); */
return OMPI_SUCCESS;
}
for(i = 0; index[i] != -1; i++) {
memset(memchecker_rw_check[i].rw_flag, 0, memchecker_rw_check[i].len*2);
}
/* opal_output(0, "memchecker warning: after clear state"); */
/* memchecker_rw_check_show_state(); */
return OMPI_SUCCESS;
}
/*
* set memory state with:
* 0: memory not readable
* 1: memory not writable
* 2: memory not accessable
*/
static inline int memchecker_set_mem_state(void *addr, size_t count, ompi_datatype_t *datatype, int mem_state)
{
if (!opal_memchecker_base_runindebugger() ||
(addr == NULL) || (count == 0) ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
size_t len = count*(datatype->super.true_ub - datatype->super.true_lb);
size_t index[10];
unsigned int i, j;
/* opal_output(0, "memchecker warning: before set state"); */
/* memchecker_rw_check_show_state(); */
index[0]=-1;
if ( OMPI_SUCCESS != opal_memchecker_base_search_mem_index(addr, len, index) ) {
return -1;
}
if(index[0] == -1) {
/* opal_output(0, "memchecker warning: <set mem state>"); */
/* opal_output(0, "memchecker warning: no memory entry found for address: %0x, with size %d.\n", addr, len); */
return OMPI_SUCCESS;
}
for(i = 0; index[i] != -1; i++) {
for(j = 0; j < memchecker_rw_check[i].len; j++) {
switch(mem_state) {
case MEMCHECKER_MEM_NOT_READABLE:
BIT_SET1(memchecker_rw_check[i].rw_flag, j*2);
break;
case MEMCHECKER_MEM_NOT_WRITABLE:
BIT_SET1(memchecker_rw_check[i].rw_flag, j*2+1);
break;
case MEMCHECKER_MEM_NOT_ACCESSABLE:
BIT_SET1(memchecker_rw_check[i].rw_flag, j*2);
BIT_SET1(memchecker_rw_check[i].rw_flag, j*2+1);
break;
default:
/* unknow state */
break;
}
}
}
/* opal_output(0, "memchecker warning: after set state"); */
/* memchecker_rw_check_show_state(); */
return OMPI_SUCCESS;
}
static inline int memchecker_rw_check_fini()
{
if (!opal_memchecker_base_runindebugger() ||
!memchecker_enable_check) {
return OMPI_SUCCESS;
}
unsigned int i, j, unused=0, wbr=0;
opal_output(0, "memchecker : <error summary>");
/* memchecker_rw_check_show_state(); */
/* loop through the registerred memory entries, check their flags */
for( i = 0;i < memchecker_num_mem;i++ ) {
for( j = 0; j < memchecker_rw_check[i].len; j++ ) {
/* check both bits */
if( !BIT_TEST(memchecker_rw_check[i].rw_flag, 2*j) ) {
/* performance issue: memory not used at all */
/* opal_output(0, "memchecker warning: buffer communicated but not used, sequence number: %d, offset: %d. %d\n", i, j, */
/* BIT_TEST(memchecker_rw_check[i].rw_flag, 2*j)); */
unused++;
}
/* check the error bit */
if( BIT_TEST(memchecker_rw_check[i].rw_flag, 2*j+1) ) {
/* performance issue: memory not used at all */
/* opal_output(0, "memchecker warning: the communicated buffer got WBR error, sequence number: %d, offset: %d.\n", i, j); */
wbr++;
}
}
}
opal_output(0, "memchecker : %d wbr errors, %d bytes communicated but not used.", wbr, unused);
/* Finally, unregister all memory entries */
opal_memchecker_base_unreg_all_mem_watch();
/* opal_output(0, "memchecker: number of mem: %d, read: %d; write: %d\n", memchecker_num_mem, read_cnt, write_cnt); */
return OMPI_SUCCESS;
}
#endif

Просмотреть файл

@ -37,6 +37,7 @@
#include "ompi/mca/pml/pml.h"
#include "ompi/peruse/peruse-internal.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#include "pml_ob1.h"
#include "pml_ob1_comm.h"
@ -209,6 +210,7 @@ void mca_pml_ob1_recv_frag_callback_match(mca_btl_base_module_t* btl,
match->req_recv.req_base.req_addr,
match->req_recv.req_base.req_count,
match->req_recv.req_base.req_datatype);
memchecker_rw_disable_check();
);
iov[0].iov_len = bytes_received;
@ -233,6 +235,7 @@ void mca_pml_ob1_recv_frag_callback_match(mca_btl_base_module_t* btl,
match->req_recv.req_base.req_addr,
match->req_recv.req_base.req_count,
match->req_recv.req_base.req_datatype);
memchecker_rw_enable_check();
);
}

Просмотреть файл

@ -1,4 +1,3 @@
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -37,6 +36,7 @@
#include "pml_ob1_recvreq.h"
#include "ompi/mca/bml/base/base.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
OBJ_CLASS_INSTANCE(mca_pml_ob1_send_range_t, ompi_free_list_item_t,
NULL, NULL);
@ -115,6 +115,9 @@ static int mca_pml_ob1_send_request_free(struct ompi_request_t** request)
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_unreg_mem_rw_check(sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
);
MCA_PML_OB1_SEND_REQUEST_RETURN( sendreq );
@ -517,6 +520,7 @@ int mca_pml_ob1_send_request_start_copy( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_disable_check();
);
(void)opal_convertor_pack( &sendreq->req_send.req_base.req_convertor,
&iov, &iov_count, &max_data );
@ -528,6 +532,7 @@ int mca_pml_ob1_send_request_start_copy( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_enable_check();
);
}
@ -583,7 +588,13 @@ int mca_pml_ob1_send_request_start_prepare( mca_pml_ob1_send_request_t* sendreq,
mca_btl_base_segment_t* segment;
mca_pml_ob1_hdr_t* hdr;
int rc;
MEMCHECKER(
memchecker_call(&opal_memchecker_base_mem_defined,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_disable_check();
);
/* prepare descriptor */
mca_bml_base_prepare_src( bml_btl,
NULL,
@ -593,6 +604,13 @@ int mca_pml_ob1_send_request_start_prepare( mca_pml_ob1_send_request_t* sendreq,
&size,
MCA_BTL_DES_FLAGS_PRIORITY | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP,
&des );
MEMCHECKER(
memchecker_call(&opal_memchecker_base_mem_noaccess,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_enable_check();
);
if( OPAL_UNLIKELY(NULL == des) ) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
@ -662,6 +680,7 @@ int mca_pml_ob1_send_request_start_rdma( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_disable_check();
);
/* prepare source descriptor/segment(s) */
/* PML owns this descriptor and will free it in */
@ -675,6 +694,7 @@ int mca_pml_ob1_send_request_start_rdma( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_enable_check();
);
if( OPAL_UNLIKELY(NULL == src) ) {
return OMPI_ERR_OUT_OF_RESOURCE;
@ -773,6 +793,7 @@ int mca_pml_ob1_send_request_start_rndv( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_disable_check();
);
mca_bml_base_prepare_src( bml_btl,
NULL,
@ -787,6 +808,7 @@ int mca_pml_ob1_send_request_start_rndv( mca_pml_ob1_send_request_t* sendreq,
sendreq->req_send.req_base.req_addr,
sendreq->req_send.req_base.req_count,
sendreq->req_send.req_base.req_datatype);
memchecker_rw_enable_check();
);
}

Просмотреть файл

@ -24,6 +24,7 @@
#include "ompi/errhandler/errhandler.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Bcast = PMPI_Bcast
@ -105,6 +106,10 @@ int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype,
OPAL_CR_ENTER_LIBRARY();
MEMCHECKER (
memchecker_check_phase(1);
memchecker_reg_mem_rw_check(buffer, count, datatype, MEMCHECKER_WATCH_WRITE);
);
/* Invoke the coll component to perform the back-end operation */
err = comm->c_coll.coll_bcast(buffer, count, datatype, root, comm,

Просмотреть файл

@ -21,6 +21,8 @@
#include "ompi/mpi/c/bindings.h"
#include "ompi/runtime/params.h"
#include "ompi/errhandler/errhandler.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Finalize = PMPI_Finalize
@ -37,6 +39,10 @@ int MPI_Finalize(void)
{
OPAL_CR_FINALIZE_LIBRARY();
MEMCHECKER(
memchecker_rw_check_fini();
);
if (MPI_PARAM_CHECK) {
OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
}

Просмотреть файл

@ -25,6 +25,7 @@
#include "ompi/mca/pml/pml.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Irecv = PMPI_Irecv
@ -75,6 +76,8 @@ int MPI_Irecv(void *buf, int count, MPI_Datatype type, int source,
MEMCHECKER (
memchecker_call(&opal_memchecker_base_mem_noaccess, buf, count, type);
memchecker_check_phase(0);
memchecker_reg_mem_rw_check(buf, count, type, MEMCHECKER_WATCH_RW);
);
rc = MCA_PML_CALL(irecv(buf,count,type,source,tag,comm,request));
OMPI_ERRHANDLER_RETURN(rc, comm, rc, FUNC_NAME);

Просмотреть файл

@ -26,6 +26,7 @@
#include "ompi/mca/pml/pml.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Isend = PMPI_Isend
@ -80,6 +81,8 @@ int MPI_Isend(void *buf, int count, MPI_Datatype type, int dest,
MEMCHECKER (
memchecker_call(&opal_memchecker_base_mem_noaccess, buf, count, type);
memchecker_check_phase(0);
memchecker_reg_mem_rw_check(buf, count, type, MEMCHECKER_WATCH_WRITE);
);
rc = MCA_PML_CALL(isend(buf,count,type,dest,tag,MCA_PML_BASE_SEND_STANDARD,comm,request));
OMPI_ERRHANDLER_RETURN(rc, comm, rc, FUNC_NAME);

Просмотреть файл

@ -10,9 +10,6 @@
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Los Alamos National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -63,17 +60,12 @@ int MPI_Testall(int count, MPI_Request requests[], int *flag,
}
}
}
if ((NULL == flag) || (count < 0)) {
if ((NULL == flag) || (0 > count)) {
rc = MPI_ERR_ARG;
}
OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME);
}
if (OPAL_UNLIKELY(0 == count)) {
*flag = true;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
if (OMPI_SUCCESS == ompi_request_test_all(count, requests, flag,

Просмотреть файл

@ -9,10 +9,7 @@
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
@ -40,7 +37,7 @@
static const char FUNC_NAME[] = "MPI_Testany";
int MPI_Testany(int count, MPI_Request requests[], int *indx, int *completed, MPI_Status *status)
int MPI_Testany(int count, MPI_Request requests[], int *index, int *completed, MPI_Status *status)
{
MEMCHECKER(
int j;
@ -62,24 +59,16 @@ int MPI_Testany(int count, MPI_Request requests[], int *indx, int *completed, MP
}
}
}
if (((NULL == indx || NULL == completed) && count > 0) ||
count < 0) {
if ((NULL == index) || (NULL == completed) || (0 > count)) {
rc = MPI_ERR_ARG;
}
OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME);
}
if (OPAL_UNLIKELY(0 == count)) {
*completed = true;
*indx = MPI_UNDEFINED;
*status = ompi_status_empty;
return MPI_SUCCESS;
}
OPAL_CR_ENTER_LIBRARY();
if (OMPI_SUCCESS == ompi_request_test_any(count, requests,
indx, completed, status)) {
index, completed, status)) {
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}

Просмотреть файл

@ -25,6 +25,7 @@
#include "ompi/errhandler/errhandler.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Wait = PMPI_Wait
@ -60,6 +61,7 @@ int MPI_Wait(MPI_Request *request, MPI_Status *status)
*/
MEMCHECKER(
opal_memchecker_base_mem_undefined(&status->MPI_ERROR, sizeof(int));
memchecker_check_phase(1);
);
}
return MPI_SUCCESS;
@ -73,13 +75,15 @@ int MPI_Wait(MPI_Request *request, MPI_Status *status)
*/
MEMCHECKER(
opal_memchecker_base_mem_undefined(&status->MPI_ERROR, sizeof(int));
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}
MEMCHECKER(
opal_memchecker_base_mem_undefined(&status->MPI_ERROR, sizeof(int));
opal_memchecker_base_mem_undefined(&status->MPI_ERROR, sizeof(int));
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return ompi_errhandler_request_invoke(1, request, FUNC_NAME);

Просмотреть файл

@ -27,6 +27,7 @@
#include "ompi/errhandler/errhandler.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Waitall = PMPI_Waitall
@ -74,10 +75,19 @@ int MPI_Waitall(int count, MPI_Request requests[], MPI_Status statuses[])
OPAL_CR_ENTER_LIBRARY();
if (OMPI_SUCCESS == ompi_request_wait_all(count, requests, statuses)) {
MEMCHECKER(
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}
MEMCHECKER(
memchecker_check_phase(1);
);
if (MPI_SUCCESS !=
ompi_errhandler_request_invoke(count, requests, FUNC_NAME)) {
OPAL_CR_EXIT_LIBRARY();

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -28,6 +30,7 @@
#include "ompi/errhandler/errhandler.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Waitany = PMPI_Waitany
@ -78,10 +81,19 @@ int MPI_Waitany(int count, MPI_Request requests[], int *indx, MPI_Status *status
OPAL_CR_ENTER_LIBRARY();
if (OMPI_SUCCESS == ompi_request_wait_any(count, requests, indx, status)) {
MEMCHECKER(
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}
MEMCHECKER(
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return ompi_errhandler_request_invoke(count, requests, FUNC_NAME);
}

Просмотреть файл

@ -1,3 +1,5 @@
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -28,6 +30,7 @@
#include "ompi/errhandler/errhandler.h"
#include "ompi/request/request.h"
#include "ompi/memchecker.h"
#include "ompi/memchecker_rw_check.h"
#if OPAL_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
#pragma weak MPI_Waitsome = PMPI_Waitsome
@ -80,6 +83,10 @@ int MPI_Waitsome(int incount, MPI_Request requests[],
if (OMPI_SUCCESS == ompi_request_wait_some( incount, requests,
outcount, indices, statuses )) {
MEMCHECKER(
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}
@ -90,6 +97,10 @@ int MPI_Waitsome(int incount, MPI_Request requests[],
return MPI_ERR_IN_STATUS;
}
MEMCHECKER(
memchecker_check_phase(1);
);
OPAL_CR_EXIT_LIBRARY();
return MPI_SUCCESS;
}

Просмотреть файл

@ -15,6 +15,7 @@
#include "opal_config.h"
#include "opal/mca/memchecker/memchecker.h"
#include "ompi/datatype/ompi_datatype.h"
/*
* Global functions for MCA overall memchecker open and close
@ -22,6 +23,14 @@
BEGIN_C_DECLS
OPAL_DECLSPEC extern memchecker_rw_check_t *memchecker_rw_check;
OPAL_DECLSPEC extern size_t memchecker_num_mem;
OPAL_DECLSPEC extern bool memchecker_enable_check;
OPAL_DECLSPEC extern int memchecker_phase;
/**
* Initialize the memchecker MCA framework
*
@ -287,7 +296,98 @@ OPAL_DECLSPEC int opal_memchecker_base_set_vbits(void * p, char * vbits, size_t
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_set_vbits(p, vbits, len)
#endif
/**
* Register memory watch
*
* @param p Pointer to the memory region
* @param len Length of the memory region
* @param op type of operation under watched
* @param cb callback function pointer
* @param info information returned from cb
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to register
* the memory region for specified operation.
*/
OPAL_DECLSPEC int opal_memchecker_base_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info);
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_reg_mem_watch(p, len, op, cb, info) 0
#endif
/**
* Unregister memory watch
*
* @param p Pointer to the memory region
* @param len Length of the memory region
* @param cb callback function pointer
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to unregister
* the memory watch.
*/
OPAL_DECLSPEC int opal_memchecker_base_unreg_mem_watch(void * p, size_t len);
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_unreg_mem_watch(p, len) 0
#endif
/**
* Unregister all memory watch
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to unregister
* all memory watch.
*/
OPAL_DECLSPEC int opal_memchecker_base_unreg_all_mem_watch();
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_unreg_all_mem_watch()
#endif
/**
* Search the entry index
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to search
* the entry index.
*/
OPAL_DECLSPEC int opal_memchecker_base_search_mem_index(void * p, size_t len, size_t *index);
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_search_mem_index(p, len, index) 0
#endif
/**
* Check mem watch count
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to get mem count
*/
OPAL_DECLSPEC int opal_memchecker_base_mem_watch_count();
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_mem_watch_count()
#endif
/**
* Print user application callstack
*
* @retval OPAL_SUCCESS upon success.
*
* This function calls the selected memchecker, to print
* user application callstack.
*/
OPAL_DECLSPEC int opal_memchecker_base_print_callstack();
#if OMPI_WANT_MEMCHECKER == 0
#define opal_memchecker_base_print_callstack()
#endif
END_C_DECLS
#endif /* OPAL_MEMCHECKER_BASE_H */

Просмотреть файл

@ -34,6 +34,12 @@ int opal_memchecker_base_output = -1;
bool opal_memchecker_base_components_opened_valid = false;
opal_list_t opal_memchecker_base_components_opened;
memchecker_rw_check_t *memchecker_rw_check;
size_t memchecker_num_mem = 0;
bool memchecker_enable_check = true;
int memchecker_phase = 0;
int callback_count = 0;
/*
* Function for finding and opening either all MCA components, or the one
* that was specifically requested via a MCA parameter.

Просмотреть файл

@ -85,4 +85,33 @@ int opal_memchecker_base_set_vbits(void * p, char * vbits, size_t len)
return opal_memchecker_base_module->set_vbits(p, vbits, len);
}
int opal_memchecker_base_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info)
{
return opal_memchecker_base_module->reg_mem_watch(p, len, op, cb, info);
}
int opal_memchecker_base_unreg_mem_watch(void * p, size_t len)
{
return opal_memchecker_base_module->unreg_mem_watch(p, len);
}
int opal_memchecker_base_unreg_all_mem_watch()
{
return opal_memchecker_base_module->unreg_all_mem_watch();
}
int opal_memchecker_base_search_mem_index(void * p, size_t len, size_t *index)
{
return opal_memchecker_base_module->search_mem_index(p, len, index);
}
int opal_memchecker_base_mem_watch_count()
{
return opal_memchecker_base_module->mem_watch_count();
}
int opal_memchecker_base_print_callstack()
{
return opal_memchecker_base_module->print_callstack();
}
#endif /* OMPI_WANT_MEMCHECKER */

Просмотреть файл

@ -38,6 +38,15 @@
#include "opal/mca/mca.h"
#include "opal/mca/base/base.h"
#include "ompi/datatype/ompi_datatype.h"
/* basic type for memory rw check */
typedef struct {
void *addr; /* starting address of the memory region */
size_t len; /* size of the memory */
char *rw_flag; /* read/write (R/W) bit flag */
ompi_datatype_t *datatype; /* MPI datatype */
} memchecker_rw_check_t;
/**
* Module initialization function. Should return OPAL_SUCCESS.
@ -105,6 +114,36 @@ typedef int (*opal_memchecker_base_module_get_vbits_fn_t)(void * p, char * vbits
*/
typedef int (*opal_memchecker_base_module_set_vbits_fn_t)(void * p, char * vbits, size_t len);
/**
* Module function to register watch memory
*/
typedef int (*opal_memchecker_base_module_reg_mem_watch_fn_t)(void * p, size_t len, int op, void *cb, void *info);
/**
* Module function to unregister watch memory
*/
typedef int (*opal_memchecker_base_module_unreg_mem_watch_fn_t)(void * p, size_t len);
/**
* Module function to unregister all watch memory
*/
typedef int (*opal_memchecker_base_module_unreg_all_mem_watch_fn_t)();
/**
* Module function to search memory entry index
*/
typedef int (*opal_memchecker_base_module_search_mem_index_fn_t)(void * p, size_t len, size_t *index);
/**
* Module function to get memory count
*/
typedef int (*opal_memchecker_base_module_mem_watch_count_fn_t)();
/**
* Module function to print callstack
*/
typedef int (*opal_memchecker_base_module_print_callstack_fn_t)();
/**
@ -159,12 +198,30 @@ struct opal_memchecker_base_module_1_0_0_t {
/** Module function to check for any leaks */
opal_memchecker_base_module_leakcheck_fn_t leakcheck;
/** Module function to get vbits */
opal_memchecker_base_module_get_vbits_fn_t get_vbits;
/** Module function to set vbits */
opal_memchecker_base_module_set_vbits_fn_t set_vbits;
/** Module function to register memory watch */
opal_memchecker_base_module_reg_mem_watch_fn_t reg_mem_watch;
/** Module function to unregister memory watch */
opal_memchecker_base_module_unreg_mem_watch_fn_t unreg_mem_watch;
/** Module function to unregister all memory watch */
opal_memchecker_base_module_unreg_all_mem_watch_fn_t unreg_all_mem_watch;
/** Module function to unregister all memory watch */
opal_memchecker_base_module_search_mem_index_fn_t search_mem_index;
/** Module function to get memory count */
opal_memchecker_base_module_mem_watch_count_fn_t mem_watch_count;
/** Module function to print callstack */
opal_memchecker_base_module_print_callstack_fn_t print_callstack;
};
/**

10
opal/mca/memchecker/mempin/.windows Обычный файл
Просмотреть файл

@ -0,0 +1,10 @@
#
# Copyright (c) 2008 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#

41
opal/mca/memchecker/mempin/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,41 @@
#
# Copyright (c) 2011 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AM_CPPFLAGS = $(opal_memchecker_pin_CPPFLAGS)
sources = \
.windows \
memchecker_pin.h \
memchecker_pin_component.c \
memchecker_pin_module.c \
MemPin.cpp \
MemPin.h
# Make the output library in this directory, and name it either
# mca_<type>_<name>.la (for DSO builds) or libmca_<type>_<name>.la
# (for static builds).
if MCA_BUILD_opal_memchecker_pin_DSO
component_noinst =
component_install = mca_memchecker_pin.la
else
component_noinst = libmca_memchecker_pin.la
component_install =
endif
mcacomponentdir = $(libdir)/openmpi
mcacomponent_LTLIBRARIES = $(component_install)
mca_memchecker_pin_la_SOURCES = $(sources)
mca_memchecker_pin_la_LDFLAGS = -module -avoid-version
mca_memchecker_pin_la_LIBADD = \
$(top_ompi_builddir)/opal/libopal.la
noinst_LTLIBRARIES = $(component_noinst)
libmca_memchecker_pin_la_SOURCES =$(sources)
libmca_memchecker_pin_la_LDFLAGS = -module -avoid-version

732
opal/mca/memchecker/mempin/MemPin.cpp Обычный файл
Просмотреть файл

@ -0,0 +1,732 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <assert.h>
#include <stdarg.h>
#include "pin.H"
#include "instlib.H"
#include "portability.H"
#include "MemPin.h"
using namespace INSTLIB;
typedef struct {
size_t index; /* index of the element */
size_t addr; /* the registered mem address */
size_t size; /* size of the memory */
int op; /* memory operation */
MEMPIN_REG_CB_T cb_func; /* callback function pointer */
void* cb_args; /* list of callback function args */
} addr_range_t;
// the key of the maps is start address of each entry
// the second element stores the whole structure
multimap<size_t, addr_range_t> addr_map, result_map;
// declaration of a function
//int search_engine_no_overlap(addr, size);
// global variables
/* ===================================================================== */
/* Commandline Switches */
/* ===================================================================== */
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "outfile", "", "Specify output file name");
KNOB<int> KnobDebugLevel(KNOB_MODE_WRITEONCE, "pintool", "debug-level", "1", "Only log debug output lower than level.\n\tlevel 0: standard non-debug output (default);\tlevel 1: output with source location info;\n\tlevel 2: output with application callstack;\n\tlevel 3: all debug info.");
KNOB<string> KnobDebugFile(KNOB_MODE_WRITEONCE, "pintool", "debug-file", "stdout", "Specify output file name for debug output");
KNOB<BOOL> KnobPid(KNOB_MODE_WRITEONCE, "pintool", "pid", "0", "Append PID to output files");
LOCALVAR int it_count = 0; // iteration counts, for debug only
LOCALVAR bool main_rtn_instrumented = FALSE;
LOCALVAR BOOL start_trace_callstack = FALSE; // at which point shall we start tracing callstacks
// define the callstack
LOCALVAR std::vector<ADDRINT> callstack;
LOCALVAR int stack_depth = 0;
LOCALFUN VOID Handler(CONTROL_EVENT ev, VOID *, CONTEXT *, VOID *, THREADID tid)
{
switch(ev)
{
case CONTROL_START:
start_trace_callstack = TRUE;
break;
case CONTROL_STOP:
start_trace_callstack = FALSE;
break;
default:
ASSERTX(false);
}
}
LOCALVAR CONTROL control;
// output streams
LOCALVAR ostream *Output;
LOCALVAR ostream *OutputDebug;
///////////////////////// Utility functions ///////////////////////////////////
VOID mempin_log(int debug_level, const char *format, ...)
{
#define MEMPIN_BUFFER_LEN 1024
va_list arglist;
char s[MEMPIN_BUFFER_LEN];
va_start(arglist, format);
vsnprintf(s, MEMPIN_BUFFER_LEN, format, arglist);
va_end(arglist);
if (0 == debug_level) {
*Output << "== <MemPin> [" << getpid_portable() << ":" << PIN_ThreadId() << "] == " << s << flush;
} else if(debug_level <= KnobDebugLevel.Value()) {
*OutputDebug << "== <MemPin Debug " << debug_level << "> [" << getpid_portable() << ":" << PIN_ThreadId() << "] == " << s << flush;
}
}
/*
* Search through the entry map,
* returns the number of the matched entries.
* Overlapping or duplicated entries are not allowed.
*/
int search_engine_no_overlap(size_t addr, int size)
{
if(addr_map.size() == 0) {
return 0;
}
// the first element of the map could be start, end address or entry id
// the second element stores the whole entry
multimap<size_t, addr_range_t>::iterator it, it_start, it_end;
int found=0;
result_map.clear();
it_start = addr_map.lower_bound(addr);
it_end = addr_map.upper_bound(addr+size);
// extend one more element for searching
if( it_start != addr_map.begin() ) {
it_start--;
}
// don't touch the 'end' element
if( it_end == addr_map.end() ) {
it_end--;
}
for( ; ( (*it_start).first <= (*it_end).first ) && ( it_start != addr_map.end() ) ; it_start++ ){
// insert the found items into the new map
if( addr < (*it_start).second.addr+(*it_start).second.size &&
addr+size > (*it_start).second.addr ) {
result_map.insert(pair<int, addr_range_t>( (*it_start) ));
found++;
}
it_count++;
}
mempin_log(3, "search_engine_no_overlap: number of iterations: %d\n", it_count);
return found;
}
/*
* Return the index of the matched entries.
* The caller must allocate a size_t array in the applicatioin.
*/
VOID mempin_search_mem_index(ADDRINT ip, size_t addr, int size, size_t *index)
{
unsigned int i;
/* set the end flag */
index[result_map.size()] = -1;
if(addr_map.size() == 0) {
return;
}
search_engine_no_overlap(addr, size);
if(result_map.size() == 0 || index == NULL) {
return;
}
multimap<size_t, addr_range_t>::iterator it = result_map.begin();
for(i = 0; i < result_map.size(); i++ ) {
index[i] = (*it).second.index;
it++;
}
}
VOID mempin_print_source(int debug_level, ADDRINT ip)
{
INT32 column=0, line=0;
string filename, rtn_name;
PIN_LockClient();
PIN_GetSourceLocation(ip, &column, &line, &filename);
PIN_UnlockClient();
rtn_name.append(RTN_FindNameByAddress(ip));
mempin_log(debug_level, "<%s> %s:%d,%d\n", rtn_name.c_str(), filename.c_str(), line, column);
}
/*
* print the current callstack of the application.
* @params:
* ip: the current instruction address
* depth: the lines should be printed in the callstack
* 0 means print all.
*/
VOID mempin_print_callstack(int debug_level, ADDRINT ip, int depth)
{
if(depth == 0) {
return;
}
if( debug_level <= KnobDebugLevel.Value() ) {
callstack.push_back(ip);
mempin_log (debug_level, "**** application callstack ****\n");
vector<ADDRINT>::iterator it;
it = callstack.end();
it--;
do {
INT32 column=0, line=0;
string filename, rtn_name;
PIN_LockClient();
PIN_GetSourceLocation(*it, &column, &line, &filename);
PIN_UnlockClient();
rtn_name.append(RTN_FindNameByAddress(*it));
mempin_log(debug_level, "<%s> %s:%d,%d\n", rtn_name.c_str(), filename.c_str(), line, column);
if( !strcmp(rtn_name.c_str(), "main") ) {
break;
}
} while(it-- != callstack.begin() || !depth--);
callstack.pop_back();
} else {
mempin_log (1, "**** application source ****\n");
mempin_print_source(1, ip);
}
}
VOID callstack_push(ADDRINT ip, ADDRINT sp)
{
if(start_trace_callstack &&
1 < KnobDebugLevel.Value()) {
callstack.push_back(ip);
stack_depth++;
}
}
VOID callstack_pop()
{
if(start_trace_callstack && callstack.size() > 0 &&
1 <= KnobDebugLevel.Value()) {
callstack.pop_back();
stack_depth--;
}
}
int mempin_mem_watch_count()
{
int count = addr_map.size();
mempin_log (1, "Number of watched memory: %d\n", count);
return count;
}
/*
* Register the memory entry.
*/
VOID mempin_reg_mem(ADDRINT ip, VOID* addr, size_t size, int op, MEMPIN_REG_CB_T cb_func, VOID* cb_args)
{
assert(addr != NULL);
assert(size > 0);
assert(op >= 0);
assert(cb_func != NULL);
/* make sure no duplicated entries */
if( search_engine_no_overlap((size_t)addr, size) > 0 ){
mempin_log(1, "reg dup mem (ignored): %0x, %d, %d, %0x, %0x\n\n",
(size_t)addr, size, op, cb_func, cb_args);
return;
}
size_t index = addr_map.size();
mempin_log(1, "reg mem: %0x, %d, %d, %0x, %0x\n\n",
(size_t)addr, size, op, cb_func, cb_args);
mempin_print_callstack(2, ip, 100);
addr_range_t entry = {index, (size_t)addr, size, op, cb_func, cb_args};
addr_map.insert(pair<int, addr_range_t>(entry.addr, entry));
mempin_log(1, "number of watched mem entries: %d\n\n", addr_map.size());
}
/*
* Unregister the memory entry.
*/
VOID mempin_unreg_mem(ADDRINT ip, VOID* addr, int size)
{
assert(addr != NULL);
assert(size > 0);
if(addr_map.size() == 0) {
return;
}
mempin_log(1, "unreg memory: %0x, %d\n", (size_t)addr, size);
mempin_print_callstack(2, ip, 100);
if(addr_map.erase((size_t)addr) <= 0){
mempin_log(1, "map erase error: %0x, %d\n", (size_t)addr, size);
}
mempin_log(1, "number of watched mem entries: %d\n\n", addr_map.size());
}
/*
* Unregister all the memory entry.
*/
VOID mempin_unreg_mem_all(ADDRINT ip)
{
if(addr_map.size() == 0) {
return;
}
mempin_log(1, "unreg all memory\n");
mempin_print_callstack(2, ip, 100);
addr_map.clear();
mempin_log(1, "number of watched mem entries: %d\n\n", addr_map.size());
}
/*
* Check whether the address is in the map,
* if yes, do the callback.
*/
VOID mem_cb(ADDRINT ip, VOID * addr, int size, int op)
{
//mempin_log(1, "%0x\n",(size_t)addr);
if( search_engine_no_overlap((size_t)addr, size) > 0 ){
multimap<size_t, addr_range_t>::iterator it;
size_t result_size, offset;
for(it = result_map.begin(); it != result_map.end(); it++){
// check if it's the operation that we are watching
if( ((op+1) & ((*it).second.op+1)) > 0 ) {
// mempin_log(1, "!!!! %d matched entry found from source: %0x,%d (%d) \n",
// result_map.size(), addr, size, op);
// mempin_print_callstack(1, ip, 100);
offset = (*it).second.addr - (size_t) addr;
if( (size_t) addr <= (*it).second.addr ){
if ( (((size_t)addr+size) < ((*it).second.addr+(*it).second.size)) ){
result_size = size - offset; // or addr + size - (*it).second.addr
} else {
result_size = (*it).second.size;
}
} else {
if ( ((size_t)addr+size) > ((*it).second.addr+(*it).second.size) ){
result_size = (*it).second.size + offset; // size - ( (a+size) - ((*it).second.addr+(*it).second.size) )
} else {
result_size = size;
}
}
// trigger the callback & check for the alignment of the memory address
int ret = (*((MEMPIN_REG_CB_T)((*it).second.cb_func)))( addr, result_size, offset, op, (*it).second.cb_args, (void*)ip );
switch(ret) {
case MEMPIN_CALLBACK_PRINT_CALLSTACK_1 :
case MEMPIN_CALLBACK_PRINT_CALLSTACK_2 :
case MEMPIN_CALLBACK_PRINT_CALLSTACK_3 :
case MEMPIN_CALLBACK_PRINT_CALLSTACK_4 :
case MEMPIN_CALLBACK_PRINT_CALLSTACK_5 :
case MEMPIN_CALLBACK_PRINT_CALLSTACK_ALL:
mempin_print_callstack(1, ip, ret);
break;
/* More options could be added here. */
default:
break;
}
}
}
}
}
/* tell the application that it's running with pin */
VOID mempin_running_with_pin(ADDRINT ip, int *pin_alive)
{
mempin_log (3, "mempin_running_with_pin ip:%p pin_alive:%p\n", (void*) ip, pin_alive);
*pin_alive = 1;
}
static BOOL IsPLT(TRACE trace)
{
RTN rtn = TRACE_Rtn(trace);
// All .plt thunks have a valid RTN
if (!RTN_Valid(rtn))
return FALSE;
if (".plt" == SEC_Name(RTN_Sec(rtn)))
return TRUE;
return FALSE;
}
/*
* The main trace routine.
* Checks all memory reads and writes.
* Determine where we should get a callstack item.
*/
static void mempin_trace(TRACE trace, void *v)
{
for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
INS tail = BBL_InsTail(bbl);
// All memory reads/writes
for( INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins) ) {
// instrument the instructions
// Instruments memory accesses using a predicated call, i.e.
// the instrumentation is called iff the instruction will actually be executed.
//
// The IA-64 architecture has explicitly predicated instructions.
// On the IA-32 and Intel(R) 64 architectures conditional moves and REP
// prefixed instructions appear as predicated instructions in Pin.
UINT32 memOperands = INS_MemoryOperandCount(ins);
// Iterate over each memory operand of the instruction.
for (UINT32 memOp = 0; memOp < memOperands; memOp++)
{
if (INS_MemoryOperandIsRead(ins, memOp))
{
int size = INS_MemoryReadSize(ins);
INS_InsertCall(
ins, IPOINT_BEFORE, (AFUNPTR)mem_cb,
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_UINT32, size,
IARG_UINT32, MEMPIN_WATCH_READ,
IARG_END);
}
// Note that in some architectures a single memory operand can be
// both read and written (for instance incl (%eax) on IA-32)
// In that case we instrument it once for read and once for write.
if (INS_MemoryOperandIsWritten(ins, memOp))
{
int size = INS_MemoryReadSize(ins);
INS_InsertCall(
ins, IPOINT_BEFORE, (AFUNPTR)mem_cb,
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_UINT32, size,
IARG_UINT32, MEMPIN_WATCH_WRITE,
IARG_END);
}
}
}
if (2 < KnobDebugLevel.Value()) {
// All calls and returns
if( !INS_IsSyscall(tail) ) {
if( INS_IsCall(tail) ) {
if( INS_IsDirectBranchOrCall(tail) ) {
ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail);
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
(AFUNPTR)callstack_push,
IARG_INST_PTR,
IARG_ADDRINT, target,
IARG_REG_VALUE, REG_STACK_PTR,
IARG_END);
} else if( !IsPLT(trace) ) {
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
(AFUNPTR)callstack_push,
IARG_INST_PTR,
IARG_BRANCH_TARGET_ADDR,
IARG_REG_VALUE, REG_STACK_PTR,
IARG_END);
}
}
if( IsPLT(trace) ) {
INS_InsertCall(tail, IPOINT_BEFORE,
(AFUNPTR)callstack_push,
IARG_INST_PTR,
IARG_BRANCH_TARGET_ADDR,
IARG_REG_VALUE, REG_STACK_PTR,
IARG_END);
}
if( INS_IsRet(tail) ) {
INS_InsertCall(tail, IPOINT_BEFORE,
(AFUNPTR)callstack_pop,
IARG_INST_PTR,
IARG_REG_VALUE, REG_STACK_PTR,
IARG_END);
}
}
}
}
}
VOID mempin_main(ADDRINT ip, ADDRINT target, ADDRINT sp)
{
start_trace_callstack = TRUE;
callstack.clear();
}
static void
mempin_image_load(IMG img, void *v)
{
RTN rtn;
mempin_log (3, "mempin_image_load: IMG_Name: %s\n", IMG_Name(img).c_str());
if( !main_rtn_instrumented && IMG_IsMainExecutable(img)) {
rtn = RTN_FindByName(img, "main");
if( rtn == RTN_Invalid() ) {
rtn = RTN_FindByName(img, "_main");
} else if( rtn == RTN_Invalid() ) {
rtn = RTN_FindByName(img, "__libc_start_main@plt");
} else if( rtn == RTN_Invalid() ) {
rtn = RTN_FindByName(img, "__libc_start_main");
} else if ( rtn == RTN_Invalid() ) {
mempin_log (0, "Pin error in mempin_image_load\n");
exit (-1);
}
mempin_log (3, "mempin_image_load: main found in main executable RTN_name:%s\n",
RTN_Name(rtn).c_str());
main_rtn_instrumented = TRUE;
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE,
(AFUNPTR)mempin_main,
IARG_INST_PTR,
IARG_ADDRINT, RTN_Address(rtn),
IARG_REG_VALUE, REG_STACK_PTR,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_REG_MEM_WATCH");
if( rtn != RTN_Invalid() ) {
RTN_Open(rtn);
mempin_log (3, "mempin_image_load: MEMPIN_REG_MEM_WATCH found\n");
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_reg_mem,
IARG_INST_PTR,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_UNREG_MEM_WATCH");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_UNREG_MEM_WATCH found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_unreg_mem,
IARG_INST_PTR,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_UNREG_ALL_MEM_WATCH");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_UNREG_ALL_MEM_WATCH found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_unreg_mem_all,
IARG_INST_PTR,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_SEARCH_MEM_INDEX");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_SEARCH_MEM_INDEX found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_search_mem_index,
IARG_INST_PTR,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_RUNNING_WITH_PIN");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_RUNNING_WITH_PIN found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)mempin_running_with_pin,
IARG_INST_PTR,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_MEM_WATCH_COUNT");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_MEM_WACH_COUNT found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_mem_watch_count,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_PRINT_CALLSTACK");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_PRINT_CALLSTACK found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_print_callstack,
IARG_BOOL, FALSE,
IARG_INST_PTR,
IARG_UINT32, 0,
IARG_END);
RTN_Close(rtn);
}
rtn = RTN_FindByName(img, "MEMPIN_DEBUG_LOG");
if( rtn != RTN_Invalid() ) {
mempin_log (3, "mempin_image_load: MEMPIN_DEBUG_LOG found\n");
RTN_Open(rtn);
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)mempin_log,
IARG_BOOL, FALSE,
IARG_INST_PTR,
IARG_UINT32, 0,
IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
IARG_END);
RTN_Close(rtn);
}
// more MEMPIN functions needs to be instrumented
// e.g. MEMPIN_MEM_NOACCESS, MEMPIN_MEM_DEFINED etc.
}
/*
* Finalize Pin
*/
VOID Fini(INT32 code, VOID *v)
{
mempin_log(2, "Fini called");
}
/*
* Print Help Message
*/
INT32 Usage()
{
cerr <<
"This pin tool implements a call-back mechanism to discover reads&writes to registered memory.\n"
"\n";
cerr << KNOB_BASE::StringKnobSummary();
cerr << endl;
return -1;
}
/*
* Main
*/
int main(int argc, char * argv[])
{
int ret;
string filename;
// Default settings
Output = &std::cout;
OutputDebug = Output;
// Initialize pin
ret = PIN_Init(argc, argv);
if (ret) {
return Usage();
}
PIN_InitSymbols();
// process command line args
control.CheckKnobs(Handler, 0);
filename = KnobOutputFile.Value();
if (0 != filename.length()) {
if( KnobPid.Value() ) {
filename += "." + decstr( getpid_portable() );
}
Output = new ofstream (filename.c_str());
}
if (0 < KnobDebugLevel.Value()) {
filename = KnobDebugFile.Value();
if (0 != filename.length()) {
if (KnobPid.Value()) {
filename += "." + decstr( getpid_portable() );
}
OutputDebug = new ofstream (filename.c_str());
}
}
IMG_AddInstrumentFunction(mempin_image_load, 0);
TRACE_AddInstrumentFunction(mempin_trace, 0);
// Register Fini to be called when the application exits
PIN_AddFiniFunction(Fini, 0);
// Start the program, never returns
PIN_StartProgram();
return 0;
}

97
opal/mca/memchecker/mempin/MemPin.h Обычный файл
Просмотреть файл

@ -0,0 +1,97 @@
#ifndef __MEMPIN_H__
#define __MEMPIN_H__
#include <stddef.h>
/* mem watch types */
#define MEMPIN_WATCH_READ 0
#define MEMPIN_WATCH_WRITE 1
#define MEMPIN_WATCH_RW 2
/* callback return value operation */
#define MEMPIN_CALLBACK_NULL 0
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_1 1
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_2 2
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_3 3
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_4 4
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_5 5
#define MEMPIN_CALLBACK_PRINT_CALLSTACK_ALL 100
/* XXX define more return callback options */
/* XXX this should be replaced with a proper check or configure/cmake-based */
#ifdef __GNUC__
#define mp_unused __attribute__((unused)) /* get rid of compiler warnings */
#define mp_weak __attribute__((weak)) /* try to have multiple local versions being replaced */
#else
#define mp_unused
#define mp_weak
#endif
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/* Format of reg/unreg functions:
* mempin_reg_mem(addr, size, watch_type, cb_func, cb_args);
* MEMPIN_REG_MEM_WATCH(void* addr,
* int size,
* int op,
* void* cb_func, -- of type mempin_reg_cb_t
* void* cb_args);
* mempin_unreg_mem(addr, size);
* !!!! These can NOT be used in callbacks from MemPin !!!!
*
* Format of the callback functions is:
* int MEMPIN_REG_CB_T(
* void * addr,
* size_t size,
* int offset,
* int is_write,
* void * cb_info,
* void * ip);
* Return value:
* The return value selects the action in the MemPin Tool:
* MEMPIN_CALLBACK_NULL
* MEMPIN_CALLBACK_PRINT_CALLSTACK_1
* and so on (see above)
*/
typedef int (*MEMPIN_REG_CB_T)(void*, size_t, int, int, void*, void*);
volatile static int MEMPIN_hardcode = 42;
void MEMPIN_RUNNING_WITH_PIN(int *pin_alive) mp_unused mp_weak;
void MEMPIN_RUNNING_WITH_PIN(int *pin_alive)
{if (NULL != pin_alive) *pin_alive = MEMPIN_hardcode;}
void MEMPIN_REG_MEM_WATCH(const void* addr mp_unused, int size mp_unused, int op mp_unused, MEMPIN_REG_CB_T cb_func mp_unused, void * cb_args mp_unused) mp_unused mp_weak;
void MEMPIN_REG_MEM_WATCH(const void* addr, int size, int op, MEMPIN_REG_CB_T cb_func, void* cb_args)
{}
void MEMPIN_UNREG_MEM_WATCH(const void* addr mp_unused, int size mp_unused) mp_unused mp_weak;
void MEMPIN_UNREG_MEM_WATCH(const void* addr, int size)
{}
void MEMPIN_UNREG_ALL_MEM_WATCH(void) mp_unused mp_weak;
void MEMPIN_UNREG_ALL_MEM_WATCH(void)
{}
void MEMPIN_SEARCH_MEM_INDEX(const void* addr mp_unused, int size mp_unused, size_t *index mp_unused) mp_unused mp_weak;
void MEMPIN_SEARCH_MEM_INDEX(const void* addr, int size, size_t *index)
{}
int MEMPIN_MEM_WATCH_COUNT(void) mp_unused mp_weak;
int MEMPIN_MEM_WATCH_COUNT(void)
{return MEMPIN_hardcode;}
void MEMPIN_PRINT_CALLSTACK(void) mp_unused mp_weak;
void MEMPIN_PRINT_CALLSTACK(void)
{}
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
#endif /* __MEMPIN_H__ */

55
opal/mca/memchecker/mempin/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,55 @@
# -*- shell-script -*-
#
# Copyright (c) 2011 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_DEFUN([MCA_opal_memchecker_pin_PRIORITY], [10])
AC_DEFUN([MCA_opal_memchecker_pin_COMPILE_MODE], [
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
$4="static"
AC_MSG_RESULT([$$4])
])
# MCA_memchecker_pin_CONFIG([action-if-found], [action-if-not-found])
# -----------------------------------------------------------
AC_DEFUN([MCA_opal_memchecker_pin_CONFIG],[
AC_CONFIG_FILES([opal/mca/memchecker/pin/Makefile])
OPAL_VAR_SCOPE_PUSH([opal_memchecker_pin_save_CPPFLAGS opal_memchecker_pin_happy opal_memchecker_pin_CPPFLAGS])
AC_ARG_WITH([pin],
[AC_HELP_STRING([--with-pin(=DIR)],
[Root directory where the Intel Pin framework is installed])])
OMPI_CHECK_WITHDIR([valgrind], [$with_valgrind], [include/valgrind/valgrind.h])
# look for Intel Pin
AS_IF([test "$with_pin" != "no"],
[AS_IF([test ! -z "$with_pin" -a "$with_pin" != "yes"],
[opal_memchecker_pin_CPPFLAGS="-I$with_pin/include"
# We need this -I to stay in CPPFLAGS when we're done
CPPFLAGS="$CPPFLAGS -I$with_pin/include"
opal_memchecker_pin_save_CPPFLAGS=$CPPFLAGS])
AC_CHECK_HEADERS([source/pin.H],
[
# FixME: if the header is found, then just compile MemPin tool
,
],
[AC_MSG_WARN([pin.H not found])
AC_MSG_WARN([Compile this component without the MemPin tool])])])
CPPFLAGS="$opal_memchecker_pin_save_CPPFLAGS"
# if Intel Pin framework is not found, we can still build the component.
[$1]
AC_SUBST([opal_memchecker_pin_CPPFLAGS])
OPAL_VAR_SCOPE_POP
])dnl

85
opal/mca/memchecker/mempin/example/test.cpp Обычный файл
Просмотреть файл

@ -0,0 +1,85 @@
#include <stdio.h>
#ifdef WIN32
# include <windows.h>
#endif
#include "MemPin.h"
int read_count = 0, write_count = 0;
int n[5];
#define BIT_SET(a,b) ((a) |= (1<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
#define BITS_PER_BYTE 8
#define SET_BIT(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] |= (1<<((pos)%BITS_PER_BYTE)))
#define CLEAR_BIT(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] &= ~(1<<((pos)%BITS_PER_BYTE)))
#define TEST_BIT(bitmap, pos) (bitmap[(pos)/BITS_PER_BYTE] & (1<<((pos)%BITS_PER_BYTE)))
int read_cb(void* addr, size_t size, int offset, int is_write, void* cb_info, void* ip)
{
int int_size = size;
printf("ip:%p is_write:%d size:%d offset:%d\n", ip, is_write, int_size, offset);
if (is_write)
write_count++;
else
read_count++;
return MEMPIN_CALLBACK_PRINT_CALLSTACK_5;
}
void func3()
{
int test;
printf("read n: %p %d\n", n, n[2]); //read
test = n[2]; //read
test = n[0]; //read
n[4] = 19+test; //write
}
void func2()
{
func3();
}
void func1()
{
func2();
}
int main()
{
int is_in_pin = 0;
size_t index[10];
unsigned int i;
for(i=0; i < sizeof(n)/sizeof(n[0]); i++) {
n[i]=i;
}
// check whether we are in Pin
MEMPIN_RUNNING_WITH_PIN(&is_in_pin);
if (is_in_pin) {
printf("we are running with pin! \n");
} else {
printf("we are not running with pin! \n");
}
MEMPIN_REG_MEM_WATCH(n, 5*sizeof(int), MEMPIN_WATCH_RW, read_cb, NULL);
func1();
// example how to use MEMPIN_SEARCH_MEM_INDEX
MEMPIN_SEARCH_MEM_INDEX(n, 5*sizeof(int), index);
printf("index %ld, %ld\n", index[0], index[1]);
//printf("index %0x: %d, %d \n", index, index[0], index[1]);
MEMPIN_UNREG_MEM_WATCH(n, 5*sizeof(int));
printf("memory reads %d time(s).\n", read_count);
printf("memory writes %d time(s).\n", write_count);
return 0;
}

61
opal/mca/memchecker/mempin/memchecker_pin.h Обычный файл
Просмотреть файл

@ -0,0 +1,61 @@
/*
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2008 The Trustees of Indiana University.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* @file
*
* This should be described well
*/
#ifndef MCA_MEMCHECKER_PIN_EXPORT_H
#define MCA_MEMCHECKER_PIN_EXPORT_H
#include "opal_config.h"
#include "opal/mca/mca.h"
#include "opal/mca/memchecker/memchecker.h"
BEGIN_C_DECLS
/**
* Globally exported variable
*/
OPAL_DECLSPEC extern const opal_memchecker_base_component_2_0_0_t
mca_memchecker_pin_component;
/**
* memchecker query API function
*
* Query function for memchecker components. Simply returns a priority
* to rank it against other available memchecker components (assumedly,
* only one component will be available per platform, but it's
* possible that there could be more than one available).
*/
int opal_memchecker_pin_component_query(mca_base_module_t **module, int *priority);
OPAL_DECLSPEC int MEMPIN_RUNNING_WITH_PIN(int *pin_alive);
OPAL_DECLSPEC int MEMPIN_REG_MEM_WATCH(void* addr, int size, int op, void * cb_func, void* cb_args);
OPAL_DECLSPEC int MEMPIN_UNREG_MEM_WATCH(void* addr, int size);
OPAL_DECLSPEC int MEMPIN_UNREG_ALL_MEM_WATCH();
OPAL_DECLSPEC int MEMPIN_SEARCH_MEM_INDEX(void* addr, int size, size_t *index);
OPAL_DECLSPEC int MEMPIN_MEM_WATCH_COUNT();
OPAL_DECLSPEC int MEMPIN_PRINT_CALLSTACK();
END_C_DECLS
#endif /* MCA_MEMCHECKER_PIN_EXPORT_H */

Просмотреть файл

@ -0,0 +1,95 @@
/*
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2008 The Trustees of Indiana University.
* All rights reserved.
*
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* These symbols are in a file by themselves to provide nice linker
* semantics. Since linkers generally pull in symbols by object
* files, keeping these symbols as the only symbols in this file
* prevents utility programs such as "ompi_info" from having to import
* entire components just to query their version and parameters.
*/
#include "opal_config.h"
#include "opal/constants.h"
#include "opal/mca/memchecker/memchecker.h"
#include "memchecker_pin.h"
/*
* Public string showing the memchecker ompi_linux component version number
*/
const char *opal_memchecker_pin_component_version_string =
"OPAL pin memchecker MCA component version " OPAL_VERSION;
/*
* Local function
*/
static int pin_open(void);
static int pin_close(void);
/*
* Instantiate the public struct with all of our public information
* and pointers to our public functions in it
*/
const opal_memchecker_base_component_2_0_0_t mca_memchecker_pin_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
OPAL_MEMCHECKER_BASE_VERSION_2_0_0,
/* Component name and version */
"pin",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
pin_open,
pin_close,
opal_memchecker_pin_component_query
},
{
/* pin does not offer functionality to save the state */
MCA_BASE_METADATA_PARAM_CHECKPOINT
}
};
static int pin_open(void)
{
/*
* Any initialization of pin upon starting of the component
* should be done here.
*
* Possibilities are, that we need to set special stuff, when
* pin is not being run / actually is being run.
*/
return OPAL_SUCCESS;
}
static int pin_close(void)
{
/*
* Any closing of pin upon starting of the component
* should be done here.
*
* Possibilities are, that we need to set special stuff, when
* pin is not being run / actually is being run.
*/
return OPAL_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,316 @@
/*
* Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2008 The Trustees of Indiana University.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
/**
* @file
*
* memchecker (memory checker) pin framework component interface.
*
* Intent
*/
#include "opal_config.h"
#include "opal/constants.h"
#include "opal/mca/base/mca_base_param.h"
#include "opal/mca/memchecker/memchecker.h"
#include "opal/mca/memchecker/base/base.h"
#include "memchecker_pin.h"
/*
* Local functions
*/
static int pin_module_init(void);
static int pin_module_runindebugger(void);
static int pin_module_isaddressable(void * p, size_t len);
static int pin_module_isdefined(void * p, size_t len);
static int pin_module_mem_noaccess(void * p, size_t len);
static int pin_module_mem_undefined(void * p, size_t len);
static int pin_module_mem_defined(void * p, size_t len);
static int pin_module_mem_defined_if_addressable(void * p, size_t len);
static int pin_module_create_block(void * p, size_t len, char * description);
static int pin_module_discard_block(void * p); /* Here, we need to do some mapping for pin */
static int pin_module_leakcheck(void);
static int pin_module_get_vbits(void * p, char * vbits, size_t len);
static int pin_module_set_vbits(void * p, char * vbits, size_t len);
static int pin_module_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info);
static int pin_module_unreg_mem_watch(void * p, size_t len);
static int pin_module_unreg_all_mem_watch();
static int pin_module_search_mem_index(void * p, size_t len, size_t *index);
static int pin_module_mem_watch_count();
static int pin_module_print_callstack();
/*
* pin memchecker module
*/
static const opal_memchecker_base_module_1_0_0_t loc_module = {
/* Initialization function */
pin_module_init,
/* Module function pointers */
pin_module_runindebugger,
pin_module_isaddressable,
pin_module_isdefined,
pin_module_mem_noaccess,
pin_module_mem_undefined,
pin_module_mem_defined,
pin_module_mem_defined_if_addressable,
pin_module_create_block,
pin_module_discard_block,
pin_module_leakcheck,
pin_module_get_vbits,
pin_module_set_vbits,
pin_module_reg_mem_watch,
pin_module_unreg_mem_watch,
pin_module_unreg_all_mem_watch,
pin_module_search_mem_index,
pin_module_mem_watch_count,
pin_module_print_callstack
};
int MEMPIN_RUNNING_WITH_PIN(int *pin_alive)
{
return OPAL_SUCCESS;
}
/* MEMPIN_REG_MEM_WATCH(addr, size, watch_type, cb_func, cb_args); */
int MEMPIN_REG_MEM_WATCH(void* addr, int size, int op, void * cb_func, void* cb_args)
{
/* assert the parameters */
return OPAL_SUCCESS;
}
/* MEMPIN_UNREG_WATCH(addr, size); */
int MEMPIN_UNREG_MEM_WATCH(void* addr, int size)
{
/* assert the parameters */
return OPAL_SUCCESS;
}
/* MEMPIN_UNREG_MEM_WATCH(); */
int MEMPIN_UNREG_ALL_MEM_WATCH()
{
/* assert the parameters */
return OPAL_SUCCESS;
}
/* MEMPIN_SEARCH_MEM_INDEX(); */
int MEMPIN_SEARCH_MEM_INDEX(void* addr, int size, size_t *index)
{
/* assert the parameters */
return OPAL_SUCCESS;
}
/* MEMPIN_UNREG_MEM_WATCH(); */
int MEMPIN_MEM_WATCH_COUNT()
{
/* assert the parameters */
return OPAL_SUCCESS;
}
/* MEMPIN_UNREG_PRINT_CALLSTACK(); */
int MEMPIN_PRINT_CALLSTACK()
{
/* assert the parameters */
return OPAL_SUCCESS;
}
int opal_memchecker_pin_component_query(mca_base_module_t **module, int *priority)
{
int param;
param = mca_base_param_find("memchecker", "pin", "priority");
mca_base_param_lookup_int(param, priority);
*module = (mca_base_module_t *)&loc_module;
return OPAL_SUCCESS;
}
static int pin_module_init(void)
{
/* Nothing to do yet, possibly update the amount of memory blocks. */
return OPAL_SUCCESS;
}
static int pin_module_runindebugger(void)
{
int pin_alive=0;
MEMPIN_RUNNING_WITH_PIN(&pin_alive);
if(pin_alive) {
return 1;
} else {
return 0;
}
}
static int pin_module_isaddressable(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_CHECK_MEM_IS_ADDRESSABLE(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_isdefined(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_CHECK_MEM_IS_DEFINED(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_mem_noaccess(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_MAKE_MEM_NOACCESS(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_mem_undefined(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_MAKE_MEM_UNDEFINED(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_mem_defined(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_MAKE_MEM_DEFINED(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_mem_defined_if_addressable(void * p, size_t len)
{
/* if (len > 0) { */
/* PIN_MAKE_MEM_DEFINED_IF_ADDRESSABLE(p, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_create_block(void * p, size_t len, char * description)
{
/* if (len > 0) { */
/* PIN_CREATE_BLOCK (p, len, description); */
/* /\* */
/* * Add p to some list atomically */
/* *\/ */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_discard_block(void * p)
{
/* Here, we need to do some mapping for pin */
/*
* If p in list, then get rid of name
*/
return OPAL_SUCCESS;
}
static int pin_module_leakcheck(void)
{
/* PIN_DO_LEAK_CHECK; */
return OPAL_SUCCESS;
}
static int pin_module_get_vbits(void * p, char * vbits, size_t len)
{
/* if (len > 0) { */
/* PIN_GET_VBITS(p, vbits, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_set_vbits(void * p, char * vbits, size_t len)
{
/* if (len > 0) { */
/* PIN_SET_VBITS(p, vbits, len); */
/* } */
return OPAL_SUCCESS;
}
static int pin_module_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info)
{
if (len > 0) {
return MEMPIN_REG_MEM_WATCH(p, len, op, cb, info);
}
return OPAL_SUCCESS;
}
static int pin_module_unreg_mem_watch(void * p, size_t len)
{
if (len > 0) {
return MEMPIN_UNREG_MEM_WATCH(p, len);
}
return OPAL_SUCCESS;
}
static int pin_module_unreg_all_mem_watch()
{
return MEMPIN_UNREG_ALL_MEM_WATCH();
}
static int pin_module_search_mem_index(void * p, size_t len, size_t *index)
{
return MEMPIN_SEARCH_MEM_INDEX(p, len, index);
}
static int pin_module_mem_watch_count()
{
return MEMPIN_MEM_WATCH_COUNT();
}
static int pin_module_print_callstack()
{
return MEMPIN_PRINT_CALLSTACK();
}

Просмотреть файл

@ -43,10 +43,14 @@ static int valgrind_module_mem_defined_if_addressable(void * p, size_t len);
static int valgrind_module_create_block(void * p, size_t len, char * description);
static int valgrind_module_discard_block(void * p); /* Here, we need to do some mapping for valgrind */
static int valgrind_module_leakcheck(void);
#if 0
static int valgrind_module_get_vbits(void * p, char * vbits, size_t len);
static int valgrind_module_set_vbits(void * p, char * vbits, size_t len);
#endif
static int valgrind_module_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info);
static int valgrind_module_unreg_mem_watch(void * p, size_t len);
static int valgrind_module_unreg_all_mem_watch();
static int valgrind_module_search_mem_index(void * p, size_t len, size_t *index);
static int valgrind_module_mem_watch_count();
static int valgrind_module_print_callstack();
/*
* Valgrind memchecker module
@ -65,7 +69,15 @@ static const opal_memchecker_base_module_1_0_0_t loc_module = {
valgrind_module_mem_defined_if_addressable,
valgrind_module_create_block,
valgrind_module_discard_block,
valgrind_module_leakcheck
valgrind_module_leakcheck,
valgrind_module_get_vbits,
valgrind_module_set_vbits,
valgrind_module_reg_mem_watch,
valgrind_module_unreg_mem_watch,
valgrind_module_unreg_all_mem_watch,
valgrind_module_search_mem_index,
valgrind_module_mem_watch_count,
valgrind_module_print_callstack
};
@ -185,7 +197,6 @@ static int valgrind_module_leakcheck(void)
}
#if 0
static int valgrind_module_get_vbits(void * p, char * vbits, size_t len)
{
if (len > 0) {
@ -204,5 +215,45 @@ static int valgrind_module_set_vbits(void * p, char * vbits, size_t len)
return OPAL_SUCCESS;
}
#endif
static int valgrind_module_reg_mem_watch(void * p, size_t len, int op, void *cb, void *info)
{
/*if (len > 0) {
return VALGRIND_REG_MEM_WATCH(p, len, op, cb, info);
}*/
return OPAL_SUCCESS;
}
static int valgrind_module_unreg_mem_watch(void * p, size_t len)
{
/*if (len > 0) {
return VALGRIND_UNREG_MEM_WATCH(p, len);
}*/
return OPAL_SUCCESS;
}
static int valgrind_module_unreg_all_mem_watch()
{
/* return VALGRIND_UNREG_USER_ALL_MEM_WATCH(); */
return OPAL_SUCCESS;
}
static int valgrind_module_search_mem_index(void * p, size_t len, size_t *index)
{
return OPAL_SUCCESS;
}
static int valgrind_module_mem_watch_count()
{
return OPAL_SUCCESS;
}
static int valgrind_module_print_callstack()
{
return OPAL_SUCCESS;
}