diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 2342a77bba4a225fa2c073e476b5cb913b072e55..7421806dc8b2213dadcd8e627116763fa6369517 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -36,6 +36,15 @@
 	* configure.ac: Ditto.
 	* configure: Rebuilt.
 
+2010-04-12  Dan Witte  <dwitte@mozilla.com>
+	    Walter Meinl <wuno@lsvw.de>
+
+	* configure.ac: Add OS/2 support.
+	* configure: Rebuilt.
+	* src/closures.c: Ditto.
+	* src/dlmalloc.c: Ditto.
+	* src/x86/win32.S: Ditto.
+
 2010-04-07  Jakub Jelinek  <jakub@redhat.com>
 
 	* regex.c (byte_re_match_2_internal): Avoid set but not used
diff --git a/libffi/README b/libffi/README
index 285cc69a3f3ad3437b7b1790c25e698c2ed4990e..3e3ab3fc950a3ef44a8d5badf8ddecb611c9c0b1 100644
--- a/libffi/README
+++ b/libffi/README
@@ -77,6 +77,7 @@ tested:
 | X86          | Linux            |
 | X86          | Mac OSX          |
 | X86          | OpenBSD          |
+| X86          | OS/2             |
 | X86          | Solaris          |
 | X86          | Windows/Cygwin   |
 | X86          | Windows/MingW    |
diff --git a/libffi/configure b/libffi/configure
index e92677a6b60ed77e9deb97b09148ecef67ca4a05..860bddd69eb7ce2c156f7645dc901af914758e0c 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -11357,7 +11357,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"
diff --git a/libffi/configure.ac b/libffi/configure.ac
index 61e746068dd65352d7258f5cd0bce5ac133fc353..64e80e2e7f7ca4c27e044455acd987dc8fcd6b55 100644
--- a/libffi/configure.ac
+++ b/libffi/configure.ac
@@ -80,7 +80,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"
diff --git a/libffi/src/closures.c b/libffi/src/closures.c
index 124ed44620666c2b3a0396cd5cb72dca2179a2b7..8f295dddc3c286cae949274aa08c9d55bfa44972 100644
--- a/libffi/src/closures.c
+++ b/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_UNUSED;
 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* addr)
 }
 #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
diff --git a/libffi/src/dlmalloc.c b/libffi/src/dlmalloc.c
index 2195b73cbdb23b1065c2d93af4b107aea8fadbda..0fa235af22e360555aef95300fdc649878197aff 100644
--- a/libffi/src/dlmalloc.c
+++ b/libffi/src/dlmalloc.c
@@ -459,6 +459,14 @@ DEFAULT_MMAP_THRESHOLD       default: 256K
 #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 file descriptor for /dev/zero. */
 #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 size) {
     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_MUTEX_INITIALIZER;
 
 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;
diff --git a/libffi/src/x86/win32.S b/libffi/src/x86/win32.S
index ac1ed6f942ab7a5a667bbab5bc9e3c0a176135d6..34ec0fd82becf08e0b38eca394c17b25ad609dc0 100644
--- a/libffi/src/x86/win32.S
+++ b/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 */