Skip to contentSkip to conversation

perf: Port to Android

PATCH In review Bernhard Rosenkraenzer 7 participants 9 messages Aug 23, 2012 – Aug 24, 2012 perf events

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 perf: Port to Android

commit 4dc79eed16e3bb03b3cf92fcc6127e107e7537aa

Author: Bernhard Rosenkraenzer <[email protected]>
Date:   Sat Jun 23 06:18:05 2012 +0200

perf: Port to Android

Adapt perf to deal with some missing functions in Bionic etc.

Change-Id I0cda2aad3edba26e1be3aebc9475a229ea9e8356
tools/perf/Makefile +0 -0
index 92271d3..d15cdae 100644
@@ -117,7 +117,7 @@ ifndef PERF_DEBUG
 endif
 
 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 

$(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-EXTLIBS = -lpthread -lrt -lelf -lm
+EXTLIBS = -lpthread -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -
D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip
@@ -474,12 +474,23 @@ FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
- msg := $(error No gnu/libc-version.h found, please install glibc-
dev[el]/glibc-static);
+ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(FLAGS_GLIBC)),y)
+ # Found Bionic instead of glibc...
+ # That works too, but needs a bit of special treatment
+ BASIC_CFLAGS += -DANDROID -include compat-android.h
+ ANDROID := 1
+ else
+ msg := $(error No gnu/libc-version.h found, please install glibc-
dev[el]/glibc-static);
+ endif
else
msg := $(error No libelf.h/libelf found, please install libelf-
dev/elfutils-libelf-devel);
endif
endif

+ifneq ($(ANDROID),1)
+EXTLIBS += -lrt
+endif
+
ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
BASIC_CFLAGS += -DLIBELF_NO_MMAP
endif

tools/perf/builtin-record.c +33 -0
index be4e1ee..3a1d0cc 100644
@@ -27,10 +27,43 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
 #include <sys/mman.h>
 
+#ifdef ANDROID
+/* While stdlib.h has a prototype for it,
+   Bionic doesn't actually implement on_exit() */
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t)(int, void*);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs();
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg) {
+	if(__on_exit_count == ATEXIT_MAX)
+		return ENOMEM;
+	else if(__on_exit_count == 0)
+		atexit(__handle_on_exit_funcs);
+	__on_exit_funcs[__on_exit_count] = function;
+	__on_exit_args[__on_exit_count++] = arg;
+	return 0;
+}
+
+static void __handle_on_exit_funcs() {
+	for(int i=0; i<__on_exit_count; i++) {
+		__on_exit_funcs[i](__exitcode, __on_exit_args[i]);
+	}
+}
+#endif
+
 enum write_mode_t {
 	WRITE_FORCE,
 	WRITE_APPEND
tools/perf/builtin-test.c +7 -0
index 223ffdc..6dbd2ee 100644
@@ -469,10 +469,17 @@ static int test__basic_mmap(void)
 		.watermark	= 0,
 	};
 	cpu_set_t cpu_set;
+#ifndef ANDROID
 	const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
 					"getpgid", };
 	pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
 				      (void*)getpgid };
+#else
+	/* No getsid() on Android */
+	const char *syscall_names[] = { "getppid", "getpgrp",
+					"getpgid", };
+	pid_t (*syscalls[])(void) = { getppid, getpgrp, (void*)getpgid };
+#endif
 #define nsyscalls ARRAY_SIZE(syscall_names)
 	int ids[nsyscalls];
 	unsigned int nr_events[nsyscalls],
tools/perf/builtin.h +1 -0
index b382bd5..1521a275 100644
@@ -1,6 +1,7 @@
 #ifndef BUILTIN_H
 #define BUILTIN_H
 
+#include "compat-android.h"
 #include "util/util.h"
 #include "util/strbuf.h"
 
tools/perf/compat-android.h new file +96 -0

96 lines not on this page · raw message

tools/perf/config/feature- renamed from tools/perf/config/feature-tests.mak +0 -0

tests.mak
index d9084e0..498cd4d 100644

tools/perf/config/feature-tests.mak +13 -0
@@ -43,6 +43,19 @@ int main(void)
 }
 endef
 
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+#ifndef __ANDROID_API__
+	error out
+#else
+	return 0;
+#endif
+}
+endef
+
 define SOURCE_ELF_MMAP
 #include <libelf.h>
 int main(void)
tools/perf/util/annotate.h +1 -0
index efa5dc8..ead88ea 100644
@@ -6,6 +6,7 @@
 #include "symbol.h"
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <pthread.h>
 
 struct objdump_line {
 	struct list_head node;
tools/perf/util/event.c +1 -0
index 2a6f33c..867415a 100644
@@ -6,6 +6,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "../compat-android.h"
 
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
tools/perf/util/event.h +1 -0
index 1b19728..2b0554b 100644
@@ -6,6 +6,7 @@
 
 #include "../perf.h"
 #include "map.h"
+#include "../compat-android.h"
 
 /*
  * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
tools/perf/util/util.h +4 -0
index 0f99f39..77c5ced 100644
@@ -70,15 +70,19 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/select.h>
+#ifndef ANDROID
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
+#endif
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
 #include "../../../include/linux/magic.h"
 #include "types.h"
+#ifndef ANDROID
 #include <sys/ttydefaults.h>
+#endif
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
#1 lore raw

Hi Bernard,

(You didn't CC perf maintainers.)

Quoted 11 lines · Bernhard Rosenkraenzer

commit 4dc79eed16e3bb03b3cf92fcc6127e107e7537aa

Author: Bernhard Rosenkraenzer <[email protected]>
Date:   Sat Jun 23 06:18:05 2012 +0200

perf: Port to Android

Adapt perf to deal with some missing functions in Bionic etc.

Change-Id I0cda2aad3edba26e1be3aebc9475a229ea9e8356

Your patch changelog format is pretty funky.

tools/perf/Makefile

Quoted 4 lines
tools/perf/Makefile +0 -0
index 92271d3..d15cdae 100644

Whoa! I had no idea Android userspace was f*cked up...

Quoted 315 lines
tools/perf/Makefile +1 -1
@@ -117,7 +117,7 @@ ifndef PERF_DEBUG
 endif
 
 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99
 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
 $(EXTRA_CFLAGS)
-EXTLIBS = -lpthread -lrt -lelf -lm
+EXTLIBS = -lpthread -lelf -lm
 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -

D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip

tools/perf/Makefile +12 -1
@@ -474,12 +474,23 @@ FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
        FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
        ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
-               msg := $(error No gnu/libc-version.h found, please install glibc-
 dev[el]/glibc-static);
+               ifeq ($(call try-cc,$(SOURCE_BIONIC),$(FLAGS_GLIBC)),y)
+                       # Found Bionic instead of glibc...
+                       # That works too, but needs a bit of special treatment
+                       BASIC_CFLAGS += -DANDROID -include compat-android.h
+                       ANDROID := 1
+               else
+                       msg := $(error No gnu/libc-version.h found, please install glibc-
 dev[el]/glibc-static);
+               endif
        else
                msg := $(error No libelf.h/libelf found, please install libelf-
 dev/elfutils-libelf-devel);
        endif
 endif
 
+ifneq ($(ANDROID),1)
+EXTLIBS += -lrt
+endif
+

ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)

        BASIC_CFLAGS += -DLIBELF_NO_MMAP

endif

tools/perf/builtin-record.c +33 -0
index be4e1ee..3a1d0cc 100644
@@ -27,10 +27,43 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
 #include <sys/mman.h>
 
+#ifdef ANDROID
+/* While stdlib.h has a prototype for it,
+   Bionic doesn't actually implement on_exit() */
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t)(int, void*);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs();
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg) {
+       if(__on_exit_count == ATEXIT_MAX)
+               return ENOMEM;
+       else if(__on_exit_count == 0)
+               atexit(__handle_on_exit_funcs);
+       __on_exit_funcs[__on_exit_count] = function;
+       __on_exit_args[__on_exit_count++] = arg;
+       return 0;
+}
+
+static void __handle_on_exit_funcs() {
+       for(int i=0; i<__on_exit_count; i++) {
+               __on_exit_funcs[i](__exitcode, __on_exit_args[i]);
+       }
+}
+#endif
+
 enum write_mode_t {
        WRITE_FORCE,
        WRITE_APPEND
tools/perf/builtin-test.c +7 -0
index 223ffdc..6dbd2ee 100644
@@ -469,10 +469,17 @@ static int test__basic_mmap(void)
                .watermark      = 0,
        };
        cpu_set_t cpu_set;
+#ifndef ANDROID
        const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
                                        "getpgid", };
        pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
                                      (void*)getpgid };
+#else
+       /* No getsid() on Android */
+       const char *syscall_names[] = { "getppid", "getpgrp",
+                                       "getpgid", };
+       pid_t (*syscalls[])(void) = { getppid, getpgrp, (void*)getpgid };
+#endif
 #define nsyscalls ARRAY_SIZE(syscall_names)
        int ids[nsyscalls];
        unsigned int nr_events[nsyscalls],
tools/perf/builtin.h +1 -0
index b382bd5..1521a275 100644
@@ -1,6 +1,7 @@
 #ifndef BUILTIN_H
 #define BUILTIN_H
 
+#include "compat-android.h"
 #include "util/util.h"
 #include "util/strbuf.h"
 
tools/perf/compat-android.h new file +96 -0
new file mode 100644
index 0000000..9a33f49
@@ -0,0 +1,96 @@
+/* Android compatibility header
+ * Provides missing bits in Bionic on Android, ignored
+ * on regular Linux.
+ *
+ * Written by [email protected]
+ *
+ * Released into the public domain. Do with this file
+ * whatever you want.
+ */
+#ifdef ANDROID
+/* Bionic has its own idea about ALIGN, and kills other definitions.
+ * Done outside the multiple-inclusion wrapper to make sure we
+ * can override Bionic's ALIGN by simply including compat-android.h
+ * again after including Bionic headers.
+ */
+#undef ALIGN
+#undef __ALIGN_MASK
+#define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
+
+#ifndef _COMPAT_ANDROID_H_
+#define _COMPAT_ANDROID_H_ 1
+#include <stdio.h>
+#include <signal.h>
+#include <asm/page.h> /* for PAGE_SIZE */
+#include <asm/termios.h> /* for winsize */
+
+#ifndef __WORDSIZE
+#include <stdint.h>
+#define __WORDSIZE _BITSIZE
+#endif
+
+#ifndef roundup
+#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#endif
+
+#ifndef __force
+#define __force
+#endif
+
+#ifndef __le32
+#define __le32 uint32_t
+#endif
+
+/* Assorted functions that are missing from Bionic */
+static void psignal(int sig, const char *s)
+{
+       if(sig >= 0 && sig < NSIG) {
+               if(s)
+                       fprintf(stderr, "%s: %s\n", s, sys_siglist[sig]);
+               else
+                       fprintf(stderr, "%s\n", sys_siglist[sig]);
+       } else {
+               if(s)
+                       fprintf(stderr, "%s: invalid signal\n", s);
+               else
+                       fputs("invalid signal\n", stderr);
+       }
+}
+
+static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
+{
+       size_t ret = 0;
+
+       if (!lineptr || !n || !stream)
+               return -1;
+
+       if(!*lineptr) {
+               *n = 128;
+               *lineptr = (char*)malloc(*n);
+               if(!*lineptr)
+                       return -1;
+       }
+
+       while(!feof(stream) && !ferror(stream)) {
+               int c;
+               if(ret == *n) {
+                       *n += 128;
+                       *lineptr = (char*)realloc(*lineptr, *n);
+                       if(!*lineptr) {
+                               *n = 0;
+                               return -1;
+                       }
+               }
+               c = fgetc(stream);
+               if(c == EOF)
+                       break;
+               *lineptr[ret++] = c;
+               if(c == '\n')
+                       break;
+       }
+       *lineptr[ret] = 0;
+       return ret;
+}
+#endif
+#endif
tools/perf/config/feature- renamed from tools/perf/config/feature-tests.mak +0 -0

tests.mak
index d9084e0..498cd4d 100644

tools/perf/config/feature-tests.mak +13 -0
@@ -43,6 +43,19 @@ int main(void)
 }
 endef
 
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+#ifndef __ANDROID_API__
+       error out
+#else
+       return 0;
+#endif
+}
+endef
+
 define SOURCE_ELF_MMAP
 #include <libelf.h>
 int main(void)
tools/perf/util/annotate.h +1 -0
index efa5dc8..ead88ea 100644
@@ -6,6 +6,7 @@
 #include "symbol.h"
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <pthread.h>
 
 struct objdump_line {
        struct list_head node;
tools/perf/util/event.c +1 -0
index 2a6f33c..867415a 100644
@@ -6,6 +6,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "../compat-android.h"
 
 static const char *perf_event__names[] = {
        [0]                                     = "TOTAL",
tools/perf/util/event.h +1 -0
index 1b19728..2b0554b 100644
@@ -6,6 +6,7 @@
 
 #include "../perf.h"
 #include "map.h"
+#include "../compat-android.h"
 
 /*
  * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
tools/perf/util/util.h +4 -1
index 0f99f39..77c5ced 100644
@@ -70,15 +70,19 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/select.h>
+#ifndef ANDROID
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
+#endif
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
 #include "../../../include/linux/magic.h"
 #include "types.h"
+#ifndef ANDROID
 #include <sys/ttydefaults.h>
+#endif
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
 
--

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

#2 lore raw
Quoted 24 lines · Pekka Enberg
Quoted 24 lines
tools/perf/builtin-record.c +24 -0
+#ifdef ANDROID
+/* While stdlib.h has a prototype for it,
+   Bionic doesn't actually implement on_exit() */
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t)(int, void*);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs();
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg) {
+       if(__on_exit_count == ATEXIT_MAX)
+               return ENOMEM;
+       else if(__on_exit_count == 0)
+               atexit(__handle_on_exit_funcs);
+       __on_exit_funcs[__on_exit_count] = function;
+       __on_exit_args[__on_exit_count++] = arg;
+       return 0;
+}
Quoted 8 lines

tools/perf/builtin-record.c line 66

Quoted 8 lines
tools/perf/builtin-record.c +8 -0
+
+static void __handle_on_exit_funcs() {
+       for(int i=0; i<__on_exit_count; i++) {
+               __on_exit_funcs[i](__exitcode, __on_exit_args[i]);
+       }
+}
+#endif
+

Why not add support for the missing functions (on_exit, getsid, psignal and getline) to Bionic instead of perf?

Quoted 6 lines
Quoted 6 lines
tools/perf/util/util.h +0 -0
index 0f99f39..77c5ced 100644
@@ -70,15 +70,19 @@
  #include <sys/socket.h>
Quoted 8 lines

tools/perf/util/util.h line 78

Quoted 8 lines
tools/perf/util/util.h +2 -0
  #include <sys/ioctl.h>
  #include <sys/select.h>
+#ifndef ANDROID
  #include <netinet/in.h>
  #include <netinet/tcp.h>
  #include <arpa/inet.h>
+#endif
  #include <netdb.h>

netinet/*, arpa/inet.h,netdb.h and sys/socket.h can be removed from util.h

David

#3 lore raw
Quoted 2 lines · David Ahern

Why not add support for the missing functions (on_exit, getsid, psignal and getline) to Bionic instead of perf?

Many vendors need to target existing Android platforms and don't have the luxury of waiting for code to get through Google review and then land on devices between 6 months in the future and never. The embedded world is dysfunctional in a whole bunch of ways.

Signature · 1 line
Matthew Garrett | [email protected]
#4 lore raw
Quoted 10 lines · Matthew Garrett
Quoted 2 lines · David Ahern

Why not add support for the missing functions (on_exit, getsid, psignal and getline) to Bionic instead of perf?

Many vendors need to target existing Android platforms and don't have the luxury of waiting for code to get through Google review and then land on devices between 6 months in the future and never. The embedded world is dysfunctional in a whole bunch of ways.

and the compat changes don't look overly large, so I guess we could do something like this.

Would be nice to make it more robust in case Bionic does add these functions? Feature tests and such? perf offering weak symbols for some of these methods and the linker sorting it out?

Thanks,

Ingo

#5 lore raw
In reply to Matthew Garrett
Quoted 9 lines · On Fri, 24 Aug 2012 05:08:45 +0100 Matthew Garrett <[email protected]> wrote:
Quoted 2 lines · David Ahern

Why not add support for the missing functions (on_exit, getsid, psignal and getline) to Bionic instead of perf?

Many vendors need to target existing Android platforms and don't have the luxury of waiting for code to get through Google review and then land on devices between 6 months in the future and never. The embedded world is dysfunctional in a whole bunch of ways.

So add a small library and link with -lstuffandroidforgot. That's basically how the FSF dealt with all the proprietary Unix library messes.

Come to think of it call the library "integrated build runtime environment" and you can like with -libre ;)

It's also going to be far more maintainable and generically useful for porting tools from GNU to 'droid userspace.

Alan

#6 lore raw
Quoted 18 lines · Alan Cox
Quoted 10 lines · On Fri, 24 Aug 2012 05:08:45 +0100 Matthew Garrett <[email protected]> wrote:
Quoted 2 lines · David Ahern

Why not add support for the missing functions (on_exit, getsid, psignal and getline) to Bionic instead of perf?

Many vendors need to target existing Android platforms and don't have the luxury of waiting for code to get through Google review and then land on devices between 6 months in the future and never. The embedded world is dysfunctional in a whole bunch of ways.

So add a small library and link with -lstuffandroidforgot. That's basically how the FSF dealt with all the proprietary Unix library messes.

Quoted 5 lines

Come to think of it call the library "integrated build runtime environment" and you can like with -libre ;)

It's also going to be far more maintainable and generically useful for porting tools from GNU to 'droid userspace.

Well, you should see the uglies Git has to support Windows ;-)

Anyway, I'm not against making perf work on Android in principle, it is Obviously Useful (tm).

Thanks,

Ingo

maintainer
#7 lore raw
In reply to Bernhard Rosenkraenzer

Hi, Bernhard

Quoted 9 lines · Bernhard Rosenkraenzer

commit 4dc79eed16e3bb03b3cf92fcc6127e107e7537aa

Author: Bernhard Rosenkraenzer <[email protected]>
Date:   Sat Jun 23 06:18:05 2012 +0200

perf: Port to Android

Adapt perf to deal with some missing functions in Bionic etc.

Change-Id: I0cda2aad3edba26e1be3aebc9475a229ea9e8356

Please remove this Change-Id line.

Quoted 15 lines
tools/perf/Makefile +1 -1
index 92271d3..d15cdae 100644
@@ -117,7 +117,7 @@ ifndef PERF_DEBUG
 endif
 
 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 
 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) 
 $(EXTRA_CFLAGS)
-EXTLIBS = -lpthread -lrt -lelf -lm
+EXTLIBS = -lpthread -lelf -lm
 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -
Quoted 1 line

D_GNU_SOURCE

It seems your mail client wraps long line (again).

tools/perf/Makefile FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) · line 481

Quoted 12 lines

ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip

tools/perf/Makefile +4 -1
@@ -474,12 +474,23 @@ FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
 	FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
 	ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
-		msg := $(error No gnu/libc-version.h found, please install glibc-
 dev[el]/glibc-static);
+		ifeq ($(call try-cc,$(SOURCE_BIONIC),$(FLAGS_GLIBC)),y)
+			# Found Bionic instead of glibc...
+			# That works too, but needs a bit of special treatment
+			BASIC_CFLAGS += -DANDROID -include compat-android.h

Do we really need to include compat-android.h to every source file?

Quoted 53 lines
tools/perf/Makefile +8 -0
+			ANDROID := 1
+		else
+			msg := $(error No gnu/libc-version.h found, please install glibc-
 dev[el]/glibc-static);
+		endif
 	else
 		msg := $(error No libelf.h/libelf found, please install libelf-
 dev/elfutils-libelf-devel);
 	endif
 endif
 
+ifneq ($(ANDROID),1)
+EXTLIBS += -lrt
+endif
+

ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)

tools/perf/Makefile +0 -0
 	BASIC_CFLAGS += -DLIBELF_NO_MMAP
 endif
tools/perf/builtin-record.c +23 -0
index be4e1ee..3a1d0cc 100644
@@ -27,10 +27,43 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
 #include <sys/mman.h>
 
+#ifdef ANDROID
+/* While stdlib.h has a prototype for it,
+   Bionic doesn't actually implement on_exit() */
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t)(int, void*);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs();
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg) {
+	if(__on_exit_count == ATEXIT_MAX)
+		return ENOMEM;
+	else if(__on_exit_count == 0)
+		atexit(__handle_on_exit_funcs);
+	__on_exit_funcs[__on_exit_count] = function;
+	__on_exit_args[__on_exit_count++] = arg;

tools/perf/builtin-record.c line 66

Quoted 10 lines
tools/perf/builtin-record.c +10 -0
+	return 0;
+}
+
+static void __handle_on_exit_funcs() {
+	for(int i=0; i<__on_exit_count; i++) {
+		__on_exit_funcs[i](__exitcode, __on_exit_args[i]);
+	}
+}
+#endif
+

Putting above in builtin-record.c seems not a good choice. How about something like util/android.c?

tools/perf/compat-android.h

Quoted 42 lines
tools/perf/builtin-record.c +0 -0
 enum write_mode_t {
 	WRITE_FORCE,
 	WRITE_APPEND
tools/perf/builtin-test.c +7 -0
index 223ffdc..6dbd2ee 100644
@@ -469,10 +469,17 @@ static int test__basic_mmap(void)
 		.watermark	= 0,
 	};
 	cpu_set_t cpu_set;
+#ifndef ANDROID
 	const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
 					"getpgid", };
 	pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
 				      (void*)getpgid };
+#else
+	/* No getsid() on Android */
+	const char *syscall_names[] = { "getppid", "getpgrp",
+					"getpgid", };
+	pid_t (*syscalls[])(void) = { getppid, getpgrp, (void*)getpgid };
+#endif
 #define nsyscalls ARRAY_SIZE(syscall_names)
 	int ids[nsyscalls];
 	unsigned int nr_events[nsyscalls],
tools/perf/builtin.h +1 -0
index b382bd5..1521a275 100644
@@ -1,6 +1,7 @@
 #ifndef BUILTIN_H
 #define BUILTIN_H
 
+#include "compat-android.h"
 #include "util/util.h"
 #include "util/strbuf.h"
 
tools/perf/compat-android.h new file +0 -0
new file mode 100644
index 0000000..9a33f49

This also can be moved under util/ along with the .c file.

Quoted 85 lines
tools/perf/compat-android.h new file +84 -0
@@ -0,0 +1,96 @@
+/* Android compatibility header
+ * Provides missing bits in Bionic on Android, ignored
+ * on regular Linux.
+ *
+ * Written by [email protected]
+ *
+ * Released into the public domain. Do with this file
+ * whatever you want.
+ */
+#ifdef ANDROID
+/* Bionic has its own idea about ALIGN, and kills other definitions.
+ * Done outside the multiple-inclusion wrapper to make sure we
+ * can override Bionic's ALIGN by simply including compat-android.h
+ * again after including Bionic headers.
+ */
+#undef ALIGN
+#undef __ALIGN_MASK
+#define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
+
+#ifndef _COMPAT_ANDROID_H_
+#define _COMPAT_ANDROID_H_ 1
+#include <stdio.h>
+#include <signal.h>
+#include <asm/page.h> /* for PAGE_SIZE */
+#include <asm/termios.h> /* for winsize */
+
+#ifndef __WORDSIZE
+#include <stdint.h>
+#define __WORDSIZE _BITSIZE
+#endif
+
+#ifndef roundup
+#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
+#endif
+
+#ifndef __force
+#define __force
+#endif
+
+#ifndef __le32
+#define __le32 uint32_t
+#endif
+
+/* Assorted functions that are missing from Bionic */
+static void psignal(int sig, const char *s)
+{
+	if(sig >= 0 && sig < NSIG) {
+		if(s)
+			fprintf(stderr, "%s: %s\n", s, sys_siglist[sig]);
+		else
+			fprintf(stderr, "%s\n", sys_siglist[sig]);
+	} else {
+		if(s)
+			fprintf(stderr, "%s: invalid signal\n", s);
+		else
+			fputs("invalid signal\n", stderr);
+	}
+}
+
+static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
+{
+	size_t ret = 0;
+
+	if (!lineptr || !n || !stream)
+		return -1;
+
+	if(!*lineptr) {
+		*n = 128;
+		*lineptr = (char*)malloc(*n);
+		if(!*lineptr)
+			return -1;
+	}
+
+	while(!feof(stream) && !ferror(stream)) {
+		int c;
+		if(ret == *n) {
+			*n += 128;
+			*lineptr = (char*)realloc(*lineptr, *n);
+			if(!*lineptr) {
+				*n = 0;
+				return -1;
+			}
+		}

tools/perf/compat-android.h line 94

Quoted 10 lines
tools/perf/compat-android.h new file +10 -0
+		c = fgetc(stream);
+		if(c == EOF)
+			break;
+		*lineptr[ret++] = c;
+		if(c == '\n')
+			break;
+	}
+	*lineptr[ret] = 0;
+	return ret;
+}

And above two functions can be moved too somehow.

Quoted 44 lines
tools/perf/compat-android.h new file +2 -0
+#endif
+#endif
tools/perf/config/feature- renamed from tools/perf/config/feature-tests.mak +0 -0

tests.mak
index d9084e0..498cd4d 100644

tools/perf/config/feature-tests.mak +13 -0
@@ -43,6 +43,19 @@ int main(void)
 }
 endef
 
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+#ifndef __ANDROID_API__
+	error out
+#else
+	return 0;
+#endif
+}
+endef
+
 define SOURCE_ELF_MMAP
 #include <libelf.h>
 int main(void)
tools/perf/util/annotate.h +1 -0
index efa5dc8..ead88ea 100644
@@ -6,6 +6,7 @@
 #include "symbol.h"
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <pthread.h>
 
 struct objdump_line {
 	struct list_head node;
tools/perf/util/event.c +0 -0
index 2a6f33c..867415a 100644

tools/perf/util/event.c line 9

Quoted 4 lines
tools/perf/util/event.c +1 -0
@@ -6,6 +6,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "../compat-android.h"

Didn't we already include the header on command line? Also I'm curious whether it can be built with O=$(DIR) option.

Btw, can you (or anyone) tell me the current status of TLS support in bionic?

Thanks,
Namhyung

Quoted 39 lines
tools/perf/util/event.c +0 -0
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
tools/perf/util/event.h +1 -0
index 1b19728..2b0554b 100644
@@ -6,6 +6,7 @@
 
 #include "../perf.h"
 #include "map.h"
+#include "../compat-android.h"
 
 /*
  * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
tools/perf/util/util.h +4 -0
index 0f99f39..77c5ced 100644
@@ -70,15 +70,19 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/select.h>
+#ifndef ANDROID
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
+#endif
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
 #include "../../../include/linux/magic.h"
 #include "types.h"
+#ifndef ANDROID
 #include <sys/ttydefaults.h>
+#endif
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
maintainer
#8 lore raw
Quoted 1 line · Namhyung Kim

On Thu, 23 Aug 2012 17:01:52 +0200, Bernhard Rosenkraenzer wrote:

[SNIP]

Quoted 45 lines
Quoted 45 lines
tools/perf/compat-android.h new file +45 -0
+
+/* Assorted functions that are missing from Bionic */
+static void psignal(int sig, const char *s)
+{
+	if(sig >= 0 && sig < NSIG) {
+		if(s)
+			fprintf(stderr, "%s: %s\n", s, sys_siglist[sig]);
+		else
+			fprintf(stderr, "%s\n", sys_siglist[sig]);
+	} else {
+		if(s)
+			fprintf(stderr, "%s: invalid signal\n", s);
+		else
+			fputs("invalid signal\n", stderr);
+	}
+}
+
+static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
+{
+	size_t ret = 0;
+
+	if (!lineptr || !n || !stream)
+		return -1;
+
+	if(!*lineptr) {
+		*n = 128;
+		*lineptr = (char*)malloc(*n);
+		if(!*lineptr)
+			return -1;
+	}
+
+	while(!feof(stream) && !ferror(stream)) {
+		int c;
+		if(ret == *n) {
+			*n += 128;
+			*lineptr = (char*)realloc(*lineptr, *n);
+			if(!*lineptr) {
+				*n = 0;
+				return -1;
+			}
+		}
+		c = fgetc(stream);
+		if(c == EOF)
+			break;
+		*lineptr[ret++] = c;
Quoted 8 lines

tools/perf/compat-android.h line 94

Quoted 6 lines
tools/perf/compat-android.h new file +6 -0
+		if(c == '\n')
+			break;
+	}
+	*lineptr[ret] = 0;
+	return ret;
+}

And above two functions can be moved too somehow.

I meant it can be moved to the .c file.

Thanks,
Namhyung