From f83929fa5228c98e060aeed11ffec670c2750adf Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Tue, 27 Apr 2021 16:11:50 +0800 Subject: [PATCH 01/11] original version --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 67ac8645e3..ee8fda5fac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vscode/ *.o # / From d0df66235227777c7b1c0d9b035f2c2ac2f35773 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Wed, 28 Apr 2021 11:07:06 +0800 Subject: [PATCH 02/11] just add new structure (store information array) --- pmemcheck/pmc_include.h | 14 ++++++++++++++ pmemcheck/pmc_main.c | 24 +++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index 64287a534e..aa3d01b0a3 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -15,6 +15,20 @@ #ifndef PMC_INCLUDE_H #define PMC_INCLUDE_H +/** Metadata structure for store information array */ +struct arr_md { + UWord end_index; //Index of current free metadata + Addr min_addr; + Addr max_addr; + UWord start_index; + enum flushed_state + { + NO_FLUSHED, + PART_FLUSHED, + ALL_FLUSHED, + } state; +}; + /** Single store to memory. */ struct pmem_st { diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 01db468534..862164ef12 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -59,8 +59,22 @@ /** Max allowable path length */ #define MAX_PATH_SIZE 4096 +/** Max allowable length of store information array*/ +#define MAX_ARRAY_NUM 100000000UL + +/** defining store information array structure*/ +struct pmem_stores_array +{ + UWord m_index;//Index of current metadata + struct pmem_st *pmem_stores; + struct arr_md* m_data; // Address of metadata array +}; + /** Holds parameters and runtime data */ static struct pmem_ops { + /** Array of stores to persistent memory*/ + struct pmem_stores_array info_array; + /** Set of stores to persistent memory. */ OSet *pmem_stores; @@ -810,7 +824,6 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) { if (LIKELY(!is_pmem_access(addr, size))) return; - struct pmem_st *store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, (SizeT) sizeof (struct pmem_st)); store->addr = addr; @@ -2033,6 +2046,15 @@ pmc_process_cmd_line_option(const HChar *arg) static void pmc_post_clo_init(void) { + pmem.info_array.pmem_stores = VG_(malloc)("pmc.main.cpci.7", + MAX_ARRAY_NUM * sizeof(struct pmem_st)); + pmem.info_array.m_index = 0; + pmem.info_array.m_data = VG_(malloc)("pmc.main.cpci.8", + MAX_ARRAY_NUM * sizeof(struct arr_md)); + pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; + pmem.info_array.m_data[0].state = NO_FLUSHED; + pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index=0; + pmem.pmem_stores = VG_(OSetGen_Create)(/*keyOff*/0, cmp_pmem_st, VG_(malloc), "pmc.main.cpci.1", VG_(free)); From f0f262471645a79ea50a8074ab36927b12185904 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Thu, 29 Apr 2021 15:58:06 +0800 Subject: [PATCH 03/11] modify the algorithm of trace_pmem_store() --- pmemcheck/pmc_include.h | 1 + pmemcheck/pmc_main.c | 181 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 177 insertions(+), 5 deletions(-) diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index aa3d01b0a3..5844a56e80 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -32,6 +32,7 @@ struct arr_md { /** Single store to memory. */ struct pmem_st { + Bool is_delete; Addr addr; ULong size; ULong block_num; diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 862164ef12..a644935241 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -670,6 +670,16 @@ add_mult_overwrite_warn(struct pmem_st *store, OSet *set, Bool preallocated) store, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); } +static void +array_add_mult_overwrite_warn(struct pmem_st *store, OSet *set, Bool preallocated) +{ + struct pmem_st *new = VG_(OSetGen_AllocNode)(set, + (SizeT)sizeof(struct pmem_st)); + *new=*store; + add_warning_event(pmem.multiple_stores, &pmem.multiple_stores_reg, + new, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); +} + /** * \brief Splits-adjusts the two given stores so that they do not overlap. * @@ -748,6 +758,74 @@ split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, tl_assert(False); } +static void +array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, + split_clb clb) +{ + Addr new_max = new->addr + new->size; + Addr old_max = old->addr + old->size; + + /* new store encapsulates old, it needs to be removed */ + if (old->addr >= new->addr && old_max <= new_max) { + old->is_delete = True; + clb(old, set, True); + return; + } + + struct pmem_st tmp; + if (old->addr < new->addr) { + /* the new store is within the old store */ + if (old_max > new_max) { + struct pmem_st *after = VG_(OSetGen_AllocNode)(set, + (SizeT) sizeof(struct pmem_st)); + *after = *old; + after->addr = new_max; + after->size = old_max - new_max; + after->value &= (1 << (after->size * 8 + 1)) - 1; + /* adjust the size and value of the old entry */ + old->value >>= old_max - new->addr; + old->size = new->addr - old->addr; + /* insert the new store fragment */ + VG_(OSetGen_Insert)(set, after); + /* clb the cut out fragment with the old ExeContext */ + tmp = *new; + tmp.context = old->context; + clb(&tmp, set, False); + } else { + /* old starts before new */ + + /* callback for removed part */ + tmp = *old; + tmp.addr = new->addr; + tmp.size = old_max - new->addr; + /* adjust leftover */ + clb(&tmp, set, False); + old->value >>= old_max - new->addr; + old->size = new->addr - old->addr; + } + return; + } + + /* now old->addr >= new->addr */ + + /* end of old is behind end of new */ + if (old_max > new_max) { + /* callback for removed part */ + tmp = *old; + tmp.size -= old_max - new_max; + clb(&tmp, set, False); + /* adjust leftover */ + old->addr = new_max; + old->size = old_max - new_max; + old->value &= (1 << (old->size * 8 + 1)) - 1; + return; + } + + /* you should never end up here */ + tl_assert(False); +} + + /** * \brief Add and merges adjacent stores if possible. * Should not be used if track_multiple_stores is enabled. @@ -783,6 +861,67 @@ add_and_merge_store(struct pmem_st *region) VG_(OSetGen_Insert)(pmem.pmem_stores, region); } +static void update_array_metadata_minandmax(struct pmem_st *store) +{ + Addr store_max = store->addr + store->size; + struct arr_md* m_data=pmem.info_array.m_data+pmem.info_array.m_index; + if (m_data->max_addr == -1 && m_data->min_addr == -1) + { + m_data->min_addr = store->addr; + m_data->max_addr = store_max; + } + if (m_data->min_addr > store->addr) + m_data->min_addr = store->addr; + if (m_data->max_addr < store_max) + m_data->max_addr = store_max; + + return; +} + +static int cmp_with_arr_minandmax(struct pmem_st *p_st,int index) +{ + Addr p_st_max = p_st->addr + p_st->size; + struct arr_md* m_data=pmem.info_array.m_data+index; + if ((p_st->addr > m_data->max_addr) || (p_st_max < m_data->min_addr)) + return -1; + else if (m_data->min_addr <= p_st->addr && p_st_max <= m_data->max_addr) + return 1; + else + return 0; +} + + +/** + * Handle multiple overwrites for store information array. + */ +static void +array_handle_with_mult_stores(struct pmem_st *store){ + struct pmem_st *existing; + /* remove any overlapping stores from the collection */ + for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ + if (cmp_with_arr_minandmax(store,s_index) != -1) + { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) + { + if (LIKELY(pmem.info_array.pmem_stores[i].is_delete != True)) + existing = pmem.info_array.pmem_stores + i; + else + continue; + if (cmp_pmem_st(existing, store) == 0) + { + + if ((store->block_num - existing->block_num) < pmem.store_sb_indiff && existing->addr == store->addr && existing->size == store->size && existing->value == store->value) + { + existing->is_delete = True; + continue; + } + array_split_stores(existing, store, pmem.pmem_stores, + array_add_mult_overwrite_warn); + } + } + } + } +} /** * \brief Handle a new store checking for multiple overwrites. * This should be called when track_multiple_stores is enabled. @@ -792,6 +931,8 @@ add_and_merge_store(struct pmem_st *region) static void handle_with_mult_stores(struct pmem_st *store) { + array_handle_with_mult_stores(store); + struct pmem_st *existing; /* remove any overlapping stores from the collection */ while ((existing = VG_(OSetGen_Lookup)(pmem.pmem_stores, store)) != @@ -809,7 +950,7 @@ handle_with_mult_stores(struct pmem_st *store) add_mult_overwrite_warn); } /* it is now safe to insert the new store */ - VG_(OSetGen_Insert)(pmem.pmem_stores, store); + //VG_(OSetGen_Insert)(pmem.pmem_stores, store); } /** @@ -824,8 +965,21 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) { if (LIKELY(!is_pmem_access(addr, size))) return; - struct pmem_st *store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + struct pmem_st *store; + UWord old_index=pmem.info_array.m_data[pmem.info_array.m_index].end_index; + if (LIKELY(old_index < MAX_ARRAY_NUM)) + { + store = pmem.info_array.pmem_stores + old_index; + } + else + { + store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, (SizeT) sizeof (struct pmem_st)); + //store->index=db_pmem_store_index; + //db_pmem_store_index++; + } + //struct pmem_st *store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + // (SizeT) sizeof (struct pmem_st)); store->addr = addr; store->size = size; store->state = STST_DIRTY; @@ -839,10 +993,27 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) if (pmem.store_traces) pp_store_trace(store, pmem.store_traces_depth); } - if (pmem.track_multiple_stores) + if (pmem.track_multiple_stores){ handle_with_mult_stores(store); - else - add_and_merge_store(store); + if (UNLIKELY(old_index >= MAX_ARRAY_NUM)){ + VG_(OSetGen_Insert)(pmem.pmem_stores, store); + } + else + { + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + update_array_metadata_minandmax(store); + } + } + else{ + if (UNLIKELY(old_index >= MAX_ARRAY_NUM)){ + add_and_merge_store(store); + } + else + { + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + update_array_metadata_minandmax(store); + } + } /* do transaction check */ handle_tx_store(store); From 1ec603086958d841b35e46ffef02d9c66116a698 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Sun, 2 May 2021 10:53:03 +0800 Subject: [PATCH 04/11] modify the algorithm of do_flush --- pmemcheck/pmc_main.c | 155 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index a644935241..6a6621cc10 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -1353,6 +1353,157 @@ do_fence(void) } } } +/* set up a new metadata */ +void init_m_data(void){ + pmem.info_array.m_index++; + struct arr_md* pm_data=pmem.info_array.m_data+pmem.info_array.m_index; + pm_data->min_addr = pm_data->max_addr = -1; + pm_data->state = NO_FLUSHED; + pm_data->end_index=pm_data->start_index=pmem.info_array.m_data[pmem.info_array.m_index-1].end_index; + +} + +/** +* \brief writeback processing for store information array +*/ +static Bool +array_process_flush(UWord base, UWord size){ + struct pmem_st flush_info = {0}; + + if (LIKELY(pmem.force_flush_align == False)) + { + flush_info.addr = base; + flush_info.size = size; + } + else + { + /* align flushed memory */ + flush_info.addr = base & ~(pmem.flush_align_size - 1); + flush_info.size = roundup(size, pmem.flush_align_size); + } + if (pmem.log_stores) + VG_(emit) + ("|FLUSH;0x%lx;0x%llx", flush_info.addr, flush_info.size); + + /* unfortunately lookup doesn't work here, the oset is an avl tree */ + + Addr flush_max = flush_info.addr + flush_info.size; + struct pmem_st *being_flushed; + Bool valid_flush = False; + /*================================array=============================*/ + for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ + /* directly mark this writeback interval */ + if (flush_max >= pmem.info_array.m_data[s_index].max_addr && pmem.info_array.m_data[s_index].min_addr >= flush_info.addr && pmem.info_array.m_data[s_index].state == NO_FLUSHED) + { + pmem.info_array.m_data[s_index].state = ALL_FLUSHED; + valid_flush = True; + } + /* directly skip this writeback interval */ + else if (flush_max < pmem.info_array.m_data[s_index].min_addr || pmem.info_array.m_data[s_index].max_addr < flush_info.addr) + { + continue; + } + /* go into this writeback interval and traverse store information one by one */ + else + { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) + { + being_flushed = pmem.info_array.pmem_stores + i; + if (being_flushed->is_delete == True) + { + being_flushed->state = STST_FLUSHED; + continue; + } + + if (cmp_pmem_st(&flush_info, being_flushed) != 0) + continue; + + valid_flush = True; + /* check for multiple flushes of stores */ + if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) + { + if (pmem.check_flush) + { + /* multiple flush of the same store - probably an issue */ + struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.3", + sizeof(struct pmem_st)); + *wrong_flush = *being_flushed; + wrong_flush->state = STST_FLUSHED; + // VG_(umsg)("=======pmem_index=%d========\n",wrong_flush->index); + add_warning_event(pmem.redundant_flushes, + &pmem.redundant_flushes_reg, + wrong_flush, MAX_FLUSH_ERROR_EVENTS, + print_redundant_flush_error); + } + continue; + } + + being_flushed->state = STST_FLUSHED; + pmem.info_array.m_data[s_index].state = PART_FLUSHED; + /* store starts before base flush address */ + if (being_flushed->addr < flush_info.addr) + { + /* split and reinsert */ + struct pmem_st *split; + UWord old_index= pmem.info_array.m_data[pmem.info_array.m_index].end_index; + if (LIKELY(old_index < MAX_ARRAY_NUM)) + { + split = pmem.info_array.pmem_stores + old_index; + + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } + else + { + split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + } + *split = *being_flushed; + split->size = flush_info.addr - being_flushed->addr; + split->state = STST_DIRTY; + + /* adjust original */ + being_flushed->addr = flush_info.addr; + being_flushed->size -= split->size; + if (old_index >= MAX_ARRAY_NUM){ + add_and_merge_store(split); + } + /* reset iter */ + } + + /* end of store is behind max flush */ + if (being_flushed->addr + being_flushed->size > flush_max) + { + /* split and reinsert */ + UWord old_index= pmem.info_array.m_data[pmem.info_array.m_index].end_index; + struct pmem_st *split; + if (LIKELY(old_index < MAX_ARRAY_NUM)) + { + split = pmem.info_array.pmem_stores + old_index; + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } + else + { + split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + } + *split = *being_flushed; + split->addr = flush_max; + split->size = being_flushed->addr + being_flushed->size - flush_max; + split->state = STST_DIRTY; + + /* adjust original */ + being_flushed->size -= split->size; + if (old_index >= MAX_ARRAY_NUM){ + add_and_merge_store(split); + } + + } + } + } +} + if (pmem.info_array.m_data[pmem.info_array.m_index].state != NO_FLUSHED){ + init_m_data(); + } + return valid_flush; +} /** * \brief Register a flush. @@ -1367,6 +1518,7 @@ do_fence(void) static void do_flush(UWord base, UWord size) { + Bool array_valid_flush=array_process_flush(base, size); struct pmem_st flush_info = {0}; if (LIKELY(pmem.force_flush_align == False)) { @@ -1496,7 +1648,7 @@ do_flush(UWord base, UWord size) } end: - if (!valid_flush && pmem.check_flush) { + if (!valid_flush && pmem.check_flush && !array_valid_flush) { /* unnecessary flush event - probably an issue */ struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.6", sizeof(struct pmem_st)); @@ -1508,6 +1660,7 @@ do_flush(UWord base, UWord size) wrong_flush, MAX_FLUSH_ERROR_EVENTS, print_superfluous_flush_error); } + } /** From 263d2af8510304ccc7613c8660e903522ce8ef6e Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Wed, 5 May 2021 09:28:08 +0800 Subject: [PATCH 05/11] modify the algorithm of do_fence --- pmemcheck/pmc_main.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 6a6621cc10..40951987d3 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -1326,6 +1326,37 @@ add_event_dw(IRSB *sb, IRAtom *daddr, Int dsize, IRAtom *value) add_event_dw_guarded(sb, daddr, dsize, NULL, value); } +/** +* \brief fence processing for store information array +*/ +static void array_process_fence(void){ + struct pmem_st *being_fenced = NULL; +for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ + if (pmem.info_array.m_data[s_index].state != ALL_FLUSHED) + { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) + { + being_fenced = pmem.info_array.pmem_stores + i; + + if (being_fenced->state == STST_FLUSHED||being_fenced->is_delete==True) + { + continue; + } + else + { + struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + add_and_merge_store(new); + } + } + + } +} +/* reset store information array */ + pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; + pmem.info_array.m_data[0].state = NO_FLUSHED; + pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index=0; + pmem.info_array.m_index=0; +} /** * \brief Register a fence. * From 93a2ec5b08f63418a57bb5b3604d30db0b0b05a8 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Sat, 8 May 2021 10:31:53 +0800 Subject: [PATCH 06/11] mini fix do_flush --- .gitignore | 2 +- pmemcheck/pmc_main.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ee8fda5fac..98cdb38da4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .vscode/ *.o - +.DS_Store # / /.in_place /.vs diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 40951987d3..ed74039745 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -1383,6 +1383,7 @@ do_fence(void) VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, &temp); } } + array_process_fence(); } /* set up a new metadata */ void init_m_data(void){ From 58e2ccbad20bdfe9d88d80b4adc704cc43517928 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Sat, 8 May 2021 16:43:23 +0800 Subject: [PATCH 07/11] fix bugs and pass the simple verification (perl tests/vg_regtest pmemcheck) --- pmemcheck/pmc_include.h | 1 - pmemcheck/pmc_main.c | 103 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index 5844a56e80..7d53d52291 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -48,7 +48,6 @@ struct pmem_st { /*------------------------------------------------------------*/ /*--- Common functions ---*/ /*------------------------------------------------------------*/ - /* Check if the given region is in the set. */ UWord is_in_mapping_set(const struct pmem_st *region, OSet *region_set); diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index ed74039745..4b470359c9 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -299,6 +299,7 @@ print_multiple_stores(void) } } +static void add_and_merge_store(struct pmem_st *region); /** * \brief Prints registered store statistics. * @@ -308,12 +309,28 @@ print_multiple_stores(void) static void print_store_stats(void) { +/* print store states of the array*/ + struct pmem_st *tmp; + for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ + for(int i=pmem.info_array.m_data[s_index].start_index;iis_delete == True) + continue; + if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED) + tmp->state = STST_FLUSHED; + struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + *new=*tmp; + add_and_merge_store(new); + } + } + } + VG_(umsg)("Number of stores not made persistent: %u\n", VG_(OSetGen_Size) (pmem.pmem_stores)); if (VG_(OSetGen_Size)(pmem.pmem_stores) != 0) { VG_(OSetGen_ResetIter)(pmem.pmem_stores); - struct pmem_st *tmp; UWord total = 0; Int i = 0; VG_(umsg)("Stores not made persistent properly:\n"); @@ -985,6 +1002,7 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) store->state = STST_DIRTY; store->block_num = sblocks; store->value = value; + store->is_delete=False; store->context = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); /* log the store, regardless if it is a double store */ @@ -1345,6 +1363,7 @@ for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ else { struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + *new=*being_fenced; add_and_merge_store(new); } } @@ -1386,7 +1405,7 @@ do_fence(void) array_process_fence(); } /* set up a new metadata */ -void init_m_data(void){ +static void init_m_data(void){ pmem.info_array.m_index++; struct arr_md* pm_data=pmem.info_array.m_data+pmem.info_array.m_index; pm_data->min_addr = pm_data->max_addr = -1; @@ -1413,9 +1432,6 @@ array_process_flush(UWord base, UWord size){ flush_info.addr = base & ~(pmem.flush_align_size - 1); flush_info.size = roundup(size, pmem.flush_align_size); } - if (pmem.log_stores) - VG_(emit) - ("|FLUSH;0x%lx;0x%llx", flush_info.addr, flush_info.size); /* unfortunately lookup doesn't work here, the oset is an avl tree */ @@ -2265,6 +2281,83 @@ pmc_handle_client_request(ThreadId tid, UWord *arg, UWord *ret ) temp_info.addr = arg[1]; temp_info.size = arg[2]; + /* remove regions from store information array*/ + struct pmem_st *modified_entry = NULL; + struct pmem_st *region = &temp_info; + UWord old_index; + for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ + if (cmp_with_arr_minandmax(&temp_info,s_index) != -1) + { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) + { + //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); + modified_entry = pmem.info_array.pmem_stores + i; + if (modified_entry->is_delete == True) + continue; + if (cmp_pmem_st(region, modified_entry) == 0) + { + SizeT region_max_addr = region->addr + region->size; + //struct pmem_st tmp; + SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; + if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < + region_max_addr)) + { + /* modified entry fully within removed region */ + modified_entry->is_delete = True; + } + else if ((modified_entry->addr < region->addr) && + (mod_entry_max_addr > region_max_addr)) + { + /* modified entry is larger than the removed region - slice */ + modified_entry->size = region->addr - modified_entry->addr; + + // VG_(OSetGen_Insert)(region_set, modified_entry); + struct pmem_st *new_region; + old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; + if (old_index>= MAX_ARRAY_NUM){ + new_region = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + sizeof(struct pmem_st)); + } + else + { + new_region = pmem.info_array.pmem_stores + old_index; + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } + new_region->addr = region_max_addr; + new_region->size = mod_entry_max_addr - new_region->addr; + if (old_index >= MAX_ARRAY_NUM){ + add_and_merge_store(new_region); + } + + } + else if ((modified_entry->addr >= region->addr) && + (mod_entry_max_addr > region_max_addr)) + { + /* head overlaps */ + modified_entry->size -= region_max_addr - modified_entry->addr; + modified_entry->addr = region_max_addr; + // VG_(OSetGen_Insert)(region_set, modified_entry); + } + else if ((mod_entry_max_addr <= region_max_addr) && + (region->addr > modified_entry->addr)) + { + /* tail overlaps */ + modified_entry->size = region->addr - modified_entry->addr; + + // VG_(OSetGen_Insert)(region_set, modified_entry); + } + else + { + /* exact match */ + modified_entry->is_delete = True; + } + } + } + } + } + + /* remove regions from pmem_stores Oset*/ + remove_region(&temp_info, pmem.pmem_stores); break; } From e4db72ff5cd3958ec440ef1ee253a9261262b122 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Wed, 12 May 2021 15:52:02 +0800 Subject: [PATCH 08/11] (1) format codes; (2) add a document to introduce what has change and why; (3) move is_delete to the end of the struct and change 100000000UL to 1000UL --- PMDebuggerToPmemcheck.md | 44 +++ pmemcheck/pmc_include.h | 5 +- pmemcheck/pmc_main.c | 589 ++++++++++++++++++++------------------- 3 files changed, 344 insertions(+), 294 deletions(-) create mode 100644 PMDebuggerToPmemcheck.md diff --git a/PMDebuggerToPmemcheck.md b/PMDebuggerToPmemcheck.md new file mode 100644 index 0000000000..1602f90cdb --- /dev/null +++ b/PMDebuggerToPmemcheck.md @@ -0,0 +1,44 @@ +In general, I try to add some new features on top of Pmemcheck instead of giving a new debugging tool like PMDebugger. + +In this file, I briefly show what has changed and why for each commit. For more details, you can read our paper: Fast, Flexible, and Comprehensive Bug Detection for Persistent Memory Programs. + +### just add new structure -- d0df66235227777c7b1c0d9b035f2c2ac2f35773 + +- Add memory location information array which includes **arr_md** structure and **pmem_stores_array** structure. + +- Information of most stores is deleted in a short term, so we use the array to keep track of hot and short-lived information and avoid the overhead of tree reorganizations (reorganizations in Oset structure). +- Most stores can be collectively flushed, so we use arr_md structure to collectively maintain and update persistency status for high performance. + + + +### modify the algorithm of trace_pmem_store() -- f0f262471645a79ea50a8074ab36927b12185904 + +- Add memory location information into the memory location information array. +- A new function for the array structure to split stores (array_split_stores ()). +- A new function for the array structure to handle multiple stores (array_handle_with_mult_stores()). + +- A new function for the array structure to handle multiple overwrite warns (array_add_mult_overwrite_warn()). +- A new function for the array structure to update minimum and maximum address in arr_md structure (update_array_metadata_minandmax()). + +- A new function for the array structure to compare a region with minimum and maximum address in arr_md structure (cmp_with_arr_minandmax()). + + + +### modify the algorithm of do_flush -- 1ec603086958d841b35e46ffef02d9c66116a698 + +- Leverage arr_md structure to collectively maintain and update persistency status for high performance when processing writeback instructions (array_process_flush()). + + + +### modify the algorithm of do_fence -- 263d2af8510304ccc7613c8660e903522ce8ef6e + +- Leverage arr_md structure to process fence instruction and the way is similar to processing writeback instructions (array_process_fence()). +- Directly invalidates arr_md structure to achieve quickly deletion after processing fence instruction. + + + +### fix bugs and pass the simple verification (perl tests/vg_regtest pmemcheck -- 58e2ccbad20bdfe9d88d80b4adc704cc43517928 + +- Add codes in print_store_stats() to print not persistent stores in the array +- Add codes in case VG_USERREQ__PMC_SET_CLEAN to remove regions from memory location information array + diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index 7d53d52291..eb8095aafa 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -21,8 +21,7 @@ struct arr_md { Addr min_addr; Addr max_addr; UWord start_index; - enum flushed_state - { + enum flushed_state { NO_FLUSHED, PART_FLUSHED, ALL_FLUSHED, @@ -32,7 +31,6 @@ struct arr_md { /** Single store to memory. */ struct pmem_st { - Bool is_delete; Addr addr; ULong size; ULong block_num; @@ -43,6 +41,7 @@ struct pmem_st { STST_DIRTY, STST_FLUSHED, } state; + Bool is_delete; }; /*------------------------------------------------------------*/ diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 4b470359c9..d46454b3b3 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -59,20 +59,20 @@ /** Max allowable path length */ #define MAX_PATH_SIZE 4096 -/** Max allowable length of store information array*/ -#define MAX_ARRAY_NUM 100000000UL +/** Max allowable length of memory location information array */ +#define MAX_ARRAY_NUM 1000UL -/** defining store information array structure*/ -struct pmem_stores_array -{ - UWord m_index;//Index of current metadata +/** Defining memory location information array structure */ +struct pmem_stores_array { + /** Index of current metadata */ + UWord m_index; struct pmem_st *pmem_stores; - struct arr_md* m_data; // Address of metadata array + struct arr_md* m_data; }; /** Holds parameters and runtime data */ static struct pmem_ops { - /** Array of stores to persistent memory*/ + /** Array of stores to persistent memory */ struct pmem_stores_array info_array; /** Set of stores to persistent memory. */ @@ -300,6 +300,7 @@ print_multiple_stores(void) } static void add_and_merge_store(struct pmem_st *region); + /** * \brief Prints registered store statistics. * @@ -309,21 +310,22 @@ static void add_and_merge_store(struct pmem_st *region); static void print_store_stats(void) { -/* print store states of the array*/ +/* print store states of the array */ struct pmem_st *tmp; - for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ - for(int i=pmem.info_array.m_data[s_index].start_index;iis_delete == True) - continue; - if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED) - tmp->state = STST_FLUSHED; - struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); - *new=*tmp; - add_and_merge_store(new); - } - } + continue; + + if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED) + tmp->state = STST_FLUSHED; + + struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + *new = *tmp; + add_and_merge_store(new); + } } VG_(umsg)("Number of stores not made persistent: %u\n", VG_(OSetGen_Size) @@ -651,6 +653,7 @@ merge_stores(struct pmem_st *to_merge, } typedef void (*split_clb)(struct pmem_st *store, OSet *set, Bool preallocated); +typedef void (*array_split_clb)(struct pmem_st *store, OSet *set); /** * \brief Free store if it was preallocated. @@ -687,14 +690,21 @@ add_mult_overwrite_warn(struct pmem_st *store, OSet *set, Bool preallocated) store, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); } +/** + * \brief Issues a warning event with the given store as the offender for the array structure. + * + * \param[in,out] store The store to be registered as a warning. + * \param[in,out] set The set that stores memory location information. + */ static void -array_add_mult_overwrite_warn(struct pmem_st *store, OSet *set, Bool preallocated) +array_add_mult_overwrite_warn(struct pmem_st *store, OSet *set) { struct pmem_st *new = VG_(OSetGen_AllocNode)(set, - (SizeT)sizeof(struct pmem_st)); - *new=*store; + (SizeT) sizeof(struct pmem_st)); + *new = *store; + add_warning_event(pmem.multiple_stores, &pmem.multiple_stores_reg, - new, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); + new, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); } /** @@ -775,9 +785,18 @@ split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, tl_assert(False); } +/** + * \brief Splits-adjusts the two given stores in memory location information array so that they do not overlap. + * + * \param[in,out] old The old store that will be modified. + * \param[in] new The new store that will not be modified. + * \param[in,out] set The set the splitted stores are inserted into. + * \param[in,out] clb The callback to be called for the overlapping part of the + * old store. + */ static void array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, - split_clb clb) + array_split_clb clb) { Addr new_max = new->addr + new->size; Addr old_max = old->addr + old->size; @@ -785,7 +804,7 @@ array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, /* new store encapsulates old, it needs to be removed */ if (old->addr >= new->addr && old_max <= new_max) { old->is_delete = True; - clb(old, set, True); + clb(old, set); return; } @@ -807,16 +826,14 @@ array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, /* clb the cut out fragment with the old ExeContext */ tmp = *new; tmp.context = old->context; - clb(&tmp, set, False); + clb(&tmp, set); } else { - /* old starts before new */ - /* callback for removed part */ tmp = *old; tmp.addr = new->addr; tmp.size = old_max - new->addr; /* adjust leftover */ - clb(&tmp, set, False); + clb(&tmp, set); old->value >>= old_max - new->addr; old->size = new->addr - old->addr; } @@ -830,7 +847,7 @@ array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, /* callback for removed part */ tmp = *old; tmp.size -= old_max - new_max; - clb(&tmp, set, False); + clb(&tmp, set); /* adjust leftover */ old->addr = new_max; old->size = old_max - new_max; @@ -878,67 +895,86 @@ add_and_merge_store(struct pmem_st *region) VG_(OSetGen_Insert)(pmem.pmem_stores, region); } -static void update_array_metadata_minandmax(struct pmem_st *store) +/** + * \brief Update minimum and maximum address of current metadata in arr_md structure. + * + * param[in] store the store used to update minimum and maximum address of current metadata. + */ +static void +update_array_metadata_minandmax(struct pmem_st *store) { Addr store_max = store->addr + store->size; - struct arr_md* m_data=pmem.info_array.m_data+pmem.info_array.m_index; - if (m_data->max_addr == -1 && m_data->min_addr == -1) - { + struct arr_md* m_data = pmem.info_array.m_data + pmem.info_array.m_index; + + if (m_data->max_addr == -1 && m_data->min_addr == -1) { m_data->min_addr = store->addr; m_data->max_addr = store_max; } + if (m_data->min_addr > store->addr) m_data->min_addr = store->addr; + if (m_data->max_addr < store_max) m_data->max_addr = store_max; return; } -static int cmp_with_arr_minandmax(struct pmem_st *p_st,int index) +/** +* \brief Compare regions with the interval of one metadata (decided by minimum and maximum address) in arr_md structure. +* \param[in] p_st the store to compare. +* \param[in] index the index to indicate with which metadata the store compares. +* \return -1 if the region doesn't overlap with the interval of the metadata, 1 if the interval of one metadata includes the region and 0 if the interval of the metadata overlaps with the region. +*/ +static int +cmp_with_arr_minandmax(struct pmem_st *p_st, int index) { Addr p_st_max = p_st->addr + p_st->size; - struct arr_md* m_data=pmem.info_array.m_data+index; - if ((p_st->addr > m_data->max_addr) || (p_st_max < m_data->min_addr)) + struct arr_md* m_data = pmem.info_array.m_data + index; + + if ((p_st->addr > m_data->max_addr) || (p_st_max < m_data->min_addr)) { return -1; - else if (m_data->min_addr <= p_st->addr && p_st_max <= m_data->max_addr) + } else if (m_data->min_addr <= p_st->addr && p_st_max <= m_data->max_addr) { return 1; - else + } else { return 0; + } } - /** - * Handle multiple overwrites for store information array. + * Handle multiple overwrites in memory location information array. + * \param[in,out] store the store to be handled. */ static void -array_handle_with_mult_stores(struct pmem_st *store){ +array_handle_with_mult_stores(struct pmem_st *store) +{ struct pmem_st *existing; - /* remove any overlapping stores from the collection */ - for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ - if (cmp_with_arr_minandmax(store,s_index) != -1) - { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) - { - if (LIKELY(pmem.info_array.pmem_stores[i].is_delete != True)) - existing = pmem.info_array.pmem_stores + i; - else - continue; - if (cmp_pmem_st(existing, store) == 0) - { - if ((store->block_num - existing->block_num) < pmem.store_sb_indiff && existing->addr == store->addr && existing->size == store->size && existing->value == store->value) - { - existing->is_delete = True; + /* remove any overlapping stores from the collection */ + for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { + if (cmp_with_arr_minandmax(store, s_index) != -1) { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { + if (LIKELY(pmem.info_array.pmem_stores[i].is_delete != True)) { + existing = pmem.info_array.pmem_stores + i; + } else { continue; } - array_split_stores(existing, store, pmem.pmem_stores, - array_add_mult_overwrite_warn); + + if (cmp_pmem_st(existing, store) == 0) { + if ((store->block_num - existing->block_num) < pmem.store_sb_indiff && existing->addr == store->addr && + existing->size == store->size && existing->value == store->value) { + existing->is_delete = True; + continue; + } + + array_split_stores(existing, store, pmem.pmem_stores, + array_add_mult_overwrite_warn); + } } } } - } } + /** * \brief Handle a new store checking for multiple overwrites. * This should be called when track_multiple_stores is enabled. @@ -948,6 +984,7 @@ array_handle_with_mult_stores(struct pmem_st *store){ static void handle_with_mult_stores(struct pmem_st *store) { + /* handle multiple overwrite in the array structure */ array_handle_with_mult_stores(store); struct pmem_st *existing; @@ -982,27 +1019,24 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) { if (LIKELY(!is_pmem_access(addr, size))) return; + struct pmem_st *store; - UWord old_index=pmem.info_array.m_data[pmem.info_array.m_index].end_index; - if (LIKELY(old_index < MAX_ARRAY_NUM)) - { + UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; + + /* Insert information into the array when the array is not full, otherwise, insert information into pmem.pmem_stores */ + if (LIKELY(old_index < MAX_ARRAY_NUM)) { store = pmem.info_array.pmem_stores + old_index; - } - else - { + } else { store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, (SizeT) sizeof (struct pmem_st)); - //store->index=db_pmem_store_index; - //db_pmem_store_index++; } - //struct pmem_st *store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, - // (SizeT) sizeof (struct pmem_st)); + store->addr = addr; store->size = size; store->state = STST_DIRTY; store->block_num = sblocks; store->value = value; - store->is_delete=False; + store->is_delete = False; store->context = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); /* log the store, regardless if it is a double store */ @@ -1011,23 +1045,20 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) if (pmem.store_traces) pp_store_trace(store, pmem.store_traces_depth); } - if (pmem.track_multiple_stores){ + + if (pmem.track_multiple_stores) { handle_with_mult_stores(store); - if (UNLIKELY(old_index >= MAX_ARRAY_NUM)){ + /* Insert information */ + if (UNLIKELY(old_index >= MAX_ARRAY_NUM)) { VG_(OSetGen_Insert)(pmem.pmem_stores, store); - } - else - { + } else { pmem.info_array.m_data[pmem.info_array.m_index].end_index++; update_array_metadata_minandmax(store); } - } - else{ - if (UNLIKELY(old_index >= MAX_ARRAY_NUM)){ + } else { + if (UNLIKELY(old_index >= MAX_ARRAY_NUM)) { add_and_merge_store(store); - } - else - { + } else { pmem.info_array.m_data[pmem.info_array.m_index].end_index++; update_array_metadata_minandmax(store); } @@ -1345,37 +1376,34 @@ add_event_dw(IRSB *sb, IRAtom *daddr, Int dsize, IRAtom *value) } /** -* \brief fence processing for store information array +* \brief process fence instructions in memory location information array */ -static void array_process_fence(void){ - struct pmem_st *being_fenced = NULL; -for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ - if (pmem.info_array.m_data[s_index].state != ALL_FLUSHED) - { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) - { - being_fenced = pmem.info_array.pmem_stores + i; - - if (being_fenced->state == STST_FLUSHED||being_fenced->is_delete==True) - { - continue; - } - else - { - struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); - *new=*being_fenced; - add_and_merge_store(new); +static void +array_process_fence(void) +{ + struct pmem_st *being_fenced = NULL; + for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { + if (pmem.info_array.m_data[s_index].state != ALL_FLUSHED) { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { + being_fenced = pmem.info_array.pmem_stores + i; + + if (being_fenced->state == STST_FLUSHED || being_fenced->is_delete == True) { + continue; + } else { + struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + *new = *being_fenced; + add_and_merge_store(new); + } } } - } -} -/* reset store information array */ - pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; + /* reset memory location information array */ + pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; pmem.info_array.m_data[0].state = NO_FLUSHED; - pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index=0; - pmem.info_array.m_index=0; + pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index = 0; + pmem.info_array.m_index = 0; } + /** * \brief Register a fence. * @@ -1402,155 +1430,146 @@ do_fence(void) VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, &temp); } } + array_process_fence(); } -/* set up a new metadata */ -static void init_m_data(void){ + +/** +* \brief set up a new metadata. +*/ +static void +init_m_data(void) +{ pmem.info_array.m_index++; - struct arr_md* pm_data=pmem.info_array.m_data+pmem.info_array.m_index; + struct arr_md* pm_data = pmem.info_array.m_data + pmem.info_array.m_index; pm_data->min_addr = pm_data->max_addr = -1; pm_data->state = NO_FLUSHED; - pm_data->end_index=pm_data->start_index=pmem.info_array.m_data[pmem.info_array.m_index-1].end_index; - + pm_data->end_index = pm_data->start_index = pmem.info_array.m_data[pmem.info_array.m_index-1].end_index; } /** -* \brief writeback processing for store information array +* \brief processing flush instruction in memory location information array. +* +* \param[in] base The base address of the flush. +* \param[in] size The size of the flush in bytes. +* \return true if the flush matches any memory location information in the array, otherwise returns false. */ static Bool -array_process_flush(UWord base, UWord size){ +array_process_flush(UWord base, UWord size) +{ struct pmem_st flush_info = {0}; if (LIKELY(pmem.force_flush_align == False)) { flush_info.addr = base; flush_info.size = size; - } - else - { + } else { /* align flushed memory */ flush_info.addr = base & ~(pmem.flush_align_size - 1); flush_info.size = roundup(size, pmem.flush_align_size); } - /* unfortunately lookup doesn't work here, the oset is an avl tree */ - Addr flush_max = flush_info.addr + flush_info.size; struct pmem_st *being_flushed; Bool valid_flush = False; - /*================================array=============================*/ - for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ - /* directly mark this writeback interval */ - if (flush_max >= pmem.info_array.m_data[s_index].max_addr && pmem.info_array.m_data[s_index].min_addr >= flush_info.addr && pmem.info_array.m_data[s_index].state == NO_FLUSHED) - { - pmem.info_array.m_data[s_index].state = ALL_FLUSHED; - valid_flush = True; - } - /* directly skip this writeback interval */ - else if (flush_max < pmem.info_array.m_data[s_index].min_addr || pmem.info_array.m_data[s_index].max_addr < flush_info.addr) - { - continue; - } - /* go into this writeback interval and traverse store information one by one */ - else - { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) - { - being_flushed = pmem.info_array.pmem_stores + i; - if (being_flushed->is_delete == True) - { - being_flushed->state = STST_FLUSHED; - continue; - } - if (cmp_pmem_st(&flush_info, being_flushed) != 0) - continue; + for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { + if (flush_max >= pmem.info_array.m_data[s_index].max_addr && pmem.info_array.m_data[s_index].min_addr >= flush_info.addr && + pmem.info_array.m_data[s_index].state == NO_FLUSHED) { + pmem.info_array.m_data[s_index].state = ALL_FLUSHED; valid_flush = True; - /* check for multiple flushes of stores */ - if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) - { - if (pmem.check_flush) - { - /* multiple flush of the same store - probably an issue */ - struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.3", - sizeof(struct pmem_st)); - *wrong_flush = *being_flushed; - wrong_flush->state = STST_FLUSHED; - // VG_(umsg)("=======pmem_index=%d========\n",wrong_flush->index); - add_warning_event(pmem.redundant_flushes, - &pmem.redundant_flushes_reg, - wrong_flush, MAX_FLUSH_ERROR_EVENTS, - print_redundant_flush_error); - } - continue; - } + } else if (flush_max < pmem.info_array.m_data[s_index].min_addr || pmem.info_array.m_data[s_index].max_addr < flush_info.addr) { + continue; + } else { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { + being_flushed = pmem.info_array.pmem_stores + i; - being_flushed->state = STST_FLUSHED; - pmem.info_array.m_data[s_index].state = PART_FLUSHED; - /* store starts before base flush address */ - if (being_flushed->addr < flush_info.addr) - { - /* split and reinsert */ - struct pmem_st *split; - UWord old_index= pmem.info_array.m_data[pmem.info_array.m_index].end_index; - if (LIKELY(old_index < MAX_ARRAY_NUM)) - { - split = pmem.info_array.pmem_stores + old_index; - - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } - else - { - split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); - } - *split = *being_flushed; - split->size = flush_info.addr - being_flushed->addr; - split->state = STST_DIRTY; - - /* adjust original */ - being_flushed->addr = flush_info.addr; - being_flushed->size -= split->size; - if (old_index >= MAX_ARRAY_NUM){ - add_and_merge_store(split); + if (being_flushed->is_delete == True) { + being_flushed->state = STST_FLUSHED; + continue; } - /* reset iter */ - } - /* end of store is behind max flush */ - if (being_flushed->addr + being_flushed->size > flush_max) - { - /* split and reinsert */ - UWord old_index= pmem.info_array.m_data[pmem.info_array.m_index].end_index; - struct pmem_st *split; - if (LIKELY(old_index < MAX_ARRAY_NUM)) - { - split = pmem.info_array.pmem_stores + old_index; - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } - else - { - split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + if (cmp_pmem_st(&flush_info, being_flushed) != 0) + continue; + + valid_flush = True; + /* check for multiple flushes of stores */ + if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) { + if (pmem.check_flush) { + /* multiple flush of the same store - probably an issue */ + struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.3", + sizeof(struct pmem_st)); + *wrong_flush = *being_flushed; + wrong_flush->state = STST_FLUSHED; + add_warning_event(pmem.redundant_flushes, + &pmem.redundant_flushes_reg, + wrong_flush, MAX_FLUSH_ERROR_EVENTS, + print_redundant_flush_error); + } + continue; } - *split = *being_flushed; - split->addr = flush_max; - split->size = being_flushed->addr + being_flushed->size - flush_max; - split->state = STST_DIRTY; - - /* adjust original */ - being_flushed->size -= split->size; - if (old_index >= MAX_ARRAY_NUM){ + + being_flushed->state = STST_FLUSHED; + pmem.info_array.m_data[s_index].state = PART_FLUSHED; + /* store starts before base flush address */ + if (being_flushed->addr < flush_info.addr) { + /* split and reinsert */ + struct pmem_st *split; + UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; + + if (LIKELY(old_index < MAX_ARRAY_NUM)) { + split = pmem.info_array.pmem_stores + old_index; + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } else { + split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + } + + *split = *being_flushed; + split->size = flush_info.addr - being_flushed->addr; + split->state = STST_DIRTY; + + /* adjust original */ + being_flushed->addr = flush_info.addr; + being_flushed->size -= split->size; + if (old_index >= MAX_ARRAY_NUM) { add_and_merge_store(split); + } + /* reset iter */ } + /* end of store is behind max flush */ + if (being_flushed->addr + being_flushed->size > flush_max) { + /* split and reinsert */ + UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; + struct pmem_st *split; + + if (LIKELY(old_index < MAX_ARRAY_NUM)) { + split = pmem.info_array.pmem_stores + old_index; + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } else { + split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + } + + *split = *being_flushed; + split->addr = flush_max; + split->size = being_flushed->addr + being_flushed->size - flush_max; + split->state = STST_DIRTY; + + /* adjust original */ + being_flushed->size -= split->size; + if (old_index >= MAX_ARRAY_NUM) { + add_and_merge_store(split); + } + + } } } } -} - if (pmem.info_array.m_data[pmem.info_array.m_index].state != NO_FLUSHED){ + if (pmem.info_array.m_data[pmem.info_array.m_index].state != NO_FLUSHED) { init_m_data(); } - return valid_flush; + return valid_flush; } /** @@ -1566,7 +1585,8 @@ array_process_flush(UWord base, UWord size){ static void do_flush(UWord base, UWord size) { - Bool array_valid_flush=array_process_flush(base, size); + Bool array_valid_flush = array_process_flush(base, size); + struct pmem_st flush_info = {0}; if (LIKELY(pmem.force_flush_align == False)) { @@ -2281,83 +2301,70 @@ pmc_handle_client_request(ThreadId tid, UWord *arg, UWord *ret ) temp_info.addr = arg[1]; temp_info.size = arg[2]; - /* remove regions from store information array*/ + /* remove regions from memory location information array */ struct pmem_st *modified_entry = NULL; struct pmem_st *region = &temp_info; UWord old_index; - for(int s_index=0;s_index<=pmem.info_array.m_index;s_index++){ - if (cmp_with_arr_minandmax(&temp_info,s_index) != -1) - { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) - { - //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); - modified_entry = pmem.info_array.pmem_stores + i; - if (modified_entry->is_delete == True) - continue; - if (cmp_pmem_st(region, modified_entry) == 0) - { - SizeT region_max_addr = region->addr + region->size; - //struct pmem_st tmp; - SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; - if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < - region_max_addr)) - { - /* modified entry fully within removed region */ - modified_entry->is_delete = True; - } - else if ((modified_entry->addr < region->addr) && - (mod_entry_max_addr > region_max_addr)) - { - /* modified entry is larger than the removed region - slice */ - modified_entry->size = region->addr - modified_entry->addr; - - // VG_(OSetGen_Insert)(region_set, modified_entry); - struct pmem_st *new_region; - old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; - if (old_index>= MAX_ARRAY_NUM){ - new_region = VG_(OSetGen_AllocNode)(pmem.pmem_stores, - sizeof(struct pmem_st)); - } - else - { - new_region = pmem.info_array.pmem_stores + old_index; - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } - new_region->addr = region_max_addr; - new_region->size = mod_entry_max_addr - new_region->addr; - if (old_index >= MAX_ARRAY_NUM){ - add_and_merge_store(new_region); + for (int s_index=0; s_index<=pmem.info_array.m_index; s_index++) { + if (cmp_with_arr_minandmax(&temp_info, s_index) != -1) { + for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++){ + //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); + modified_entry = pmem.info_array.pmem_stores + i; + + if (modified_entry->is_delete == True) + continue; + + if (cmp_pmem_st(region, modified_entry) == 0) { + SizeT region_max_addr = region->addr + region->size; + //struct pmem_st tmp; + SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; + if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < + region_max_addr)) { + /* modified entry fully within removed region */ + modified_entry->is_delete = True; + } else if ((modified_entry->addr < region->addr) && + (mod_entry_max_addr > region_max_addr)) { + /* modified entry is larger than the removed region - slice */ + modified_entry->size = region->addr - modified_entry->addr; + + struct pmem_st *new_region; + old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; + + if (old_index >= MAX_ARRAY_NUM) { + new_region = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + (SizeT) sizeof(struct pmem_st)); + } else { + new_region = pmem.info_array.pmem_stores + old_index; + pmem.info_array.m_data[pmem.info_array.m_index].end_index++; + } + + new_region->addr = region_max_addr; + new_region->size = mod_entry_max_addr - new_region->addr; + + if (old_index >= MAX_ARRAY_NUM) { + add_and_merge_store(new_region); + } + + } else if ((modified_entry->addr >= region->addr) && + (mod_entry_max_addr > region_max_addr)) { + /* head overlaps */ + modified_entry->size -= region_max_addr - modified_entry->addr; + modified_entry->addr = region_max_addr; + // VG_(OSetGen_Insert)(region_set, modified_entry); + } else if ((mod_entry_max_addr <= region_max_addr) && + (region->addr > modified_entry->addr)) { + /* tail overlaps */ + modified_entry->size = region->addr - modified_entry->addr; + } else { + /* exact match */ + modified_entry->is_delete = True; } - - } - else if ((modified_entry->addr >= region->addr) && - (mod_entry_max_addr > region_max_addr)) - { - /* head overlaps */ - modified_entry->size -= region_max_addr - modified_entry->addr; - modified_entry->addr = region_max_addr; - // VG_(OSetGen_Insert)(region_set, modified_entry); - } - else if ((mod_entry_max_addr <= region_max_addr) && - (region->addr > modified_entry->addr)) - { - /* tail overlaps */ - modified_entry->size = region->addr - modified_entry->addr; - - // VG_(OSetGen_Insert)(region_set, modified_entry); - } - else - { - /* exact match */ - modified_entry->is_delete = True; } } } } - } - - /* remove regions from pmem_stores Oset*/ + /* remove regions from pmem_stores Oset*/ remove_region(&temp_info, pmem.pmem_stores); break; } @@ -2496,13 +2503,13 @@ static void pmc_post_clo_init(void) { pmem.info_array.pmem_stores = VG_(malloc)("pmc.main.cpci.7", - MAX_ARRAY_NUM * sizeof(struct pmem_st)); + MAX_ARRAY_NUM * sizeof(struct pmem_st)); pmem.info_array.m_index = 0; pmem.info_array.m_data = VG_(malloc)("pmc.main.cpci.8", - MAX_ARRAY_NUM * sizeof(struct arr_md)); + MAX_ARRAY_NUM * sizeof(struct arr_md)); pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; pmem.info_array.m_data[0].state = NO_FLUSHED; - pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index=0; + pmem.info_array.m_data[0].end_index = pmem.info_array.m_data[0].start_index = 0; pmem.pmem_stores = VG_(OSetGen_Create)(/*keyOff*/0, cmp_pmem_st, VG_(malloc), "pmc.main.cpci.1", VG_(free)); From f600a97852556f2806ad9fec50b4cdd8e96fd748 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Thu, 27 May 2021 14:31:34 +0800 Subject: [PATCH 09/11] (1) Dynamically grow the array structure; (2) unify this code; (3) remove the is_delete flag; (4) abstract the process of inserting data; --- pmemcheck/pmc_include.h | 1 - pmemcheck/pmc_main.c | 518 +++++++++++++++++----------------------- 2 files changed, 216 insertions(+), 303 deletions(-) diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index eb8095aafa..adb5975909 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -41,7 +41,6 @@ struct pmem_st { STST_DIRTY, STST_FLUSHED, } state; - Bool is_delete; }; /*------------------------------------------------------------*/ diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index d46454b3b3..9a941b2d2f 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -60,23 +60,31 @@ #define MAX_PATH_SIZE 4096 /** Max allowable length of memory location information array */ -#define MAX_ARRAY_NUM 1000UL +#define INIT_STORE_ARRAY_MAX_NUM 1000UL /** Defining memory location information array structure */ struct pmem_stores_array { /** Index of current metadata */ UWord m_index; struct pmem_st *pmem_stores; - struct arr_md* m_data; + struct arr_md *m_data; + ULong max_array_num; + ULong max_m_data_num; }; -/** Holds parameters and runtime data */ -static struct pmem_ops { +/** Hybrid structure to store information of persistent memory **/ + +static struct pmem_hybrid_struct { + /** Array of stores to persistent memory */ struct pmem_stores_array info_array; /** Set of stores to persistent memory. */ OSet *pmem_stores; +} pInfo; + +/** Holds parameters and runtime data */ +static struct pmem_ops { /** Set of registered persistent memory regions. */ OSet *pmem_mappings; @@ -177,6 +185,27 @@ static struct pmem_st *lastPMEM = NULL; /** Cached last non-pmem region. */ static struct pmem_st *lastNONPMEM = NULL; +/** +* \brief Allocate a node in the store information array. +* \return The pointer of the allocated node +*/ +static struct pmem_st * +pInfo_AllocNodeInArray(void) +{ + struct pmem_st *store; + UWord old_index = pInfo.info_array.m_data[pInfo.info_array.m_index].end_index; + + /* grow store information array if the array is not enough */ + if (UNLIKELY(old_index >= pInfo.info_array.max_array_num)) { + pInfo.info_array.max_array_num *= 2; + pInfo.info_array.pmem_stores = VG_(realloc)("grow info_array structure", pInfo.info_array.pmem_stores, + pInfo.info_array.max_array_num); + } + + store = pInfo.info_array.pmem_stores + old_index; + return store; +} + /** * \brief Check if a given store overlaps with registered persistent memory * regions. @@ -312,31 +341,31 @@ print_store_stats(void) { /* print store states of the array */ struct pmem_st *tmp; - for (int s_index=0; s_index<=pmem.info_array.m_index; s_index++) { - for (int i=pmem.info_array.m_data[s_index].start_index; iis_delete == True) + if (tmp->size == 0) continue; - if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED) + if (pInfo.info_array.m_data[s_index].state == ALL_FLUSHED) tmp->state = STST_FLUSHED; - struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + struct pmem_st *new = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, sizeof(struct pmem_st)); *new = *tmp; add_and_merge_store(new); } } VG_(umsg)("Number of stores not made persistent: %u\n", VG_(OSetGen_Size) - (pmem.pmem_stores)); + (pInfo.pmem_stores)); - if (VG_(OSetGen_Size)(pmem.pmem_stores) != 0) { - VG_(OSetGen_ResetIter)(pmem.pmem_stores); + if (VG_(OSetGen_Size)(pInfo.pmem_stores) != 0) { + VG_(OSetGen_ResetIter)(pInfo.pmem_stores); UWord total = 0; Int i = 0; VG_(umsg)("Stores not made persistent properly:\n"); - while ((tmp = VG_(OSetGen_Next)(pmem.pmem_stores)) != NULL) { + while ((tmp = VG_(OSetGen_Next)(pInfo.pmem_stores)) != NULL) { VG_(umsg)("[%d] ", i); VG_(pp_ExeContext)(tmp->context); VG_(umsg)("\tAddress: 0x%lx\tsize: %llu\tstate: %s\n", @@ -690,23 +719,6 @@ add_mult_overwrite_warn(struct pmem_st *store, OSet *set, Bool preallocated) store, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); } -/** - * \brief Issues a warning event with the given store as the offender for the array structure. - * - * \param[in,out] store The store to be registered as a warning. - * \param[in,out] set The set that stores memory location information. - */ -static void -array_add_mult_overwrite_warn(struct pmem_st *store, OSet *set) -{ - struct pmem_st *new = VG_(OSetGen_AllocNode)(set, - (SizeT) sizeof(struct pmem_st)); - *new = *store; - - add_warning_event(pmem.multiple_stores, &pmem.multiple_stores_reg, - new, MAX_MULT_OVERWRITES, print_max_poss_overwrites_error); -} - /** * \brief Splits-adjusts the two given stores so that they do not overlap. * @@ -720,15 +732,21 @@ array_add_mult_overwrite_warn(struct pmem_st *store, OSet *set) */ static void split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, - split_clb clb) + split_clb clb, Bool is_array) { Addr new_max = new->addr + new->size; Addr old_max = old->addr + old->size; /* new store encapsulates old, it needs to be removed */ if (old->addr >= new->addr && old_max <= new_max) { - VG_(OSetGen_Remove)(set, old); - clb(old, set, True); + if (is_array == True) { + clb(old, set, False); + /* using size =0 to mark this information as deleted */ + old->size = 0; + } else { + VG_(OSetGen_Remove)(set, old); + clb(old, set, True); + } return; } @@ -785,81 +803,6 @@ split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, tl_assert(False); } -/** - * \brief Splits-adjusts the two given stores in memory location information array so that they do not overlap. - * - * \param[in,out] old The old store that will be modified. - * \param[in] new The new store that will not be modified. - * \param[in,out] set The set the splitted stores are inserted into. - * \param[in,out] clb The callback to be called for the overlapping part of the - * old store. - */ -static void -array_split_stores(struct pmem_st *old, const struct pmem_st *new, OSet *set, - array_split_clb clb) -{ - Addr new_max = new->addr + new->size; - Addr old_max = old->addr + old->size; - - /* new store encapsulates old, it needs to be removed */ - if (old->addr >= new->addr && old_max <= new_max) { - old->is_delete = True; - clb(old, set); - return; - } - - struct pmem_st tmp; - if (old->addr < new->addr) { - /* the new store is within the old store */ - if (old_max > new_max) { - struct pmem_st *after = VG_(OSetGen_AllocNode)(set, - (SizeT) sizeof(struct pmem_st)); - *after = *old; - after->addr = new_max; - after->size = old_max - new_max; - after->value &= (1 << (after->size * 8 + 1)) - 1; - /* adjust the size and value of the old entry */ - old->value >>= old_max - new->addr; - old->size = new->addr - old->addr; - /* insert the new store fragment */ - VG_(OSetGen_Insert)(set, after); - /* clb the cut out fragment with the old ExeContext */ - tmp = *new; - tmp.context = old->context; - clb(&tmp, set); - } else { - /* callback for removed part */ - tmp = *old; - tmp.addr = new->addr; - tmp.size = old_max - new->addr; - /* adjust leftover */ - clb(&tmp, set); - old->value >>= old_max - new->addr; - old->size = new->addr - old->addr; - } - return; - } - - /* now old->addr >= new->addr */ - - /* end of old is behind end of new */ - if (old_max > new_max) { - /* callback for removed part */ - tmp = *old; - tmp.size -= old_max - new_max; - clb(&tmp, set); - /* adjust leftover */ - old->addr = new_max; - old->size = old_max - new_max; - old->value &= (1 << (old->size * 8 + 1)) - 1; - return; - } - - /* you should never end up here */ - tl_assert(False); -} - - /** * \brief Add and merges adjacent stores if possible. * Should not be used if track_multiple_stores is enabled. @@ -871,15 +814,15 @@ add_and_merge_store(struct pmem_st *region) { struct pmem_st *old_entry; /* remove old overlapping entries */ - while ((old_entry = VG_(OSetGen_Lookup)(pmem.pmem_stores, region)) != NULL) - split_stores(old_entry, region, pmem.pmem_stores, free_clb); + while ((old_entry = VG_(OSetGen_Lookup)(pInfo.pmem_stores, region)) != NULL) + split_stores(old_entry, region, pInfo.pmem_stores, free_clb, False); /* check adjacent entries */ struct pmem_st search_entry = *region; search_entry.addr -= 1; int i = 0; for (i = 0; i < 2; ++i, search_entry.addr += 2) { - old_entry = VG_(OSetGen_Lookup)(pmem.pmem_stores, &search_entry); + old_entry = VG_(OSetGen_Lookup)(pInfo.pmem_stores, &search_entry); /* no adjacent entry */ if (old_entry == NULL) continue; @@ -889,10 +832,10 @@ add_and_merge_store(struct pmem_st *region) /* registering overlapping stores, glue them together */ merge_stores(region, old_entry); - old_entry = VG_(OSetGen_Remove)(pmem.pmem_stores, &search_entry); - VG_(OSetGen_FreeNode)(pmem.pmem_stores, old_entry); + old_entry = VG_(OSetGen_Remove)(pInfo.pmem_stores, &search_entry); + VG_(OSetGen_FreeNode)(pInfo.pmem_stores, old_entry); } - VG_(OSetGen_Insert)(pmem.pmem_stores, region); + VG_(OSetGen_Insert)(pInfo.pmem_stores, region); } /** @@ -904,7 +847,7 @@ static void update_array_metadata_minandmax(struct pmem_st *store) { Addr store_max = store->addr + store->size; - struct arr_md* m_data = pmem.info_array.m_data + pmem.info_array.m_index; + struct arr_md* m_data = pInfo.info_array.m_data + pInfo.info_array.m_index; if (m_data->max_addr == -1 && m_data->min_addr == -1) { m_data->min_addr = store->addr; @@ -930,7 +873,7 @@ static int cmp_with_arr_minandmax(struct pmem_st *p_st, int index) { Addr p_st_max = p_st->addr + p_st->size; - struct arr_md* m_data = pmem.info_array.m_data + index; + struct arr_md* m_data = pInfo.info_array.m_data + index; if ((p_st->addr > m_data->max_addr) || (p_st_max < m_data->min_addr)) { return -1; @@ -951,24 +894,27 @@ array_handle_with_mult_stores(struct pmem_st *store) struct pmem_st *existing; /* remove any overlapping stores from the collection */ - for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { + for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { if (cmp_with_arr_minandmax(store, s_index) != -1) { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { - if (LIKELY(pmem.info_array.pmem_stores[i].is_delete != True)) { - existing = pmem.info_array.pmem_stores + i; + for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { + if (LIKELY(pInfo.info_array.pmem_stores[i].size != 0)) { + existing = pInfo.info_array.pmem_stores + i; } else { continue; } if (cmp_pmem_st(existing, store) == 0) { - if ((store->block_num - existing->block_num) < pmem.store_sb_indiff && existing->addr == store->addr && - existing->size == store->size && existing->value == store->value) { - existing->is_delete = True; + if ((store->block_num - existing->block_num) < pmem.store_sb_indiff + && existing->addr == store->addr + && existing->size == store->size + && existing->value == store->value) { + /* using size = 0 to mark this information as deleted */ + existing->size = 0; continue; } - array_split_stores(existing, store, pmem.pmem_stores, - array_add_mult_overwrite_warn); + split_stores(existing, store, pInfo.pmem_stores, + add_mult_overwrite_warn, True); } } } @@ -989,22 +935,21 @@ handle_with_mult_stores(struct pmem_st *store) struct pmem_st *existing; /* remove any overlapping stores from the collection */ - while ((existing = VG_(OSetGen_Lookup)(pmem.pmem_stores, store)) != + while ((existing = VG_(OSetGen_Lookup)(pInfo.pmem_stores, store)) != NULL) { /* check store indifference */ if ((store->block_num - existing->block_num) < pmem.store_sb_indiff && existing->addr == store->addr && existing->size == store->size && existing->value == store->value) { - VG_(OSetGen_Remove)(pmem.pmem_stores, store); - VG_(OSetGen_FreeNode)(pmem.pmem_stores, existing); + VG_(OSetGen_Remove)(pInfo.pmem_stores, store); + VG_(OSetGen_FreeNode)(pInfo.pmem_stores, existing); continue; } - split_stores(existing, store, pmem.pmem_stores, - add_mult_overwrite_warn); + split_stores(existing, store, pInfo.pmem_stores, + add_mult_overwrite_warn, False); } - /* it is now safe to insert the new store */ - //VG_(OSetGen_Insert)(pmem.pmem_stores, store); + /* Inserting the new store happens after return*/ } /** @@ -1020,23 +965,13 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) if (LIKELY(!is_pmem_access(addr, size))) return; - struct pmem_st *store; - UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; - - /* Insert information into the array when the array is not full, otherwise, insert information into pmem.pmem_stores */ - if (LIKELY(old_index < MAX_ARRAY_NUM)) { - store = pmem.info_array.pmem_stores + old_index; - } else { - store = VG_(OSetGen_AllocNode)(pmem.pmem_stores, - (SizeT) sizeof (struct pmem_st)); - } + struct pmem_st *store = pInfo_AllocNodeInArray(); store->addr = addr; store->size = size; store->state = STST_DIRTY; store->block_num = sblocks; store->value = value; - store->is_delete = False; store->context = VG_(record_ExeContext)(VG_(get_running_tid)(), 0); /* log the store, regardless if it is a double store */ @@ -1048,22 +983,12 @@ trace_pmem_store(Addr addr, SizeT size, UWord value) if (pmem.track_multiple_stores) { handle_with_mult_stores(store); - /* Insert information */ - if (UNLIKELY(old_index >= MAX_ARRAY_NUM)) { - VG_(OSetGen_Insert)(pmem.pmem_stores, store); - } else { - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - update_array_metadata_minandmax(store); - } - } else { - if (UNLIKELY(old_index >= MAX_ARRAY_NUM)) { - add_and_merge_store(store); - } else { - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - update_array_metadata_minandmax(store); - } } + /* Insert information */ + pInfo.info_array.m_data[pInfo.info_array.m_index].end_index++; + update_array_metadata_minandmax(store); + /* do transaction check */ handle_tx_store(store); } @@ -1382,15 +1307,15 @@ static void array_process_fence(void) { struct pmem_st *being_fenced = NULL; - for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { - if (pmem.info_array.m_data[s_index].state != ALL_FLUSHED) { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { - being_fenced = pmem.info_array.pmem_stores + i; + for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { + if (pInfo.info_array.m_data[s_index].state != ALL_FLUSHED) { + for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { + being_fenced = pInfo.info_array.pmem_stores + i; - if (being_fenced->state == STST_FLUSHED || being_fenced->is_delete == True) { + if (being_fenced->state == STST_FLUSHED || being_fenced->size == 0) { continue; } else { - struct pmem_st *new = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); + struct pmem_st *new = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, sizeof(struct pmem_st)); *new = *being_fenced; add_and_merge_store(new); } @@ -1398,12 +1323,71 @@ array_process_fence(void) } } /* reset memory location information array */ - pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; - pmem.info_array.m_data[0].state = NO_FLUSHED; - pmem.info_array.m_data[0].end_index=pmem.info_array.m_data[0].start_index = 0; - pmem.info_array.m_index = 0; + pInfo.info_array.m_data[0].min_addr = pInfo.info_array.m_data[0].max_addr = -1; + pInfo.info_array.m_data[0].state = NO_FLUSHED; + pInfo.info_array.m_data[0].end_index=pInfo.info_array.m_data[0].start_index = 0; + pInfo.info_array.m_index = 0; } +/** +* \brief Remove element from store information array +* \param[in] region The region to remove. +*/ +static void +remove_array_info(struct pmem_st *region) +{ + /* remove regions from memory location information array */ + struct pmem_st *modified_entry = NULL; + for (int s_index=0; s_index<=pInfo.info_array.m_index; s_index++) { + if (cmp_with_arr_minandmax(region, s_index) != -1) { + for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++){ + //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); + modified_entry = pInfo.info_array.pmem_stores + i; + + if (modified_entry->size == 0) + continue; + + if (cmp_pmem_st(region, modified_entry) == 0) { + SizeT region_max_addr = region->addr + region->size; + //struct pmem_st tmp; + SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; + if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < + region_max_addr)) { + /* modified entry fully within removed region */ + modified_entry->size = 0; + } else if ((modified_entry->addr < region->addr) && + (mod_entry_max_addr > region_max_addr)) { + /* modified entry is larger than the removed region - slice */ + modified_entry->size = region->addr - modified_entry->addr; + + struct pmem_st *new_region = pInfo_AllocNodeInArray(); + new_region = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, + (SizeT) sizeof(struct pmem_st)); + + new_region->addr = region_max_addr; + new_region->size = mod_entry_max_addr - new_region->addr; + + add_and_merge_store(new_region); + + } else if ((modified_entry->addr >= region->addr) && + (mod_entry_max_addr > region_max_addr)) { + /* head overlaps */ + modified_entry->size -= region_max_addr - modified_entry->addr; + modified_entry->addr = region_max_addr; + // VG_(OSetGen_Insert)(region_set, modified_entry); + } else if ((mod_entry_max_addr <= region_max_addr) && + (region->addr > modified_entry->addr)) { + /* tail overlaps */ + modified_entry->size = region->addr - modified_entry->addr; + } else { + /* mark this information as deleted if exact match */ + modified_entry->size = 0; + } + } + } + } + } +} /** * \brief Register a fence. * @@ -1418,16 +1402,16 @@ do_fence(void) VG_(emit)("|FENCE"); /* go through the stores and remove all flushed */ - VG_(OSetGen_ResetIter)(pmem.pmem_stores); + VG_(OSetGen_ResetIter)(pInfo.pmem_stores); struct pmem_st *being_fenced = NULL; - while ((being_fenced = VG_(OSetGen_Next)(pmem.pmem_stores)) != NULL) { + while ((being_fenced = VG_(OSetGen_Next)(pInfo.pmem_stores)) != NULL) { if (being_fenced->state == STST_FLUSHED) { /* remove it from the oset */ struct pmem_st temp = *being_fenced; - VG_(OSetGen_Remove)(pmem.pmem_stores, being_fenced); - VG_(OSetGen_FreeNode)(pmem.pmem_stores, being_fenced); + VG_(OSetGen_Remove)(pInfo.pmem_stores, being_fenced); + VG_(OSetGen_FreeNode)(pInfo.pmem_stores, being_fenced); /* reset the iterator (remove invalidated store) */ - VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, &temp); + VG_(OSetGen_ResetIterAt)(pInfo.pmem_stores, &temp); } } @@ -1440,11 +1424,16 @@ do_fence(void) static void init_m_data(void) { - pmem.info_array.m_index++; - struct arr_md* pm_data = pmem.info_array.m_data + pmem.info_array.m_index; - pm_data->min_addr = pm_data->max_addr = -1; - pm_data->state = NO_FLUSHED; - pm_data->end_index = pm_data->start_index = pmem.info_array.m_data[pmem.info_array.m_index-1].end_index; + if (UNLIKELY(pInfo.info_array.m_index >= (pInfo.info_array.max_array_num - 1))) { + pInfo.info_array.max_array_num *= 2; + pInfo.info_array.m_data = VG_(realloc)("grow info_array structure", pInfo.info_array.m_data, + pInfo.info_array.max_array_num); + } + pInfo.info_array.m_index++; + struct arr_md* pm_data = pInfo.info_array.m_data + pInfo.info_array.m_index; + pm_data->min_addr = pm_data->max_addr = -1; + pm_data->state = NO_FLUSHED; + pm_data->end_index = pm_data->start_index = pInfo.info_array.m_data[pInfo.info_array.m_index-1].end_index; } /** @@ -1473,19 +1462,19 @@ array_process_flush(UWord base, UWord size) struct pmem_st *being_flushed; Bool valid_flush = False; - for(int s_index=0; s_index <= pmem.info_array.m_index; s_index++) { - if (flush_max >= pmem.info_array.m_data[s_index].max_addr && pmem.info_array.m_data[s_index].min_addr >= flush_info.addr && - pmem.info_array.m_data[s_index].state == NO_FLUSHED) { + for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { + if (flush_max >= pInfo.info_array.m_data[s_index].max_addr && pInfo.info_array.m_data[s_index].min_addr >= flush_info.addr && + pInfo.info_array.m_data[s_index].state == NO_FLUSHED) { - pmem.info_array.m_data[s_index].state = ALL_FLUSHED; + pInfo.info_array.m_data[s_index].state = ALL_FLUSHED; valid_flush = True; - } else if (flush_max < pmem.info_array.m_data[s_index].min_addr || pmem.info_array.m_data[s_index].max_addr < flush_info.addr) { + } else if (flush_max < pInfo.info_array.m_data[s_index].min_addr || pInfo.info_array.m_data[s_index].max_addr < flush_info.addr) { continue; } else { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++) { - being_flushed = pmem.info_array.pmem_stores + i; + for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { + being_flushed = pInfo.info_array.pmem_stores + i; - if (being_flushed->is_delete == True) { + if (being_flushed->size == 0) { being_flushed->state = STST_FLUSHED; continue; } @@ -1495,7 +1484,7 @@ array_process_flush(UWord base, UWord size) valid_flush = True; /* check for multiple flushes of stores */ - if (pmem.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) { + if (pInfo.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) { if (pmem.check_flush) { /* multiple flush of the same store - probably an issue */ struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.3", @@ -1511,19 +1500,12 @@ array_process_flush(UWord base, UWord size) } being_flushed->state = STST_FLUSHED; - pmem.info_array.m_data[s_index].state = PART_FLUSHED; + pInfo.info_array.m_data[s_index].state = PART_FLUSHED; /* store starts before base flush address */ if (being_flushed->addr < flush_info.addr) { /* split and reinsert */ struct pmem_st *split; - UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; - - if (LIKELY(old_index < MAX_ARRAY_NUM)) { - split = pmem.info_array.pmem_stores + old_index; - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } else { - split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); - } + split = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, sizeof(struct pmem_st)); *split = *being_flushed; split->size = flush_info.addr - being_flushed->addr; @@ -1532,24 +1514,16 @@ array_process_flush(UWord base, UWord size) /* adjust original */ being_flushed->addr = flush_info.addr; being_flushed->size -= split->size; - if (old_index >= MAX_ARRAY_NUM) { add_and_merge_store(split); - } /* reset iter */ } /* end of store is behind max flush */ if (being_flushed->addr + being_flushed->size > flush_max) { /* split and reinsert */ - UWord old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; struct pmem_st *split; - if (LIKELY(old_index < MAX_ARRAY_NUM)) { - split = pmem.info_array.pmem_stores + old_index; - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } else { - split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, sizeof(struct pmem_st)); - } + split = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, sizeof(struct pmem_st)); *split = *being_flushed; split->addr = flush_max; @@ -1558,15 +1532,12 @@ array_process_flush(UWord base, UWord size) /* adjust original */ being_flushed->size -= split->size; - if (old_index >= MAX_ARRAY_NUM) { - add_and_merge_store(split); - } - + add_and_merge_store(split); } } } } - if (pmem.info_array.m_data[pmem.info_array.m_index].state != NO_FLUSHED) { + if (pInfo.info_array.m_data[pInfo.info_array.m_index].state != NO_FLUSHED) { init_m_data(); } return valid_flush; @@ -1604,7 +1575,7 @@ do_flush(UWord base, UWord size) Bool valid_flush = False; /* try to find any region that overlaps with what we want to flush */ - struct pmem_st *f = VG_(OSetGen_Lookup)(pmem.pmem_stores, &flush_info); + struct pmem_st *f = VG_(OSetGen_Lookup)(pInfo.pmem_stores, &flush_info); /* * If there's none, then there's no point in searching for the first one * and iterating - just skip to the end where we report unneeded flushes. @@ -1629,7 +1600,7 @@ do_flush(UWord base, UWord size) first_overlapping_tmpl.size = 1; do { - first_overlapping = VG_(OSetGen_Lookup)(pmem.pmem_stores, + first_overlapping = VG_(OSetGen_Lookup)(pInfo.pmem_stores, &first_overlapping_tmpl); first_overlapping_tmpl.addr++; } while (first_overlapping == NULL); @@ -1638,10 +1609,10 @@ do_flush(UWord base, UWord size) struct pmem_st *being_flushed; /* reset the iterator */ - VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, first_overlapping); + VG_(OSetGen_ResetIterAt)(pInfo.pmem_stores, first_overlapping); int found = 0; - while ((being_flushed = VG_(OSetGen_Next)(pmem.pmem_stores)) != NULL){ + while ((being_flushed = VG_(OSetGen_Next)(pInfo.pmem_stores)) != NULL){ /* not an interesting entry, flush doesn't matter */ if (cmp_pmem_st(&flush_info, being_flushed) != 0) { @@ -1679,26 +1650,26 @@ do_flush(UWord base, UWord size) /* store starts before base flush address */ if (being_flushed->addr < flush_info.addr) { /* split and reinsert */ - struct pmem_st *split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + struct pmem_st *split = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, (SizeT)sizeof (struct pmem_st)); *split = *being_flushed; split->size = flush_info.addr - being_flushed->addr; split->state = STST_DIRTY; /* adjust original */ - VG_(OSetGen_Remove)(pmem.pmem_stores, being_flushed); + VG_(OSetGen_Remove)(pInfo.pmem_stores, being_flushed); being_flushed->addr = flush_info.addr; being_flushed->size -= split->size; - VG_(OSetGen_Insert)(pmem.pmem_stores, split); - VG_(OSetGen_Insert)(pmem.pmem_stores, being_flushed); + VG_(OSetGen_Insert)(pInfo.pmem_stores, split); + VG_(OSetGen_Insert)(pInfo.pmem_stores, being_flushed); /* reset iter */ - VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, being_flushed); + VG_(OSetGen_ResetIterAt)(pInfo.pmem_stores, being_flushed); } /* end of store is behind max flush */ if (being_flushed->addr + being_flushed->size > flush_max) { /* split and reinsert */ - struct pmem_st *split = VG_(OSetGen_AllocNode)(pmem.pmem_stores, + struct pmem_st *split = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, (SizeT)sizeof (struct pmem_st)); *split = *being_flushed; split->addr = flush_max; @@ -1706,12 +1677,12 @@ do_flush(UWord base, UWord size) split->state = STST_DIRTY; /* adjust original */ - VG_(OSetGen_Remove)(pmem.pmem_stores, being_flushed); + VG_(OSetGen_Remove)(pInfo.pmem_stores, being_flushed); being_flushed->size -= split->size; - VG_(OSetGen_Insert)(pmem.pmem_stores, split); - VG_(OSetGen_Insert)(pmem.pmem_stores, being_flushed); + VG_(OSetGen_Insert)(pInfo.pmem_stores, split); + VG_(OSetGen_Insert)(pInfo.pmem_stores, being_flushed); /* reset iter */ - VG_(OSetGen_ResetIterAt)(pmem.pmem_stores, split); + VG_(OSetGen_ResetIterAt)(pInfo.pmem_stores, split); } } @@ -1856,7 +1827,7 @@ print_general_summary(void) UWord all_errors = pmem.redundant_flushes_reg + pmem.superfluous_flushes_reg + pmem.multiple_stores_reg + - VG_(OSetGen_Size)(pmem.pmem_stores) + + VG_(OSetGen_Size)(pInfo.pmem_stores) + get_tx_all_err(); VG_(umsg)("ERROR SUMMARY: %lu errors\n", all_errors); } @@ -1954,7 +1925,7 @@ static Bool handle_gdb_monitor_command(ThreadId tid, HChar *req) case 2: {/* print_pmem_regions */ VG_(gdb_printf)("Registered persistent memory regions:\n"); struct pmem_st *tmp; - while ((tmp = VG_(OSetGen_Next)(pmem.pmem_stores)) != NULL) { + while ((tmp = VG_(OSetGen_Next)(pInfo.pmem_stores)) != NULL) { VG_(gdb_printf)("\tAddress: 0x%lx \tsize: %llu\n", tmp->addr, tmp->size); } @@ -2300,72 +2271,9 @@ pmc_handle_client_request(ThreadId tid, UWord *arg, UWord *ret ) struct pmem_st temp_info = {0}; temp_info.addr = arg[1]; temp_info.size = arg[2]; - - /* remove regions from memory location information array */ - struct pmem_st *modified_entry = NULL; - struct pmem_st *region = &temp_info; - UWord old_index; - for (int s_index=0; s_index<=pmem.info_array.m_index; s_index++) { - if (cmp_with_arr_minandmax(&temp_info, s_index) != -1) { - for (int i = pmem.info_array.m_data[s_index].start_index; i < pmem.info_array.m_data[s_index].end_index; i++){ - //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); - modified_entry = pmem.info_array.pmem_stores + i; - - if (modified_entry->is_delete == True) - continue; - - if (cmp_pmem_st(region, modified_entry) == 0) { - SizeT region_max_addr = region->addr + region->size; - //struct pmem_st tmp; - SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; - if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < - region_max_addr)) { - /* modified entry fully within removed region */ - modified_entry->is_delete = True; - } else if ((modified_entry->addr < region->addr) && - (mod_entry_max_addr > region_max_addr)) { - /* modified entry is larger than the removed region - slice */ - modified_entry->size = region->addr - modified_entry->addr; - - struct pmem_st *new_region; - old_index = pmem.info_array.m_data[pmem.info_array.m_index].end_index; - - if (old_index >= MAX_ARRAY_NUM) { - new_region = VG_(OSetGen_AllocNode)(pmem.pmem_stores, - (SizeT) sizeof(struct pmem_st)); - } else { - new_region = pmem.info_array.pmem_stores + old_index; - pmem.info_array.m_data[pmem.info_array.m_index].end_index++; - } - - new_region->addr = region_max_addr; - new_region->size = mod_entry_max_addr - new_region->addr; - - if (old_index >= MAX_ARRAY_NUM) { - add_and_merge_store(new_region); - } - - } else if ((modified_entry->addr >= region->addr) && - (mod_entry_max_addr > region_max_addr)) { - /* head overlaps */ - modified_entry->size -= region_max_addr - modified_entry->addr; - modified_entry->addr = region_max_addr; - // VG_(OSetGen_Insert)(region_set, modified_entry); - } else if ((mod_entry_max_addr <= region_max_addr) && - (region->addr > modified_entry->addr)) { - /* tail overlaps */ - modified_entry->size = region->addr - modified_entry->addr; - } else { - /* exact match */ - modified_entry->is_delete = True; - } - } - } - } - } - - /* remove regions from pmem_stores Oset*/ - remove_region(&temp_info, pmem.pmem_stores); + remove_array_info(&temp_info); + /* remove regions from pmem_stores Oset */ + remove_region(&temp_info, pInfo.pmem_stores); break; } @@ -2502,16 +2410,7 @@ pmc_process_cmd_line_option(const HChar *arg) static void pmc_post_clo_init(void) { - pmem.info_array.pmem_stores = VG_(malloc)("pmc.main.cpci.7", - MAX_ARRAY_NUM * sizeof(struct pmem_st)); - pmem.info_array.m_index = 0; - pmem.info_array.m_data = VG_(malloc)("pmc.main.cpci.8", - MAX_ARRAY_NUM * sizeof(struct arr_md)); - pmem.info_array.m_data[0].min_addr = pmem.info_array.m_data[0].max_addr = -1; - pmem.info_array.m_data[0].state = NO_FLUSHED; - pmem.info_array.m_data[0].end_index = pmem.info_array.m_data[0].start_index = 0; - - pmem.pmem_stores = VG_(OSetGen_Create)(/*keyOff*/0, cmp_pmem_st, + pInfo.pmem_stores = VG_(OSetGen_Create)(/*keyOff*/0, cmp_pmem_st, VG_(malloc), "pmc.main.cpci.1", VG_(free)); if (pmem.track_multiple_stores) @@ -2526,6 +2425,21 @@ pmc_post_clo_init(void) pmem.nonpmem_mappings = VG_(OSetGen_Create)(/*keyOff*/0, cmp_pmem_st, VG_(malloc), "pmc.main.cpci.5", VG_(free)); + + pInfo.info_array.pmem_stores = VG_(malloc)("pmc.main.cpci.7", + INIT_STORE_ARRAY_MAX_NUM * sizeof(struct pmem_st)); + + pInfo.info_array.m_data = VG_(malloc)("pmc.main.cpci.8", + INIT_STORE_ARRAY_MAX_NUM * sizeof(struct arr_md)); + + pInfo.info_array.m_data[0].min_addr = pInfo.info_array.m_data[0].max_addr = -1; + pInfo.info_array.m_data[0].state = NO_FLUSHED; + pInfo.info_array.m_data[0].end_index = pInfo.info_array.m_data[0].start_index = 0; + pInfo.info_array.m_index = 0; + pInfo.info_array.max_array_num = INIT_STORE_ARRAY_MAX_NUM; + pInfo.info_array.max_m_data_num = INIT_STORE_ARRAY_MAX_NUM; + + struct pmem_st temp_info = {0}; temp_info.addr = 0; From 0f26388188d8b3511d2f83f3cb0333c5efd88a53 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Sat, 5 Jun 2021 10:04:33 +0800 Subject: [PATCH 10/11] shorten codes and remove comments --- pmemcheck/pmc_main.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 9a941b2d2f..1f38ebb1a4 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -341,14 +341,15 @@ print_store_stats(void) { /* print store states of the array */ struct pmem_st *tmp; - for (int s_index=0; s_index<=pInfo.info_array.m_index; s_index++) { - for (int i= pInfo.info_array.m_data[s_index].start_index; i< pInfo.info_array.m_data[s_index].end_index; i++) { - tmp = pInfo.info_array.pmem_stores + i; + struct pmem_stores_array *info_arr = &pInfo.info_array; + for (int s_index=0; s_index <= info_arr->m_index; s_index++) { + for (int i= info_arr->m_data[s_index].start_index; i< info_arr->m_data[s_index].end_index; i++) { + tmp = info_arr->pmem_stores + i; if (tmp->size == 0) continue; - if (pInfo.info_array.m_data[s_index].state == ALL_FLUSHED) + if (info_arr->m_data[s_index].state == ALL_FLUSHED) tmp->state = STST_FLUSHED; struct pmem_st *new = VG_(OSetGen_AllocNode)(pInfo.pmem_stores, sizeof(struct pmem_st)); @@ -1341,7 +1342,6 @@ remove_array_info(struct pmem_st *region) for (int s_index=0; s_index<=pInfo.info_array.m_index; s_index++) { if (cmp_with_arr_minandmax(region, s_index) != -1) { for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++){ - //VG_(umsg)("remove before=%d\n",VG_(OSetGen_Size)(curr_node->pmem_stores)); modified_entry = pInfo.info_array.pmem_stores + i; if (modified_entry->size == 0) @@ -1349,7 +1349,6 @@ remove_array_info(struct pmem_st *region) if (cmp_pmem_st(region, modified_entry) == 0) { SizeT region_max_addr = region->addr + region->size; - //struct pmem_st tmp; SizeT mod_entry_max_addr = modified_entry->addr + modified_entry->size; if ((modified_entry->addr > region->addr) && (mod_entry_max_addr < region_max_addr)) { @@ -1374,7 +1373,6 @@ remove_array_info(struct pmem_st *region) /* head overlaps */ modified_entry->size -= region_max_addr - modified_entry->addr; modified_entry->addr = region_max_addr; - // VG_(OSetGen_Insert)(region_set, modified_entry); } else if ((mod_entry_max_addr <= region_max_addr) && (region->addr > modified_entry->addr)) { /* tail overlaps */ @@ -1463,15 +1461,16 @@ array_process_flush(UWord base, UWord size) Bool valid_flush = False; for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { - if (flush_max >= pInfo.info_array.m_data[s_index].max_addr && pInfo.info_array.m_data[s_index].min_addr >= flush_info.addr && - pInfo.info_array.m_data[s_index].state == NO_FLUSHED) { + struct arr_md *m_data = pInfo.info_array.m_data; + if (flush_max >= m_data[s_index].max_addr && m_data[s_index].min_addr >= flush_info.addr && + m_data[s_index].state == NO_FLUSHED) { - pInfo.info_array.m_data[s_index].state = ALL_FLUSHED; + m_data[s_index].state = ALL_FLUSHED; valid_flush = True; - } else if (flush_max < pInfo.info_array.m_data[s_index].min_addr || pInfo.info_array.m_data[s_index].max_addr < flush_info.addr) { + } else if (flush_max < m_data[s_index].min_addr || m_data[s_index].max_addr < flush_info.addr) { continue; } else { - for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { + for (int i = m_data[s_index].start_index; i < m_data[s_index].end_index; i++) { being_flushed = pInfo.info_array.pmem_stores + i; if (being_flushed->size == 0) { @@ -1484,7 +1483,7 @@ array_process_flush(UWord base, UWord size) valid_flush = True; /* check for multiple flushes of stores */ - if (pInfo.info_array.m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) { + if (m_data[s_index].state == ALL_FLUSHED || being_flushed->state != STST_DIRTY) { if (pmem.check_flush) { /* multiple flush of the same store - probably an issue */ struct pmem_st *wrong_flush = VG_(malloc)("pmc.main.cpci.3", @@ -1500,7 +1499,7 @@ array_process_flush(UWord base, UWord size) } being_flushed->state = STST_FLUSHED; - pInfo.info_array.m_data[s_index].state = PART_FLUSHED; + m_data[s_index].state = PART_FLUSHED; /* store starts before base flush address */ if (being_flushed->addr < flush_info.addr) { /* split and reinsert */ From ab4a7d14c215c6714af29e4a983dbf85c6859282 Mon Sep 17 00:00:00 2001 From: dibang <504730857@qq.com> Date: Tue, 6 Jul 2021 11:37:07 +0800 Subject: [PATCH 11/11] align structure arr_md --- pmemcheck/pmc_include.h | 11 ++++++++--- pmemcheck/pmc_main.c | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pmemcheck/pmc_include.h b/pmemcheck/pmc_include.h index adb5975909..e22fc0cec6 100644 --- a/pmemcheck/pmc_include.h +++ b/pmemcheck/pmc_include.h @@ -15,12 +15,17 @@ #ifndef PMC_INCLUDE_H #define PMC_INCLUDE_H -/** Metadata structure for store information array */ +/* + * Metadata structure for store information array. + * Start index and end index point to elements in pmem_stores. + * The metadata stores information (min_addr, max_addr and flushed_state) for + * elements between start index and end index */ struct arr_md { - UWord end_index; //Index of current free metadata + + UWord start_index; + UWord end_index; Addr min_addr; Addr max_addr; - UWord start_index; enum flushed_state { NO_FLUSHED, PART_FLUSHED, diff --git a/pmemcheck/pmc_main.c b/pmemcheck/pmc_main.c index 1f38ebb1a4..324d4a17af 100644 --- a/pmemcheck/pmc_main.c +++ b/pmemcheck/pmc_main.c @@ -898,11 +898,10 @@ array_handle_with_mult_stores(struct pmem_st *store) for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { if (cmp_with_arr_minandmax(store, s_index) != -1) { for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { - if (LIKELY(pInfo.info_array.pmem_stores[i].size != 0)) { - existing = pInfo.info_array.pmem_stores + i; - } else { + if (UNLIKELY(pInfo.info_array.pmem_stores[i].size == 0)) { continue; } + existing = pInfo.info_array.pmem_stores + i; if (cmp_pmem_st(existing, store) == 0) { if ((store->block_num - existing->block_num) < pmem.store_sb_indiff @@ -1309,8 +1308,9 @@ array_process_fence(void) { struct pmem_st *being_fenced = NULL; for(int s_index=0; s_index <= pInfo.info_array.m_index; s_index++) { - if (pInfo.info_array.m_data[s_index].state != ALL_FLUSHED) { - for (int i = pInfo.info_array.m_data[s_index].start_index; i < pInfo.info_array.m_data[s_index].end_index; i++) { + struct arr_md *m_data = pInfo.info_array.m_data + s_index; + if (m_data->state != ALL_FLUSHED) { + for (int i = m_data->start_index; i < m_data->end_index; i++) { being_fenced = pInfo.info_array.pmem_stores + i; if (being_fenced->state == STST_FLUSHED || being_fenced->size == 0) {