Index: libffi/configure.ac
===================================================================
--- libffi.orig/configure.ac
+++ libffi/configure.ac
@@ -84,7 +84,7 @@ case "$host" in
   i?86-*-freebsd* | i?86-*-openbsd*)
 	TARGET=X86_FREEBSD; TARGETDIR=x86
 	;;
-  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw*)
+  i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2*)
 	TARGET=X86_WIN32; TARGETDIR=x86
 	# All mingw/cygwin/win32 builds require this for sharedlib
 	AM_LTLDFLAGS="-no-undefined"
Index: libffi/src/closures.c
===================================================================
--- libffi.orig/src/closures.c
+++ libffi/src/closures.c
@@ -44,7 +44,7 @@
 #  define FFI_MMAP_EXEC_WRIT 1
 #  define HAVE_MNTENT 1
 # endif
-# if defined(X86_WIN32) || defined(X86_WIN64)
+# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
 /* Windows systems may have Data Execution Protection (DEP) enabled, 
    which requires the use of VirtualMalloc/VirtualFree to alloc/free
    executable memory. */
@@ -193,11 +193,11 @@ static int dlmalloc_trim(size_t) MAYBE_U
 static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
 static void dlmalloc_stats(void) MAYBE_UNUSED;
 
-#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
 /* Use these for mmap and munmap within dlmalloc.c.  */
 static void *dlmmap(void *, size_t, int, int, int, off_t);
 static int dlmunmap(void *, size_t);
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
 
 #define mmap dlmmap
 #define munmap dlmunmap
@@ -207,7 +207,7 @@ static int dlmunmap(void *, size_t);
 #undef mmap
 #undef munmap
 
-#if !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__)
+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
 
 /* A mutex used to synchronize access to *exec* variables in this file.  */
 static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -522,7 +522,7 @@ segment_holding_code (mstate m, char* ad
 }
 #endif
 
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64)) || defined (__CYGWIN__) */
+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
 
 /* Allocate a chunk of memory with the given size.  Returns a pointer
    to the writable address, and sets *CODE to the executable
Index: libffi/src/dlmalloc.c
===================================================================
--- libffi.orig/src/dlmalloc.c
+++ libffi/src/dlmalloc.c
@@ -459,6 +459,14 @@ DEFAULT_MMAP_THRESHOLD       default: 25
 #define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
 #endif  /* WIN32 */
 
+#ifdef __OS2__
+#define INCL_DOS
+#include <os2.h>
+#define HAVE_MMAP 1
+#define HAVE_MORECORE 0
+#define LACKS_SYS_MMAN_H
+#endif  /* __OS2__ */
+
 #if defined(DARWIN) || defined(_DARWIN)
 /* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
 #ifndef HAVE_MORECORE
@@ -1288,7 +1296,7 @@ extern void*     sbrk(ptrdiff_t);
 #define IS_MMAPPED_BIT       (SIZE_T_ONE)
 #define USE_MMAP_BIT         (SIZE_T_ONE)
 
-#ifndef WIN32
+#if !defined(WIN32) && !defined (__OS2__)
 #define CALL_MUNMAP(a, s)    munmap((a), (s))
 #define MMAP_PROT            (PROT_READ|PROT_WRITE)
 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
@@ -1311,6 +1319,42 @@ static int dev_zero_fd = -1; /* Cached f
 #endif /* MAP_ANONYMOUS */
 
 #define DIRECT_MMAP(s)       CALL_MMAP(s)
+
+#elif defined(__OS2__)
+
+/* OS/2 MMAP via DosAllocMem */
+static void* os2mmap(size_t size) {
+  void* ptr;
+  if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) &&
+      DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE))
+    return MFAIL;
+  return ptr;
+}
+
+#define os2direct_mmap(n)     os2mmap(n)
+
+/* This function supports releasing coalesed segments */
+static int os2munmap(void* ptr, size_t size) {
+  while (size) {
+    ULONG ulSize = size;
+    ULONG ulFlags = 0;
+    if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0)
+      return -1;
+    if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 ||
+        ulSize > size)
+      return -1;
+    if (DosFreeMem(ptr) != 0)
+      return -1;
+    ptr = ( void * ) ( ( char * ) ptr + ulSize );
+    size -= ulSize;
+  }
+  return 0;
+}
+
+#define CALL_MMAP(s)         os2mmap(s)
+#define CALL_MUNMAP(a, s)    os2munmap((a), (s))
+#define DIRECT_MMAP(s)       os2direct_mmap(s)
+
 #else /* WIN32 */
 
 /* Win32 MMAP via VirtualAlloc */
@@ -1387,7 +1431,7 @@ static int win32munmap(void* ptr, size_t
     unique mparams values are initialized only once.
 */
 
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__OS2__)
 /* By default use posix locks */
 #include <pthread.h>
 #define MLOCK_T pthread_mutex_t
@@ -1401,6 +1445,16 @@ static MLOCK_T morecore_mutex = PTHREAD_
 
 static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+#elif defined(__OS2__)
+#define MLOCK_T HMTX
+#define INITIAL_LOCK(l)      DosCreateMutexSem(0, l, 0, FALSE)
+#define ACQUIRE_LOCK(l)      DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT)
+#define RELEASE_LOCK(l)      DosReleaseMutexSem(*l)
+#if HAVE_MORECORE
+static MLOCK_T morecore_mutex;
+#endif /* HAVE_MORECORE */
+static MLOCK_T magic_init_mutex;
+
 #else /* WIN32 */
 /*
    Because lock-protected regions have bounded times, and there
@@ -2492,10 +2546,15 @@ static int init_mparams(void) {
     }
     RELEASE_MAGIC_INIT_LOCK();
 
-#ifndef WIN32
+#if !defined(WIN32) && !defined(__OS2__)
     mparams.page_size = malloc_getpagesize;
     mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
                            DEFAULT_GRANULARITY : mparams.page_size);
+#elif defined (__OS2__)
+ /* if low-memory is used, os2munmap() would break
+    if it were anything other than 64k */
+    mparams.page_size = 4096u;
+    mparams.granularity = 65536u;
 #else /* WIN32 */
     {
       SYSTEM_INFO system_info;
Index: libffi/src/x86/win32.S
===================================================================
--- libffi.orig/src/x86/win32.S
+++ libffi/src/x86/win32.S
@@ -395,7 +395,9 @@ END
         # This assumes we are using gas.
         .balign 16
 	.globl	_ffi_call_win32
+#ifndef __OS2__
 	.def	_ffi_call_win32;	.scl	2;	.type	32;	.endef
+#endif
 _ffi_call_win32:
 .LFB1:
         pushl %ebp
@@ -547,7 +549,9 @@ _ffi_call_win32:
         # This assumes we are using gas.
         .balign 16
 	.globl	_ffi_closure_SYSV
+#ifndef __OS2__
 	.def	_ffi_closure_SYSV;	.scl	2;	.type	32;	.endef
+#endif
 _ffi_closure_SYSV:
 .LFB3:
 	pushl	%ebp
@@ -668,7 +672,9 @@ _ffi_closure_SYSV:
         # This assumes we are using gas.
         .balign 16
 	.globl	_ffi_closure_raw_SYSV
+#ifndef __OS2__
 	.def	_ffi_closure_raw_SYSV;	.scl	2;	.type	32;	.endef
+#endif
 _ffi_closure_raw_SYSV:
 .LFB4:
 	pushl	%ebp
@@ -784,7 +790,9 @@ _ffi_closure_raw_SYSV:
         # This assumes we are using gas.
 	.balign	16
 	.globl	_ffi_closure_STDCALL
+#ifndef __OS2__
 	.def	_ffi_closure_STDCALL;	.scl	2;	.type	32;	.endef
+#endif
 _ffi_closure_STDCALL:
 .LFB5:
 	pushl	%ebp
@@ -890,7 +898,9 @@ _ffi_closure_STDCALL:
 .ffi_closure_STDCALL_end:
 .LFE5:
 
+#ifndef __OS2__
 	.section	.eh_frame,"w"
+#endif
 .Lframe1:
 .LSCIE1:
 	.long	.LECIE1-.LASCIE1  /* Length of Common Information Entry */
Index: libffi/README
===================================================================
--- libffi.orig/README
+++ libffi/README
@@ -75,6 +75,7 @@ tested:
 | X86          | Linux            |
 | X86          | Mac OSX          |
 | X86          | OpenBSD          |
+| X86          | OS/2             |
 | X86          | Solaris          |
 | X86          | Windows/Cygwin   |
 | X86          | Windows/MingW    |
