[PATCH 2/5] [RFC] Introduce multi-thread to search_physical

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux