summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Antipov <dmitry.antipov@linaro.org>2013-01-14 17:14:55 +0400
committerDmitry Antipov <dmitry.antipov@linaro.org>2013-01-14 17:14:55 +0400
commit9b71bb8b5ebfab37dc91dd5d8f51d33b59c3d044 (patch)
treeb8d17dfadecf4e2706e3c6536919734958b147f0
downloadlinaro-android-kernel-test-9b71bb8b5ebfab37dc91dd5d8f51d33b59c3d044.tar.gz
Initial commit.
-rw-r--r--ashmemtest-expanded/Android.mk9
-rw-r--r--ashmemtest-expanded/Makefile15
-rw-r--r--ashmemtest-expanded/ashmem.h45
-rw-r--r--ashmemtest-expanded/ashmemtest-expanded.l272
-rw-r--r--ashmemtest-expanded/example.txt22
5 files changed, 363 insertions, 0 deletions
diff --git a/ashmemtest-expanded/Android.mk b/ashmemtest-expanded/Android.mk
new file mode 100644
index 0000000..75aa6ef
--- /dev/null
+++ b/ashmemtest-expanded/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ashmemtest-expanded.l
+LOCAL_MODULE := ashmemtest-expanded
+LOCAL_MODULE_TAGS := optional tests
+LOCAL_C_INCLUDES := $(TOP)/frameworks/native/include
+
+include $(BUILD_EXECUTABLE)
diff --git a/ashmemtest-expanded/Makefile b/ashmemtest-expanded/Makefile
new file mode 100644
index 0000000..1c53b72
--- /dev/null
+++ b/ashmemtest-expanded/Makefile
@@ -0,0 +1,15 @@
+# This file is here just to allow compiling the test without full Android setup.
+
+CROSS_COMPILE =
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -O2 -g
+FLEX = flex
+
+ashmemtest-expanded: ashmemtest-expanded.c
+ $(CC) $(CFLAGS) -I. -o $@ $<
+
+ashmemtest-expanded.c: ashmemtest-expanded.l
+ $(FLEX) -o $@ $<
+
+clean:
+ $(RM) ashmemtest-expanded ashmemtest-expanded.c
diff --git a/ashmemtest-expanded/ashmem.h b/ashmemtest-expanded/ashmem.h
new file mode 100644
index 0000000..519fcfb
--- /dev/null
+++ b/ashmemtest-expanded/ashmem.h
@@ -0,0 +1,45 @@
+/*
+ * This file is here just to allow debugging the test without full Android setup.
+ * Original copyright is below.
+ *
+ ** utils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed. It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _UTILS_ASHMEM_H
+#define _UTILS_ASHMEM_H
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN 256
+
+#define ASHMEM_NAME_DEF "dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_REAPED 0
+#define ASHMEM_WAS_REAPED 1
+
+/* Return values from ASHMEM_ISPINNED: Is the mapping now pinned or unpinned? */
+#define ASHMEM_NOW_UNPINNED 0
+#define ASHMEM_NOW_PINNED 1
+
+#define __ASHMEMIOC 0x77
+
+#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin)
+#define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
+#define ASHMEM_ISPINNED _IOW(__ASHMEMIOC, 9, struct ashmem_pin)
+#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
+
+#endif /* _UTILS_ASHMEM_H */
diff --git a/ashmemtest-expanded/ashmemtest-expanded.l b/ashmemtest-expanded/ashmemtest-expanded.l
new file mode 100644
index 0000000..074a948
--- /dev/null
+++ b/ashmemtest-expanded/ashmemtest-expanded.l
@@ -0,0 +1,272 @@
+/* Expanded ashmem test -- flex input, but mostly -*-C-*- really */
+
+%option noyywrap yylineno
+
+%{
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/sysinfo.h>
+
+#ifdef ANDROID
+#include <utils/ashmem.h>
+#else
+#include "ashmem.h"
+#endif
+
+#ifndef _LINUX_ASHMEM_H
+struct ashmem_pin {
+ uint32_t offset;
+ uint32_t len;
+};
+#endif
+
+typedef struct {
+ int beg;
+ int end;
+} range_t;
+
+int ashmemfd = -1;
+void *pages;
+int nrpages;
+int pagesize;
+
+int parse_number (char *);
+range_t * parse_range (char *);
+void getpages (int);
+void pinpages (range_t *);
+void unpinpages (range_t *);
+void pressure (int);
+void purgepages (void);
+void fatal (int, const char *, ...);
+
+%}
+
+%%
+
+getpages[ \t]+[0-9]+ { getpages (parse_number (yytext + 8)); }
+
+pin[ \t]+[0-9]+[ \t]+[0-9]+ { pinpages (parse_range (yytext + 3)); }
+
+unpin[ \t]+[0-9]+[ \t]+[0-9]+ { unpinpages (parse_range (yytext + 5)); }
+
+alloc[ \t]+[0-9]+ { pressure (parse_number (yytext + 5)); }
+
+purge { purgepages (); }
+
+[ \t\n]+ /* spaces */
+
+[ \t]*#.+ /* comment starts from '#' */
+
+. { fprintf (stderr, "Unrecognized input '%s' at line %d\n",
+ yytext, yylineno);
+ exit (1); }
+
+%%
+
+void fatal (int error, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ if (error)
+ fprintf (stderr, " (error %d [%s])", error, strerror (error));
+ va_end (ap);
+ fprintf (stderr, "\n");
+ exit (error ? error : 1);
+}
+
+int
+parse_number (char *buf)
+{
+ while (isspace (*buf))
+ buf++;
+ return atoi (buf);
+}
+
+range_t *
+parse_range (char *buf)
+{
+ char *p, *q;
+ range_t *range;
+
+ if (ashmemfd == -1)
+ fatal (0, "pages not allocated (use getpages X first)");
+
+ range = (range_t *) malloc (sizeof (range_t));
+ if (!range)
+ fatal (0, "cannot allocate memory");
+ for (p = buf; isspace (*p); p++);
+ if (!isdigit (*p))
+ fatal (0, "unexpected parse error");
+ range->beg = strtol (p, &q, 10);
+ for (; isspace (*q); q++);
+ range->end = strtol (q, NULL, 10);
+
+ if (range->beg > nrpages)
+ fatal (0, "range begin %d is outside of allocated pages", range->beg);
+ if (range->end > nrpages)
+ fatal (0, "range end %d is outside of allocated pages", range->beg);
+ if (range->end == range->beg)
+ fatal (0, "zero-sized range at line %d", yylineno);
+ return range;
+}
+
+void
+getpages (int npages)
+{
+ size_t size = npages * pagesize;
+
+ if (ashmemfd != -1)
+ fatal (0, "pages already allocated");
+ if (npages < 1)
+ fatal (0, "should allocate at least one page");
+
+ ashmemfd = open ("/dev/ashmem", O_RDWR);
+ if (ashmemfd < 0)
+ fatal (errno, "can't open /dev/ashmem");
+ if (ioctl (ashmemfd, ASHMEM_SET_SIZE, size) < 0)
+ fatal (errno, "can't set size");
+ pages = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemfd, 0);
+ if (pages == MAP_FAILED)
+ fatal (errno, "can't map pages");
+ nrpages = npages;
+ printf ("-> got %d pages\n", npages);
+}
+
+void
+pinpages (range_t *range)
+{
+ struct ashmem_pin pin;
+
+ if (ashmemfd == -1)
+ fatal (0, "pages not allocated (use getpages X first)");
+
+ if (range->end > range->beg)
+ {
+ /* Normal order, pin all at once. */
+ pin.offset = range->beg * pagesize;
+ pin.len = (range->end - range->beg) * pagesize;
+ if (ioctl (ashmemfd, ASHMEM_PIN, &pin) < 0)
+ fatal (errno, "can't pin %d..%d", range->beg, range->end);
+ printf ("-> pin %d..%d OK\n", range->beg, range->end);
+ }
+ else
+ {
+ /* Reverse order, pin page-by-page from higher to lower. */
+ int pgno;
+
+ for (pgno = range->beg - 1; pgno >= range->end; pgno--)
+ {
+ pin.offset = pgno * pagesize;
+ pin.len = pagesize;
+ if (ioctl (ashmemfd, ASHMEM_PIN, &pin) < 0)
+ fatal (errno, "can't pin page %d", pgno);
+ }
+ printf ("-> pin backward %d..%d OK\n", range->beg, range->end);
+ }
+}
+
+void
+unpinpages (range_t *range)
+{
+ struct ashmem_pin pin;
+
+ if (ashmemfd == -1)
+ fatal (0, "pages not allocated (use getpages X first)");
+
+ if (range->end > range->beg)
+ {
+ /* Normal order, unpin all at once. */
+ pin.offset = range->beg * pagesize;
+ pin.len = (range->end - range->beg) * pagesize;
+ if (ioctl (ashmemfd, ASHMEM_UNPIN, &pin) < 0)
+ fatal (errno, "can't unpin %d..%d", range->beg, range->end);
+ printf ("-> unpin %d..%d OK\n", range->beg, range->end);
+ }
+ else
+ {
+ /* Reverse order, unpin page-by-page from higher to lower. */
+ int pgno;
+
+ for (pgno = range->beg - 1; pgno >= range->end; pgno--)
+ {
+ pin.offset = pgno * pagesize;
+ pin.len = pagesize;
+ if (ioctl (ashmemfd, ASHMEM_UNPIN, &pin) < 0)
+ fatal (errno, "can't unpin page %d", pgno);
+ }
+ printf ("-> unpin backward %d..%d OK\n", range->beg, range->end);
+ }
+}
+
+/* Percentage is of physical RAM */
+
+void
+pressure (int percentage)
+{
+ struct sysinfo si;
+ int mbytes;
+ char *mem;
+
+ if (sysinfo (&si) < 0)
+ fatal (0, "can't obtain system information");
+ mbytes = (si.totalram >> 20) * percentage / 100;
+ switch (fork ())
+ {
+ case 0: /* child */
+ mem = (char *) malloc (mbytes << 20);
+ if (!mem)
+ fatal (0, "can't allocate %d MBytes", mbytes);
+ else
+ {
+ printf ("-> child allocates %d MBytes\n", mbytes);
+ memset (mem, 0, mbytes << 20);
+ /* let's wait for OOM killer */
+ pause ();
+ }
+ /* NOTREACHED */
+ break;
+ case -1: /* error */
+ fatal (errno, "can't fork");
+ default: /* parent */
+ break;
+ }
+}
+
+void
+purgepages (void)
+{
+ int ret;
+
+ if (ashmemfd == -1)
+ fatal (0, "pages not allocated (use getpages X first)");
+ ret = ioctl (ashmemfd, ASHMEM_PURGE_ALL_CACHES);
+ if (ret < 0)
+ fatal (errno, "can't purge caches");
+ printf ("-> purge return %d pages OK\n", ret);
+}
+
+int main (int argc, char *argv[])
+{
+ pagesize = getpagesize ();
+
+ if (argc == 2)
+ {
+ yyin = fopen (argv[1], "r");
+ if (!yyin)
+ fatal (errno, "can't open '%s'", argv[1]);
+ }
+ else
+ yyin = stdin;
+
+ yylex ();
+ return 0;
+}
diff --git a/ashmemtest-expanded/example.txt b/ashmemtest-expanded/example.txt
new file mode 100644
index 0000000..73ae92c
--- /dev/null
+++ b/ashmemtest-expanded/example.txt
@@ -0,0 +1,22 @@
+# Example input for ashmemtest-expanded test program.
+
+# Get 1000 pages
+getpages 1000
+
+# Unpin pages 100..200
+unpin 100 200
+
+# Unpin pages 400..300 (in that order, e.g. backward)
+unpin 400 300
+
+# Allocate huge chunk (90% of physical RAM)
+alloc 90
+
+# Pin 100..200 back
+pin 100 200
+
+# Pin 300..400 back (in normal order)
+pin 300 400
+
+# Purge all
+purge