This patch will introduce multithread for search_physical. It have the same
logic as search_virtual.
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
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