Per the MemPin RFC, submit the component source files, and update the memchecker macros.
This commit was SVN r27508.
Этот коммит содержится в:
родитель
8677693d9a
Коммит
12c3c743de
@ -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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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 */
|
95
opal/mca/memchecker/mempin/memchecker_pin_component.c
Обычный файл
95
opal/mca/memchecker/mempin/memchecker_pin_component.c
Обычный файл
@ -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;
|
||||
}
|
||||
|
316
opal/mca/memchecker/mempin/memchecker_pin_module.c
Обычный файл
316
opal/mca/memchecker/mempin/memchecker_pin_module.c
Обычный файл
@ -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;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user