Add av_page_alloc, av_page_free, and av_page_protect to allocate pages
and mark them executable, and use them to replace the equivalent
open-coded functionality in libswscale.
---
libavutil/Makefile | 2 +
libavutil/page.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++
libavutil/page.h | 82 ++++++++++++++++++++++++++++++++++++
libswscale/utils.c | 45 +++-----------------
4 files changed, 208 insertions(+), 38 deletions(-)
create mode 100644 libavutil/page.c
create mode 100644 libavutil/page.h
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 626b60a..a193acd 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -28,6 +28,7 @@ HEADERS = adler32.h
\
mem.h \
dict.h \
opt.h \
+ page.h \
parseutils.h \
pixdesc.h \
pixfmt.h \
@@ -62,6 +63,7 @@ OBJS = adler32.o
\
mem.o \
dict.o \
opt.o \
+ page.o \
parseutils.o \
pixdesc.o \
random_seed.o \
diff --git a/libavutil/page.c b/libavutil/page.c
new file mode 100644
index 0000000..aa1cee5
--- /dev/null
+++ b/libavutil/page.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2001-2003 Michael Niedermayer <[email protected]>
+ * Copyright (C) 2012 Daniel Verkamp <[email protected]>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/**
+ * @file
+ * Memory page handling functions
+ */
+
+#define _SVID_SOURCE // needed for MAP_ANONYMOUS
+
+#include "config.h"
+#include "page.h"
+
+#if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+# if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+#endif
+
+#if HAVE_VIRTUALALLOC
+# include <windows.h>
+#endif
+
+#if defined(MAP_ANONYMOUS)
+
+void *av_page_alloc(size_t size)
+{
+ void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
MAP_ANONYMOUS, -1, 0);
+ return ptr == MAP_FAILED ? NULL : ptr;
+}
+
+void av_page_free(void *ptr, size_t size)
+{
+ if (!ptr) return;
+ munmap(ptr, size);
+}
+
+int av_page_protect(void *ptr, size_t size, int prot)
+{
+ return mprotect(ptr, size, prot);
+}
+
+#elif HAVE_VIRTUALALLOC
+
+void *av_page_alloc(size_t size)
+{
+ return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+void av_page_free(void *ptr, size_t size)
+{
+ if (!ptr) return;
+ VirtualFree(ptr, 0, MEM_RELEASE);
+}
+
+int av_page_protect(void *ptr, size_t size, int prot)
+{
+ DWORD oldprotect, newprotect =
+ prot & (AV_PROT_WRITE | AV_PROT_EXEC) ==
+ (AV_PROT_WRITE | AV_PROT_EXEC) ? PAGE_EXECUTE_READWRITE :
+ prot & (AV_PROT_READ | AV_PROT_EXEC) ==
+ (AV_PROT_READ | AV_PROT_EXEC) ? PAGE_EXECUTE_READ :
+ prot & AV_PROT_EXEC ? PAGE_EXECUTE :
+ prot & AV_PROT_WRITE ? PAGE_READWRITE :
+ prot & AV_PROT_READ ? PAGE_READONLY :
+ PAGE_NOACCESS;
+
+ if (!VirtualProtect(ptr, size, newprotect, &oldprotect))
+ return -1;
+
+ if (prot & AV_PROT_EXEC && !FlushInstructionCache(GetCurrentProcess(),
ptr, size))
+ return -1;
+
+ return 0;
+}
+
+#else // fallback version - just allocate with av_malloc and hope it is
executable
+
+void *av_page_alloc(size_t size)
+{
+ return av_malloc(size);
+}
+
+void av_page_free(void *ptr, size_t size)
+{
+ av_free(ptr);
+}
+
+int av_page_protect(void *ptr, size_t size, int prot)
+{
+ return 0;
+}
+
+#endif
+
+
+void av_page_freep(void *arg, size_t size)
+{
+ void **ptr= (void**)arg;
+ av_page_free(*ptr, size);
+ *ptr = NULL;
+}
diff --git a/libavutil/page.h b/libavutil/page.h
new file mode 100644
index 0000000..0786ca6
--- /dev/null
+++ b/libavutil/page.h
@@ -0,0 +1,82 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/**
+ * @file
+ * Memory page handling functions
+ */
+
+#ifndef AVUTIL_PAGE_H
+#define AVUTIL_PAGE_H
+
+#include "avutil.h"
+#include "config.h"
+
+#if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#ifdef PROT_NONE
+# define AV_PROT_NONE PROT_NONE
+# define AV_PROT_READ PROT_READ
+# define AV_PROT_WRITE PROT_WRITE
+# define AV_PROT_EXEC PROT_EXEC
+#else
+# define AV_PROT_NONE 0 ///< No access allowed
+# define AV_PROT_READ 1 ///< Memory can be read
+# define AV_PROT_WRITE 2 ///< Memory can be written
+# define AV_PROT_EXEC 4 ///< Memory can be executed
+#endif
+
+/**
+ * Allocate consecutive pages of memory.
+ * @param size Size in bytes of the pages to allocate.
+ * @return Pointer to the allocated pages, or NULL on error.
+ * @note size need not be a multiple of the page size.
+ * @note The pages will initially be readable and writable but not executable.
+ */
+void *av_page_alloc(size_t size);
+
+/**
+ * Free consecutive pages of memory which have been allocated with
av_page_alloc.
+ * @param ptr Pointer to the pages to free.
+ * @param size Size in bytes of the pages to free.
+ * @note ptr must have been returned from a previous av_page_alloc call, and
+ * size must be the same as size passed to that av_page_alloc call.
+ * @note If ptr is NULL, no action is taken.
+ */
+void av_page_free(void *ptr, size_t size);
+
+/**
+ * Free consecutive pages of memory which have been allocated with
av_page_alloc
+ * and set the pointer pointing to it to NULL.
+ * @param ptr Pointer to the pointer to the pages to free.
+ * @see av_page_free()
+ */
+void av_page_freep(void *arg, size_t size);
+
+/**
+ * Set memory protection on a region of pages.
+ * @param ptr Pointer to the start of the region of pages to be protected.
+ * @param size Size in bytes of the region to protect.
+ * @param prot Combination of protection options (AV_PROT_*) ORed together to
+ * apply to the region of pages.
+ * @return 0 if the requested protection was applied, or -1 on error.
+ * @note ptr must be aligned to a page boundary.
+ * @note If the exact protection requested is not available on the current
system,
+ * the protection that is applied will be no more restrictive than prot.
+ */
+int av_page_protect(void *ptr, size_t size, int prot);
+
+#endif /* AVUTIL_PAGE_H */
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 15039ce..ff0e468 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -18,23 +18,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define _SVID_SOURCE //needed for MAP_ANONYMOUS
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "config.h"
#include <assert.h>
-#if HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-#endif
-#if HAVE_VIRTUALALLOC
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
#include "swscale.h"
#include "swscale_internal.h"
#include "rgb2rgb.h"
@@ -46,6 +35,7 @@
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/page.h"
unsigned swscale_version(void)
{
@@ -925,17 +915,8 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
SwsFilter *dstFilter)
c->lumMmx2FilterCodeSize = initMMX2HScaler( dstW, c->lumXInc,
NULL, NULL, NULL, 8);
c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc,
NULL, NULL, NULL, 4);
-#ifdef MAP_ANONYMOUS
- c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-#elif HAVE_VIRTUALALLOC
- c->lumMmx2FilterCode = VirtualAlloc(NULL,
c->lumMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- c->chrMmx2FilterCode = VirtualAlloc(NULL,
c->chrMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
-#else
- c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize);
- c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);
-#endif
-
+ c->lumMmx2FilterCode = av_page_alloc(c->lumMmx2FilterCodeSize);
+ c->chrMmx2FilterCode = av_page_alloc(c->chrMmx2FilterCodeSize);
if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)
return AVERROR(ENOMEM);
FF_ALLOCZ_OR_GOTO(c, c->hLumFilter , (dstW
/8+8)*sizeof(int16_t), fail);
@@ -946,10 +927,8 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
SwsFilter *dstFilter)
initMMX2HScaler( dstW, c->lumXInc, c->lumMmx2FilterCode,
c->hLumFilter, c->hLumFilterPos, 8);
initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode,
c->hChrFilter, c->hChrFilterPos, 4);
-#ifdef MAP_ANONYMOUS
- mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC
| PROT_READ);
- mprotect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize, PROT_EXEC
| PROT_READ);
-#endif
+ av_page_protect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize,
AV_PROT_EXEC | AV_PROT_READ);
+ av_page_protect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize,
AV_PROT_EXEC | AV_PROT_READ);
} else
#endif /* HAVE_MMX2 */
{
@@ -1467,18 +1446,8 @@ void sws_freeContext(SwsContext *c)
av_freep(&c->hChrFilterPos);
#if HAVE_MMX
-#ifdef MAP_ANONYMOUS
- if (c->lumMmx2FilterCode) munmap(c->lumMmx2FilterCode,
c->lumMmx2FilterCodeSize);
- if (c->chrMmx2FilterCode) munmap(c->chrMmx2FilterCode,
c->chrMmx2FilterCodeSize);
-#elif HAVE_VIRTUALALLOC
- if (c->lumMmx2FilterCode) VirtualFree(c->lumMmx2FilterCode, 0,
MEM_RELEASE);
- if (c->chrMmx2FilterCode) VirtualFree(c->chrMmx2FilterCode, 0,
MEM_RELEASE);
-#else
- av_free(c->lumMmx2FilterCode);
- av_free(c->chrMmx2FilterCode);
-#endif
- c->lumMmx2FilterCode=NULL;
- c->chrMmx2FilterCode=NULL;
+ av_page_freep(&c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize);
+ av_page_freep(&c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize);
#endif /* HAVE_MMX */
av_freep(&c->yuvTable);
--
1.7.8.3
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel