lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1281104713-23141-9-git-send-email-bp@amd64.org>
Date:	Fri,  6 Aug 2010 16:25:12 +0200
From:	Borislav Petkov <bp@...64.org>
To:	<acme@...radead.org>, <fweisbec@...il.com>, <mingo@...e.hu>,
	<peterz@...radead.org>, <rostedt@...dmis.org>
Cc:	<linux-kernel@...r.kernel.org>,
	Borislav Petkov <borislav.petkov@....com>
Subject: [RFC PATCH 8/9] perf: Carve out mmap helpers for general use

From: Borislav Petkov <borislav.petkov@....com>

Export the mmap_read* helpers into tools/lib/perf/mmap.[ch]

Signed-off-by: Borislav Petkov <borislav.petkov@....com>
---
 tools/Makefile              |    6 ++-
 tools/lib/perf/Makefile     |   35 ++++++++++++++
 tools/lib/perf/mmap.c       |   95 ++++++++++++++++++++++++++++++++++++++
 tools/lib/perf/mmap.h       |   15 ++++++
 tools/perf/Makefile         |    2 +-
 tools/perf/builtin-record.c |  107 ++++---------------------------------------
 tools/perf/builtin-top.c    |   28 ++---------
 7 files changed, 166 insertions(+), 122 deletions(-)
 create mode 100644 tools/lib/perf/Makefile
 create mode 100644 tools/lib/perf/mmap.c
 create mode 100644 tools/lib/perf/mmap.h

diff --git a/tools/Makefile b/tools/Makefile
index d3b1447..691f78b 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -34,7 +34,7 @@ export BASIC_CFLAGS
 PERF_TOP_DIR := $(CURDIR)
 export PERF_TOP_DIR
 
-perf: libparsevent lklib .FORCE
+perf: libparsevent lklib lkperflib .FORCE
 	$(QUIET_SUBDIR0)perf/ $(QUIET_SUBDIR1)
 
 libparsevent: .FORCE
@@ -43,9 +43,13 @@ libparsevent: .FORCE
 lklib: .FORCE
 	$(QUIET_SUBDIR0)lib/lk/ $(QUIET_SUBDIR1)
 
+lkperflib: .FORCE
+	$(QUIET_SUBDIR0)lib/perf/ $(QUIET_SUBDIR1)
+
 clean:
 	$(QUIET_SUBDIR0)lib/trace/ $(QUIET_SUBDIR1) clean
 	$(QUIET_SUBDIR0)lib/lk/ $(QUIET_SUBDIR1) clean
+	$(QUIET_SUBDIR0)lib/perf/ $(QUIET_SUBDIR1) clean
 	$(QUIET_SUBDIR0)perf/ $(QUIET_SUBDIR1) clean
 
 .PHONY: clean .FORCE
diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile
new file mode 100644
index 0000000..9942d52
--- /dev/null
+++ b/tools/lib/perf/Makefile
@@ -0,0 +1,35 @@
+include ../../scripts/Makefile.lib
+
+# guard against environment variables
+LIB_H=
+LIB_OBJS=
+
+LIB_H += mmap.h
+
+LIB_OBJS += mmap.o
+
+LIBFILE = $(LIB_OUTPUT)lkperflib.a
+
+CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+EXTLIBS = -lpthread -lrt -lelf -lm
+ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_LDFLAGS = $(LDFLAGS)
+
+RM = rm -f
+
+$(LIBFILE): $(LIB_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+
+$(LIB_OBJS): $(LIB_H)
+
+%.o: %.c
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
+%.s: %.c
+	$(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
+%.o: %.S
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
+
+clean:
+	$(RM) $(LIB_OBJS) $(LIBFILE)
+
+.PHONY: clean
diff --git a/tools/lib/perf/mmap.c b/tools/lib/perf/mmap.c
new file mode 100644
index 0000000..b154ccc
--- /dev/null
+++ b/tools/lib/perf/mmap.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <perf.h>
+#include "mmap.h"
+
+unsigned long mmap_read_head(struct mmap_data *md)
+{
+	struct perf_event_mmap_page *pc = md->base;
+	long head;
+
+	head = pc->data_head;
+	rmb();
+
+	return head;
+}
+
+static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
+{
+	struct perf_event_mmap_page *pc = md->base;
+
+	/*
+	 * ensure all reads are done before we write the tail out.
+	 */
+	/* mb(); */
+	pc->data_tail = tail;
+}
+
+static unsigned long mmap_read(struct mmap_data *md,
+			       void (*write_output)(void *, size_t))
+{
+	unsigned int head = mmap_read_head(md);
+	unsigned int old = md->prev;
+	unsigned int page_size;
+	unsigned char *data;
+	unsigned long size, samples = 0;
+	void *buf;
+	int diff;
+
+	page_size = sysconf(_SC_PAGE_SIZE);
+	data = md->base + page_size;
+
+	/*
+	 * If we're further behind than half the buffer, there's a chance
+	 * the writer will bite our tail and mess up the samples under us.
+	 *
+	 * If we somehow ended up ahead of the head, we got messed up.
+	 *
+	 * In either case, truncate and restart at head.
+	 */
+	diff = head - old;
+	if (diff < 0) {
+		fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
+		/*
+		 * head points to a known good entry, start there.
+		 */
+		old = head;
+	}
+
+	if (old != head)
+		samples++;
+
+	size = head - old;
+
+	if ((old & md->mask) + size != (head & md->mask)) {
+		buf = &data[old & md->mask];
+		size = md->mask + 1 - (old & md->mask);
+		old += size;
+
+		write_output(buf, size);
+	}
+
+	buf = &data[old & md->mask];
+	size = head - old;
+	old += size;
+
+	write_output(buf, size);
+
+	md->prev = old;
+	mmap_write_tail(md, old);
+
+	return samples;
+}
+
+unsigned long mmap_read_all(struct mmap_data *mmap_array, int nr_cpus,
+			    void (*write_output)(void *, size_t))
+{
+	int i;
+	unsigned long samples = 0;
+
+	for (i = 0; i < nr_cpus; i++) {
+		if (mmap_array[i].base)
+			samples += mmap_read(&mmap_array[i], write_output);
+	}
+
+	return samples;
+}
diff --git a/tools/lib/perf/mmap.h b/tools/lib/perf/mmap.h
new file mode 100644
index 0000000..b6622e5
--- /dev/null
+++ b/tools/lib/perf/mmap.h
@@ -0,0 +1,15 @@
+#ifndef __PERF_MMAP_H
+#define __PERF_MMAP_H
+
+struct mmap_data {
+	int			counter;
+	void			*base;
+	unsigned int		mask;
+	unsigned int		prev;
+};
+
+unsigned long mmap_read_head(struct mmap_data *md);
+unsigned long mmap_read_all(struct mmap_data *, int,
+			    void (*write_output)(void *, size_t));
+
+#endif /* __PERF_MMAP_H */
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7171f27..6a7d019 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -328,7 +328,7 @@ export PERL_PATH
 
 LIB_FILE=$(OUTPUT)libperf.a
 
-EXTRA_LIB_FILES=$(LIB_OUTPUT)libparsevent.a $(LIB_OUTPUT)lklib.a
+EXTRA_LIB_FILES=$(LIB_OUTPUT)libparsevent.a $(LIB_OUTPUT)lklib.a $(LIB_OUTPUT)lkperflib.a
 
 LIB_H += ../../include/linux/perf_event.h
 LIB_H += ../../include/linux/rbtree.h
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e55aa5b..2111f7d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -6,22 +6,21 @@
  * later analysis via perf report.
  */
 #define _FILE_OFFSET_BITS 64
-
 #include "builtin.h"
-
 #include "perf.h"
 
 #include "util/build-id.h"
-#include <lk/util.h>
 #include "util/parse-options.h"
 #include "util/parse-events.h"
-
 #include "util/header.h"
 #include "util/event.h"
 #include "util/debug.h"
 #include "util/session.h"
 #include "util/symbol.h"
+
 #include <lk/cpumap.h>
+#include <lk/util.h>
+#include <perf/mmap.h>
 
 #include <unistd.h>
 #include <sched.h>
@@ -62,7 +61,7 @@ static bool			no_samples			=  false;
 static bool			sample_address			=  false;
 static bool			no_buildid			=  false;
 
-static long			samples				=      0;
+static unsigned long		samples				=      0;
 static u64			bytes_written			=      0;
 
 static struct pollfd		*event_array;
@@ -76,37 +75,8 @@ static off_t			post_processing_offset;
 static struct perf_session	*session;
 static const char		*cpu_list;
 
-struct mmap_data {
-	int			counter;
-	void			*base;
-	unsigned int		mask;
-	unsigned int		prev;
-};
-
 static struct mmap_data		mmap_array[MAX_NR_CPUS];
 
-static unsigned long mmap_read_head(struct mmap_data *md)
-{
-	struct perf_event_mmap_page *pc = md->base;
-	long head;
-
-	head = pc->data_head;
-	rmb();
-
-	return head;
-}
-
-static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
-{
-	struct perf_event_mmap_page *pc = md->base;
-
-	/*
-	 * ensure all reads are done before we write the tail out.
-	 */
-	/* mb(); */
-	pc->data_tail = tail;
-}
-
 static void advance_output(size_t size)
 {
 	bytes_written += size;
@@ -134,55 +104,6 @@ static int process_synthesized_event(event_t *event,
 	return 0;
 }
 
-static void mmap_read(struct mmap_data *md)
-{
-	unsigned int head = mmap_read_head(md);
-	unsigned int old = md->prev;
-	unsigned char *data = md->base + page_size;
-	unsigned long size;
-	void *buf;
-	int diff;
-
-	/*
-	 * If we're further behind than half the buffer, there's a chance
-	 * the writer will bite our tail and mess up the samples under us.
-	 *
-	 * If we somehow ended up ahead of the head, we got messed up.
-	 *
-	 * In either case, truncate and restart at head.
-	 */
-	diff = head - old;
-	if (diff < 0) {
-		fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
-		/*
-		 * head points to a known good entry, start there.
-		 */
-		old = head;
-	}
-
-	if (old != head)
-		samples++;
-
-	size = head - old;
-
-	if ((old & md->mask) + size != (head & md->mask)) {
-		buf = &data[old & md->mask];
-		size = md->mask + 1 - (old & md->mask);
-		old += size;
-
-		write_output(buf, size);
-	}
-
-	buf = &data[old & md->mask];
-	size = head - old;
-	old += size;
-
-	write_output(buf, size);
-
-	md->prev = old;
-	mmap_write_tail(md, old);
-}
-
 static volatile int done = 0;
 static volatile int signr = -1;
 
@@ -483,19 +404,6 @@ static struct perf_event_header finished_round_event = {
 	.type = PERF_RECORD_FINISHED_ROUND,
 };
 
-static void mmap_read_all(void)
-{
-	int i;
-
-	for (i = 0; i < nr_cpu; i++) {
-		if (mmap_array[i].base)
-			mmap_read(&mmap_array[i]);
-	}
-
-	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
-		write_output(&finished_round_event, sizeof(finished_round_event));
-}
-
 static int __cmd_record(int argc, const char **argv)
 {
 	int i, counter;
@@ -729,10 +637,13 @@ static int __cmd_record(int argc, const char **argv)
 		close(go_pipe[1]);
 
 	for (;;) {
-		int hits = samples;
+		unsigned long hits = samples;
 		int thread;
 
-		mmap_read_all();
+		samples = mmap_read_all(mmap_array, nr_cpu, write_output);
+
+		if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
+			write_output(&finished_round_event, sizeof(finished_round_event));
 
 		if (hits == samples) {
 			if (done)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 9813351..5fc6bd4 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -24,11 +24,8 @@
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
-#include <lk/util.h>
-#include <linux/rbtree.h>
 #include "util/parse-options.h"
 #include "util/parse-events.h"
-#include <lk/cpumap.h>
 
 #include "util/debug.h"
 
@@ -52,6 +49,11 @@
 #include <sys/uio.h>
 #include <sys/mman.h>
 
+#include <lk/util.h>
+#include <lk/cpumap.h>
+#include <perf/mmap.h>
+
+#include <linux/rbtree.h>
 #include <linux/unistd.h>
 #include <linux/types.h>
 
@@ -1102,24 +1104,6 @@ static int event__process(event_t *event, struct perf_session *session)
 	return 0;
 }
 
-struct mmap_data {
-	int			counter;
-	void			*base;
-	int			mask;
-	unsigned int		prev;
-};
-
-static unsigned int mmap_read_head(struct mmap_data *md)
-{
-	struct perf_event_mmap_page *pc = md->base;
-	int head;
-
-	head = pc->data_head;
-	rmb();
-
-	return head;
-}
-
 static void perf_session__mmap_read_counter(struct perf_session *self,
 					    struct mmap_data *md)
 {
@@ -1137,7 +1121,7 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
 	 * In either case, truncate and restart at head.
 	 */
 	diff = head - old;
-	if (diff > md->mask / 2 || diff < 0) {
+	if ((unsigned)diff > md->mask / 2 || diff < 0) {
 		fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
 
 		/*
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ