This patch will introduce multithread for search_physical. It have the same logic as search_virtual. Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- memory.c | 369 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 302 insertions(+), 67 deletions(-) diff --git a/memory.c b/memory.c index c396b07..75112d7 100644 --- a/memory.c +++ b/memory.c @@ -250,9 +250,9 @@ static ulong search_ulong(ulong *, ulong, int, struct searchinfo *, struct searc static ulong search_uint(ulong *, ulong, int, struct searchinfo *, struct searchinfo *, void *); static ulong search_ushort(ulong *, ulong, int, struct searchinfo *, struct searchinfo *, void *); static ulong search_chars(ulong *, ulong, int, struct searchinfo *); -static ulonglong search_ulong_p(ulong *, ulonglong, int, struct searchinfo *); -static ulonglong search_uint_p(ulong *, ulonglong, int, struct searchinfo *); -static ulonglong search_ushort_p(ulong *, ulonglong, int, struct searchinfo *); +static ulonglong search_ulong_p(ulong *, ulonglong, int, struct searchinfo *, void *); +static ulonglong search_uint_p(ulong *, ulonglong, int, struct searchinfo *, void *); +static ulonglong search_ushort_p(ulong *, ulonglong, int, struct searchinfo *, void *); static ulonglong search_chars_p(ulong *, ulonglong, int, struct searchinfo *); static void search_virtual(struct searchinfo *); static void search_physical(struct searchinfo *); @@ -14992,9 +14992,12 @@ search_ulong(ulong *bufptr, ulong addr, int longcnt, /* phys search uses ulonglong address representation */ static ulonglong -search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si) +search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si, void *priv) { int i; + cache_output_t *co; + char *buf; + ulong mask = si->s_parms.s_ulong.mask; for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) { for (si->val = 0; si->val < si->vcnt; si->val++) { @@ -15002,9 +15005,35 @@ search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si SEARCHMASK(si->s_parms.s_ulong.value[si->val])) { if (si->context) display_with_pre_and_post(bufptr, addr, si); - else - fprintf(fp, "%llx: %lx %s\n", addr, *bufptr, - show_opt_string(si)); + else { + if (priv) { + co = (cache_output_t *)priv; + *co->output_buf_offset += snprintf( + *co->output_buf + + *co->output_buf_offset, + *co->output_buf_size - + *co->output_buf_offset, + "%llx: %lx %s\n", + addr, *bufptr, + show_opt_string(si)); + if (*co->output_buf_offset >= + *co->output_buf_size >> 1) { + *co->output_buf_size <<= 1; + buf = *co->output_buf; + if (!(*co->output_buf = + malloc(*co->output_buf_size))) { + error(FATAL, "cannot malloc" + " more output buffer"); + } + memcpy(*co->output_buf, buf, + *co->output_buf_offset); + free(buf); + } + } else { + fprintf(fp, "%llx: %lx %s\n", + addr, *bufptr, show_opt_string(si)); + } + } } } } @@ -15073,12 +15102,14 @@ search_uint(ulong *bufptr, ulong addr, int longcnt, /* phys search uses ulonglong address representation */ static ulonglong -search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si) +search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si, void *priv) { int i; int cnt = longcnt * (sizeof(long)/sizeof(int)); uint *ptr = (uint *)bufptr; uint mask = si->s_parms.s_uint.mask; + cache_output_t *co; + char *buf; for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) { for (si->val = 0; si->val < si->vcnt; si->val++) { @@ -15086,9 +15117,35 @@ search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si) SEARCHMASK(si->s_parms.s_uint.value[si->val])) { if (si->context) display_with_pre_and_post(ptr, addr, si); - else - fprintf(fp, "%llx: %x %s\n", addr, *ptr, - show_opt_string(si)); + else { + if (priv) { + co = (cache_output_t *)priv; + *co->output_buf_offset += snprintf( + *co->output_buf + + *co->output_buf_offset, + *co->output_buf_size - + *co->output_buf_offset, + "%llx: %x %s\n", + addr, *ptr, + show_opt_string(si)); + if (*co->output_buf_offset >= + *co->output_buf_size >> 1) { + *co->output_buf_size <<= 1; + buf = *co->output_buf; + if (!(*co->output_buf = + malloc(*co->output_buf_size))) { + error(FATAL, "cannot malloc" + " more output buffer"); + } + memcpy(*co->output_buf, buf, + *co->output_buf_offset); + free(buf); + } + } else { + fprintf(fp, "%llx: %x %s\n", addr, *ptr, + show_opt_string(si)); + } + } } } } @@ -15160,12 +15217,14 @@ search_ushort(ulong *bufptr, ulong addr, int longcnt, /* phys search uses ulonglong address representation */ static ulonglong -search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si) +search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si, void *priv) { int i; int cnt = longcnt * (sizeof(long)/sizeof(short)); ushort *ptr = (ushort *)bufptr; ushort mask = si->s_parms.s_ushort.mask; + cache_output_t *co; + char *buf; for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) { for (si->val = 0; si->val < si->vcnt; si->val++) { @@ -15173,9 +15232,35 @@ search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *s SEARCHMASK(si->s_parms.s_ushort.value[si->val])) { if (si->context) display_with_pre_and_post(ptr, addr, si); - else - fprintf(fp, "%llx: %x %s\n", addr, *ptr, - show_opt_string(si)); + else { + if (priv) { + co = (cache_output_t *)priv; + *co->output_buf_offset += snprintf( + *co->output_buf + + *co->output_buf_offset, + *co->output_buf_size - + *co->output_buf_offset, + "%llx: %x %s\n", + addr, *ptr, + show_opt_string(si)); + if (*co->output_buf_offset >= + *co->output_buf_size >> 1) { + *co->output_buf_size <<= 1; + buf = *co->output_buf; + if (!(*co->output_buf = + malloc(*co->output_buf_size))) { + error(FATAL, "cannot malloc" + " more output buffer"); + } + memcpy(*co->output_buf, buf, + *co->output_buf_offset); + free(buf); + } + } else { + fprintf(fp, "%llx: %x %s\n", addr, *ptr, + show_opt_string(si)); + } + } } } } @@ -15691,95 +15776,245 @@ done: } } +static void * +do_search_physical(void *args) +{ + ulong *ubp; + ulonglong ppp, pnext; + ulonglong end_in; + int wordcnt, lastpage; + struct searchinfo si; + int i, page_buf_zone_index, page_buf_num_per_zone; + cache_output_t cache_output; + + thread_data_t *td = (thread_data_t *)args; + end_in = td->si->paddr_end; + memcpy(&si, td->si, sizeof(struct searchinfo)); + cache_output.output_buf = &td->output_buf; + cache_output.output_buf_size = &td->output_buf_size; + cache_output.output_buf_offset = &td->output_buf_offset; + page_buf_num_per_zone = si.thread_num * si.factor; + + while (1) { + pthread_barrier_wait(td->barrier); + page_buf_zone_index = *td->page_buf_zone_index; + for (i = td->start[page_buf_zone_index]; + i < td->end[page_buf_zone_index]; + i++) { + ppp = (page_buf + page_buf_zone_index * + page_buf_num_per_zone)[i].ppp; + pnext = (page_buf + page_buf_zone_index * + page_buf_num_per_zone)[i].pnext; + lastpage = (page_buf + page_buf_zone_index * + page_buf_num_per_zone)[i].lastpage; + + ubp = (ulong *)&(page_buf + page_buf_zone_index * + page_buf_num_per_zone)[i] + .pagebuf[pnext - ppp]; + if (lastpage) { + if (end_in == (ulonglong)(-1)) + wordcnt = PAGESIZE()/sizeof(long); + else + wordcnt = (end_in - pnext)/sizeof(long); + } else + wordcnt = (PAGESIZE() - (pnext - ppp))/sizeof(long); + + switch (td->si->mode) + { + case SEARCH_ULONG: + pnext = search_ulong_p(ubp, pnext, wordcnt, + &si, &cache_output); + break; + case SEARCH_UINT: + pnext = search_uint_p(ubp, pnext, wordcnt, + &si, &cache_output); + break; + case SEARCH_USHORT: + pnext = search_ushort_p(ubp, pnext, wordcnt, + &si, &cache_output); + break; + case SEARCH_CHARS: + pnext = search_chars_p(ubp, pnext, wordcnt, si); + break; + default: + /* unimplemented search type */ + pnext += wordcnt * (sizeof(long)); + break; + } + } + pthread_mutex_lock(td->finished_thread_count_mutex); + if (++(*td->finished_thread_count) == si.thread_num) { + pthread_mutex_unlock(td->finished_thread_count_mutex); + + for (i = 0; i < si.thread_num; i++) { + fprintf(fp, "%s", (td->td + i)->output_buf); + *((td->td + i)->output_buf) = '\0'; + (td->td + i)->output_buf_offset = 0; + } + *td->page_buf_zone_index = (page_buf_zone_index + 1) % + si.page_buf_zone_num; + (*td->finished_thread_count) = 0; + + sem_post(td->empty_page_buf_zone_count); + } else { + pthread_mutex_unlock(td->finished_thread_count_mutex); + } + if (td->exit[page_buf_zone_index]) { + break; + } + } + return NULL; +} static void search_physical(struct searchinfo *si) { ulonglong start_in, end_in; - ulong *ubp; - int wordcnt, lastpage; ulonglong pnext, ppp; - char *pagebuf; + ulong page; ulong pct, pages_read, pages_checked; time_t begin, finish; - ulong page; - - start_in = si->paddr_start; - end_in = si->paddr_end; + int i, start, end; + int page_buf_zone_index = 0; + int page_buf_index; + int thread_num = si->thread_num; + int page_buf_num_per_zone = thread_num * si->factor; pages_read = pages_checked = 0; begin = finish = 0; - pagebuf = GETBUF(PAGESIZE()); + // For thread sync + sem_t empty_page_buf_zone_count; + pthread_barrier_t barrier; + pthread_t *threads; + thread_data_t *td; + int finished_thread_count = 0; + pthread_mutex_t finished_thread_count_mutex = PTHREAD_MUTEX_INITIALIZER; + int thread_page_buf_zone_index = 0; + sem_init(&empty_page_buf_zone_count, 0, si->page_buf_zone_num); + pthread_barrier_init(&barrier, NULL, thread_num + 1); + + // Alloc buffers + page_buf = (page_buf_t *)GETBUF(sizeof(page_buf_t) * + si->page_buf_zone_num * page_buf_num_per_zone); + threads = (pthread_t *)GETBUF(sizeof(pthread_t) * thread_num); + td = (thread_data_t *)GETBUF(sizeof(thread_data_t) * thread_num); + memset(td, 0, sizeof(thread_data_t) * thread_num); + memset(page_buf, 0, sizeof(struct page_buf) * si->page_buf_zone_num * + page_buf_num_per_zone); + for (i = 0; i < si->page_buf_zone_num * page_buf_num_per_zone; i++) { + ((struct page_buf *)page_buf + i)->pagebuf = GETBUF(PAGESIZE()); + } - if (start_in & (sizeof(ulonglong)-1)) { - start_in &= ~(sizeof(ulonglong)-1); - error(INFO, "rounding down start address to: %llx\n", + start_in = si->paddr_start; + end_in = si->paddr_end; + if (start_in & (sizeof(ulonglong)-1)) { + start_in &= ~(sizeof(ulonglong)-1); + error(INFO, "rounding down start address to: %llx\n", (ulonglong)start_in); - } - + } if (CRASHDEBUG(1)) { begin = time(NULL); - fprintf(fp, "search_physical: start: %llx end: %llx\n", + fprintf(fp, "search_physical: start: %llx end: %llx\n", start_in, end_in); } - pnext = start_in; + for (i = 0; i < thread_num; i++) { + td[i].si = si; + if ((td[i].output_buf = malloc(1024)) == NULL) + error(FATAL, "cannot malloc output buffer"); + *td[i].output_buf = '\0'; + td[i].output_buf_size = 1024; + td[i].empty_page_buf_zone_count = &empty_page_buf_zone_count; + td[i].barrier = &barrier; + td[i].finished_thread_count = &finished_thread_count; + td[i].page_buf_zone_index = &thread_page_buf_zone_index; + td[i].finished_thread_count_mutex = &finished_thread_count_mutex; + td[i].td = td; + td[i].start = (int *)GETBUF(sizeof(int) * si->page_buf_zone_num * 3); + td[i].end = td[i].start + si->page_buf_zone_num * 1; + td[i].exit = td[i].start + si->page_buf_zone_num * 2; + memset(td[i].start, 0, sizeof(int) * si->page_buf_zone_num * 3); + + td[i].thread_index = i; + + pthread_create(&threads[i], NULL, do_search_physical, &td[i]); + } + + page_buf_index = 0; + pnext = start_in; + sem_wait(&empty_page_buf_zone_count); for (ppp = PHYSPAGEBASE(start_in); pnext < end_in; pnext = ppp) { pages_checked++; - lastpage = (PHYSPAGEBASE(pnext) == PHYSPAGEBASE(end_in)); - if (LKCD_DUMPFILE()) - set_lkcd_nohash(); + (page_buf + page_buf_num_per_zone * page_buf_zone_index) + [page_buf_index].lastpage = + (PHYSPAGEBASE(pnext) == PHYSPAGEBASE(end_in)); - if (!phys_to_page(ppp, &page) || - !readmem(ppp, PHYSADDR, pagebuf, PAGESIZE(), - "search page", RETURN_ON_ERROR|QUIET)) { + if (!phys_to_page(ppp, &page) || + !readmem(ppp, PHYSADDR, (page_buf + + page_buf_num_per_zone * page_buf_zone_index) + [page_buf_index].pagebuf, + PAGESIZE(), "search page", + RETURN_ON_ERROR|QUIET)) { if (!next_physpage(ppp, &ppp)) break; continue; } pages_read++; - ubp = (ulong *)&pagebuf[pnext - ppp]; - if (lastpage) { - if (end_in == (ulonglong)(-1)) - wordcnt = PAGESIZE()/sizeof(long); - else - wordcnt = (end_in - pnext)/sizeof(long); - } else - wordcnt = (PAGESIZE() - (pnext - ppp))/sizeof(long); - - switch (si->mode) - { - case SEARCH_ULONG: - pnext = search_ulong_p(ubp, pnext, wordcnt, si); - break; - case SEARCH_UINT: - pnext = search_uint_p(ubp, pnext, wordcnt, si); - break; - case SEARCH_USHORT: - pnext = search_ushort_p(ubp, pnext, wordcnt, si); - break; - case SEARCH_CHARS: - pnext = search_chars_p(ubp, pnext, wordcnt, si); - break; - default: - /* unimplemented search type */ - pnext += wordcnt * (sizeof(long)); - break; + (page_buf + page_buf_num_per_zone * page_buf_zone_index) + [page_buf_index].ppp = ppp; + (page_buf + page_buf_num_per_zone * page_buf_zone_index) + [page_buf_index++].pnext = pnext; + if (page_buf_index >= page_buf_num_per_zone) { + for (start = 0, i = 0; i < thread_num; start = end, i++) { + end = start + page_buf_index / thread_num + 1; + end = end > page_buf_index ? page_buf_index : end; + td[i].start[page_buf_zone_index] = start; + td[i].end[page_buf_zone_index] = end; + } + pthread_barrier_wait(&barrier); + page_buf_index = 0; + page_buf_zone_index = (page_buf_zone_index + 1) % + si->page_buf_zone_num; + sem_wait(&empty_page_buf_zone_count); } ppp += PAGESIZE(); } + if (pnext >= end_in) { + for (start = 0, i = 0; i < thread_num; start = end, i++) { + end = start + page_buf_index / thread_num + 1; + end = end > page_buf_index ? page_buf_index : end; + td[i].start[page_buf_zone_index] = start; + td[i].end[page_buf_zone_index] = end; + td[i].exit[page_buf_zone_index] = true; + } + pthread_barrier_wait(&barrier); + sem_wait(&empty_page_buf_zone_count); + } + + for (i = 0; i < thread_num; i++) { + pthread_join(threads[i], NULL); + } + for (i = 0; i < thread_num; i++) { + free(td[i].output_buf); + FREEBUF(td[i].start); + } + for (i = 0; i < si->page_buf_zone_num * page_buf_num_per_zone; i++) { + FREEBUF(((struct page_buf *)page_buf + i)->pagebuf); + } + FREEBUF(page_buf); + sem_destroy(&empty_page_buf_zone_count); + pthread_barrier_destroy(&barrier); + pthread_mutex_destroy(&finished_thread_count_mutex); if (CRASHDEBUG(1)) { finish = time(NULL); pct = (pages_read * 100)/pages_checked; - fprintf(fp, - "search_physical: read %ld (%ld%%) of %ld pages checked in %ld seconds\n", + fprintf(fp, + "search_physical: read %ld (%ld%%) of %ld pages checked in %ld seconds\n", pages_read, pct, pages_checked, finish - begin); } - - FREEBUF(pagebuf); } static bool -- 2.33.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki