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

Reply via email to