Skip to content

Instantly share code, notes, and snippets.

@hoheinzollern
Created June 1, 2011 20:12
Show Gist options
  • Save hoheinzollern/1003197 to your computer and use it in GitHub Desktop.
Save hoheinzollern/1003197 to your computer and use it in GitHub Desktop.
hg_adv.c
#include "hg_adv.h"
#define ADV_DEBUG 0
VgHashTable write_buffers_8;
VgHashTable write_buffers_16;
VgHashTable write_buffers_32;
VgHashTable write_buffers_64;
typedef struct _AddrWBNode {
void *next;
Addr addr;
XArray *wb;
} AddrWBNode;
typedef struct _AdvWB {
UInt tid; // Thread ID
XArray *wb; // Relative WriteBuffer
} AdvWB;
#define GET_WB_DECL(sz) \
XArray *get_or_create_wb_##sz(Thread *t, Addr a); \
XArray *get_random_wb_##sz(Thread *t, Addr a);
GET_WB_DECL(8)
GET_WB_DECL(16)
GET_WB_DECL(32)
GET_WB_DECL(64)
void adv_init(void) {
write_buffers_8 = VG_(HT_construct)("hg_writebuffer_map");
write_buffers_16 = VG_(HT_construct)("hg_writebuffer_map");
write_buffers_32 = VG_(HT_construct)("hg_writebuffer_map");
write_buffers_64 = VG_(HT_construct)("hg_writebuffer_map");
}
#define ADV_TRACK_ADDR(sz) \
void adv_track_addr_##sz(Addr a) { \
AddrWBNode *node = VG_(HT_lookup)(write_buffers_##sz, (UInt) a); \
if (node != NULL) \
return; \
XArray *wb = VG_(newXA)(HG_(zalloc), \
"addr_wb", HG_(free), sizeof(AdvWB)); \
node = HG_(zalloc)("addr_wb_node", sizeof(AddrWBNode)); \
node->addr = a; \
node->wb = wb; \
VG_(HT_add_node)(write_buffers_##sz, node); \
if (ADV_DEBUG) \
VG_(printf)("tracking address 0x%x\n", (UInt)a); \
}
ADV_TRACK_ADDR(8)
ADV_TRACK_ADDR(16)
ADV_TRACK_ADDR(32)
ADV_TRACK_ADDR(64)
/**
* Handles the event of a read to a memory location
*
* Use one of the most outdated values found in a writebuffer != wb[t] if there's any
* and write it to the specified memory location (to be used from the subsequent memory access)
*
* @param t operating thread
* @param a the address at which the read is attempted
*
*/
#define ADV_READ(sz) \
void adv_read_##sz(Thread *t, Addr a) { \
XArray *wb = get_random_wb_##sz(t, a); \
if (wb == NULL) \
return; \
\
uint##sz##_t val; \
UInt size = VG_(sizeXA)(wb); \
UInt index = VG_(random)(NULL) % size; \
if (size > 0) \
val = *((uint##sz##_t*)VG_(indexXA)(wb, 0)); \
else if (ADV_DEBUG) { \
val = *(uint##sz##_t*)a; \
VG_(printf)("read val %x at 0x%x [%s] thread: %d\n", \
val, (UInt)a, size>0 ? "s" : "f", t->coretid); \
if (*(uint##sz##_t*)a != val) \
VG_(printf)("actual val %x\n", (uint##sz##_t)*(uint##sz##_t*)a); \
} \
if (size > 0) \
(*(uint##sz##_t*)a) = val; \
}
ADV_READ(8)
ADV_READ(16)
ADV_READ(32)
ADV_READ(64)
/**
* Records a write in the writebuffer
*
* @param t operating thread
* @param a the memory location (address) at which the write is done
* @param v the written value
*/
#define ADV_WRITE(sz) \
void adv_write_##sz(Thread *t, Addr a, uint##sz##_t v) { \
XArray *wb = get_or_create_wb_##sz(t, a); \
if (wb == NULL) \
return; \
UInt idx = VG_(addToXA)(wb, &v); \
if (ADV_DEBUG) { \
VG_(printf)("write val %x at 0x%x thread: %d index: %d\n", \
v, (UInt)a, t->coretid, idx); \
} \
}
ADV_WRITE(8)
ADV_WRITE(16)
ADV_WRITE(32)
ADV_WRITE(64)
/**
* Flushes the writebuffer for the current thread
*
* @param t operating thread
*/
#define ADV_FENCE(sz) \
void adv_fence_##sz(Thread *t) { \
VG_(HT_ResetIter)(write_buffers_##sz); \
AddrWBNode *node; \
while ((node = VG_(HT_Next)(write_buffers_##sz)) != NULL) { \
Addr a = node->addr; \
XArray *awb = node->wb; \
Int i, j; \
for (i = 0; i < VG_(sizeXA)(awb); i++) { \
XArray *wb = ((AdvWB*)VG_(indexXA)(awb, i))->wb; \
for (j = 0; j < VG_(sizeXA)(wb); j++) \
*((uint##sz##_t *)a) = *((uint##sz##_t*)VG_(indexXA)(wb, j)); \
VG_(dropTailXA)(wb, VG_(sizeXA)(wb)); \
} \
} \
if (ADV_DEBUG) { \
VG_(printf)("memory fence\n"); \
} \
}
ADV_FENCE(8)
ADV_FENCE(16)
ADV_FENCE(32)
ADV_FENCE(64)
void adv_fence(Thread *t) {
adv_fence_8(t);
adv_fence_16(t);
adv_fence_32(t);
adv_fence_64(t);
}
/*
* Gets the writebuffer for thread t and address a if a is tracked,
* if not found it creates a new one. Returns NULL if a is not tracked.
*/
#define GET_OR_CREATE_WB(sz) \
XArray *get_or_create_wb_##sz(Thread *t, Addr a) { \
AddrWBNode *node = VG_(HT_lookup)(write_buffers_##sz, (UInt)a); \
if (node == NULL) \
return NULL; \
Int i; \
XArray *wb = node->wb; \
for (i = 0; i < VG_(sizeXA)(wb); i++) { \
AdvWB *awb = VG_(indexXA)(wb, i); \
if (awb->tid == t->coretid) \
return awb->wb; \
} \
AdvWB awb; \
awb.tid = t->coretid; \
awb.wb = VG_(newXA)(HG_(zalloc), "addr_thr_wb", \
HG_(free), sizeof(uint##sz##_t)); \
VG_(addToXA)(wb, &awb); \
return awb.wb; \
}
GET_OR_CREATE_WB(8)
GET_OR_CREATE_WB(16)
GET_OR_CREATE_WB(32)
GET_OR_CREATE_WB(64)
#define GET_RANDOM_WB(sz) \
XArray *get_random_wb_##sz(Thread *t, Addr a) { \
AddrWBNode *node = VG_(HT_lookup)(write_buffers_##sz, (UInt)a); \
if (node == NULL) \
return NULL; \
XArray *wb = node->wb; \
Int size = VG_(sizeXA)(wb); \
if (size == 1) { \
AdvWB *awb = ((AdvWB *)VG_(indexXA)(wb, 0)); \
if (awb->tid == t->coretid) \
return NULL; \
else \
return awb->wb; \
} else if (size > 1) { \
AdvWB *awb = ((AdvWB*)VG_(indexXA)(wb, VG_(random)(NULL) % VG_(sizeXA)(wb))); \
while (awb->tid == t->coretid) \
awb = ((AdvWB*)VG_(indexXA)(wb, VG_(random)(NULL) % VG_(sizeXA)(wb))); \
return awb->wb; \
} else return NULL; \
}
GET_RANDOM_WB(8)
GET_RANDOM_WB(16)
GET_RANDOM_WB(32)
GET_RANDOM_WB(64)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment