diff options
author | Axel Fagerstedt <axel.fagerstedt@linaro.org> | 2013-01-28 11:55:29 +0100 |
---|---|---|
committer | Axel Fagerstedt <axel.fagerstedt@linaro.org> | 2013-01-28 11:55:29 +0100 |
commit | b9402c3ad937cb6050a6072f18a2d2d357a91ac2 (patch) | |
tree | 81acdd28fc649508432caf356f6172a28c35c950 | |
parent | b9f6a1cc0bf67c0dd60a006b50232ce25e4c5f93 (diff) | |
parent | 46c3e094fdcd0a5dde120a2a63e15e5e66bb780f (diff) | |
download | linaro-android-kernel-test-b9402c3ad937cb6050a6072f18a2d2d357a91ac2.tar.gz |
Merge remote-tracking branch 'expanded/master'
-rw-r--r-- | ashmemtest-expanded/Android.mk | 9 | ||||
-rw-r--r-- | ashmemtest-expanded/Makefile | 15 | ||||
-rw-r--r-- | ashmemtest-expanded/ashmem.h | 45 | ||||
-rw-r--r-- | ashmemtest-expanded/ashmemtest-expanded.l | 261 | ||||
-rw-r--r-- | ashmemtest-expanded/test0.out | 3 | ||||
-rw-r--r-- | ashmemtest-expanded/test0.txt | 12 | ||||
-rw-r--r-- | ashmemtest-expanded/test1.out | 3 | ||||
-rw-r--r-- | ashmemtest-expanded/test1.txt | 13 |
8 files changed, 361 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..f13c7a5 --- /dev/null +++ b/ashmemtest-expanded/ashmemtest-expanded.l @@ -0,0 +1,261 @@ +/* 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 shrink (void); +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)); } + +shrink { shrink (); } + +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; + int ret; + + 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; + ret = ioctl (ashmemfd, ASHMEM_PIN, &pin); + if (ret < 0) + fatal (errno, "can't pin %d..%d", range->beg, range->end); + printf ("-> pin %d..%d OK ret %d\n", range->beg, range->end, ret); + } + 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; + ret = ioctl (ashmemfd, ASHMEM_PIN, &pin); + if (ret < 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; + int ret; + + 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; + ret = ioctl (ashmemfd, ASHMEM_UNPIN, &pin); + if (ret < 0) + fatal (errno, "can't unpin %d..%d", range->beg, range->end); + printf ("-> unpin %d..%d OK ret %d\n", range->beg, range->end, ret); + } + 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; + ret = ioctl (ashmemfd, ASHMEM_UNPIN, &pin); + if (ret < 0) + fatal (errno, "can't unpin page %d", pgno); + } + printf ("-> unpin backward %d..%d OK\n", range->beg, range->end); + } +} + +/* Enforce the kernel to run cache shrinker */ + +void +shrink (void) +{ + int fd; + char cmd[2]; + + fd = open ("/proc/sys/vm/drop_caches", O_WRONLY); + if (fd < 0) + fatal (errno, "can't open /proc/sys/vm/drop_caches (is /proc mounted?)"); + cmd[0] = '3'; + cmd[1] = '\n'; + if (write (fd, cmd, sizeof cmd) != sizeof cmd) + fatal (errno, "can't write to /proc/sys/vm/drop_caches"); +} + +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/test0.out b/ashmemtest-expanded/test0.out new file mode 100644 index 0000000..23f56f8 --- /dev/null +++ b/ashmemtest-expanded/test0.out @@ -0,0 +1,3 @@ +-> got 1000 pages +-> unpin 0..500 OK ret 0 +-> pin 0..500 OK ret 0 diff --git a/ashmemtest-expanded/test0.txt b/ashmemtest-expanded/test0.txt new file mode 100644 index 0000000..83c39a9 --- /dev/null +++ b/ashmemtest-expanded/test0.txt @@ -0,0 +1,12 @@ +# Simple test to make sure that the pages aren't purged initially. +# Expected output is: +# +# -> got 1000 pages +# -> unpin 0..500 OK ret 0 +# -> pin 0..500 OK ret 0 +# +# Here the last pin operation should return 0 (e.g. ASHMEM_NOT_PURGED). + +getpages 1000 +unpin 0 500 +pin 0 500 diff --git a/ashmemtest-expanded/test1.out b/ashmemtest-expanded/test1.out new file mode 100644 index 0000000..0027c44 --- /dev/null +++ b/ashmemtest-expanded/test1.out @@ -0,0 +1,3 @@ +-> got 1000 pages +-> unpin 0..500 OK ret 0 +-> pin 0..500 OK ret 1 diff --git a/ashmemtest-expanded/test1.txt b/ashmemtest-expanded/test1.txt new file mode 100644 index 0000000..6ecd6df --- /dev/null +++ b/ashmemtest-expanded/test1.txt @@ -0,0 +1,13 @@ +# Simple test to call cache shrinker. Expected output is: +# +# -> got 1000 pages +# -> unpin 0..500 OK ret 0 +# -> pin 0..500 OK ret 1 +# +# Here the call to kernel cache shrinker should give 1 +# (e.g. ASHMEM_WAS_PURGED) for the last pin operation. + +getpages 1000 +unpin 0 500 +shrink +pin 0 500 |