OS/2 EMX port changes (Python part of patch #450267):
  Python/
    dynload_shlib.c  // EMX port emulates dlopen() etc. for DL extensions
    import.c         // changes to support 8.3 DLL name limit (VACPP+EMX)
                     //  and case sensitive import semantics
    importdl.h
    thread_os2.h
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
index e8a04ce..61674ba 100644
--- a/Python/dynload_shlib.c
+++ b/Python/dynload_shlib.c
@@ -18,6 +18,10 @@
 
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
+#else
+#if defined(PYOS_OS2) && defined(PYCC_GCC)
+#include "dlfcn.h"
+#endif
 #endif
 
 #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
@@ -32,9 +36,14 @@
 	{".dll", "rb", C_EXTENSION},
 	{"module.dll", "rb", C_EXTENSION},
 #else
+#if defined(PYOS_OS2) && defined(PYCC_GCC)
+	{".pyd", "rb", C_EXTENSION},
+	{".dll", "rb", C_EXTENSION},
+#else
 	{".so", "rb", C_EXTENSION},
 	{"module.so", "rb", C_EXTENSION},
 #endif
+#endif
 	{0, 0}
 };
 
@@ -82,7 +91,9 @@
 		}
 	}
 
+#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
         dlopenflags = PyThreadState_Get()->interp->dlopenflags;
+#endif
 
 	if (Py_VerboseFlag)
 		printf("dlopen(\"%s\", %x);\n", pathname, dlopenflags);
diff --git a/Python/import.c b/Python/import.c
index e657b70..e106aad 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -900,6 +900,11 @@
 	static struct filedescr fd_builtin = {"", "", C_BUILTIN};
 	static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
 	char name[MAXPATHLEN+1];
+#if defined(PYOS_OS2)
+	size_t saved_len;
+	size_t saved_namelen;
+	char *saved_buf = NULL;
+#endif
 
 	if (strlen(realname) > MAXPATHLEN) {
 		PyErr_SetString(PyExc_OverflowError,
@@ -1026,7 +1031,38 @@
 		fdp = PyMac_FindModuleExtension(buf, &len, name);
 		if (fdp) {
 #else
+#if defined(PYOS_OS2)
+		/* take a snapshot of the module spec for restoration
+		 * after the 8 character DLL hackery
+		 */
+		saved_buf = strdup(buf);
+		saved_len = len;
+		saved_namelen = namelen;
+#endif /* PYOS_OS2 */
 		for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) {
+#if defined(PYOS_OS2)
+			/* OS/2 limits DLLs to 8 character names (w/o extension)
+			 * so if the name is longer than that and its a
+			 * dynamically loaded module we're going to try,
+			 * truncate the name before trying
+			 */
+			if (strlen(realname) > 8) {
+				/* is this an attempt to load a C extension? */
+				const struct filedescr *scan = _PyImport_DynLoadFiletab;
+				while (scan->suffix != NULL) {
+					if (strcmp(scan->suffix, fdp->suffix) == 0)
+						break;
+					else
+						scan++;
+				}
+				if (scan->suffix != NULL) {
+					/* yes, so truncate the name */
+					namelen = 8;
+					len -= strlen(realname) - namelen;
+					buf[len] = '\0';
+				}
+			}
+#endif /* PYOS_OS2 */
 			strcpy(buf+len, fdp->suffix);
 			if (Py_VerboseFlag > 1)
 				PySys_WriteStderr("# trying %s\n", buf);
@@ -1040,7 +1076,21 @@
 					fp = NULL;
 				}
 			}
+#if defined(PYOS_OS2)
+			/* restore the saved snapshot */
+			strcpy(buf, saved_buf);
+			len = saved_len;
+			namelen = saved_namelen;
+#endif
 		}
+#if defined(PYOS_OS2)
+		/* don't need/want the module name snapshot anymore */
+		if (saved_buf)
+		{
+			free(saved_buf);
+			saved_buf = NULL;
+		}
+#endif
 		if (fp != NULL)
 			break;
 	}
@@ -1099,6 +1149,12 @@
 #include <sys/types.h>
 #include <dirent.h>
 
+#elif defined(PYOS_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_NOPMAPI
+#include <os2.h>
+
 #elif defined(RISCOS)
 #include "oslib/osfscontrol.h"
 #endif
@@ -1255,6 +1311,26 @@
 
 	return 0;
 
+/* OS/2 */
+#elif defined(PYOS_OS2)
+	HDIR hdir = 1;
+	ULONG srchcnt = 1;
+	FILEFINDBUF3 ffbuf;
+	APIRET rc;
+
+	if (getenv("PYTHONCASEOK") != NULL)
+		return 1;
+
+	rc = DosFindFirst(buf,
+			  &hdir,
+			  FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
+			  &ffbuf, sizeof(ffbuf),
+			  &srchcnt,
+			  FIL_STANDARD);
+	if (rc != NO_ERROR)
+		return 0;
+	return strncmp(ffbuf.achName, name, namelen) == 0;
+
 /* assuming it's a case-sensitive filesystem, so there's nothing to do! */
 #else
 	return 1;
diff --git a/Python/importdl.h b/Python/importdl.h
index 76fd05d..8e04f28 100644
--- a/Python/importdl.h
+++ b/Python/importdl.h
@@ -37,7 +37,7 @@
 #include <windows.h>
 typedef FARPROC dl_funcptr;
 #else
-#ifdef PYOS_OS2
+#if defined(PYOS_OS2) && !defined(PYCC_GCC)
 #include <os2def.h>
 typedef int (* APIENTRY dl_funcptr)();
 #else
diff --git a/Python/thread_os2.h b/Python/thread_os2.h
index a35f3e9..69bcd2c 100644
--- a/Python/thread_os2.h
+++ b/Python/thread_os2.h
@@ -7,8 +7,12 @@
 
 #include "process.h"
 
+#if defined(PYCC_GCC)
+#include <sys/builtin.h>
+#include <sys/fmutex.h>
+#else
 long PyThread_get_thread_ident(void);
-
+#endif
 
 /*
  * Initialization of the C package, should not be needed.
@@ -41,14 +45,20 @@
 long
 PyThread_get_thread_ident(void)
 {
+#if !defined(PYCC_GCC)
   PPIB pib;
   PTIB tib;
+#endif
 
   if (!initialized)
     PyThread_init_thread();
         
+#if defined(PYCC_GCC)
+  return _gettid();
+#else
   DosGetInfoBlocks(&tib,&pib);
   return tib->tib_ptib2->tib2_ultid;
+#endif
 }
 
 static void
@@ -103,7 +113,7 @@
 /*
  * Lock support.  This is implemented with an event semaphore and critical
  * sections to make it behave more like a posix mutex than its OS/2 
- # counterparts.
+ * counterparts.
  */
 
 typedef struct os2_lock_t {
@@ -114,6 +124,19 @@
 PyThread_type_lock 
 PyThread_allocate_lock(void)
 {
+#if defined(PYCC_GCC)
+  _fmutex *sem = malloc(sizeof(_fmutex));
+  if (!initialized)
+    PyThread_init_thread();
+  dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
+    PyThread_get_thread_ident(),
+    (long)sem));
+  if (_fmutex_create(sem, 0)) {
+    free(sem);
+    sem = NULL;
+  }
+  return (PyThread_type_lock) sem;
+#else
   APIRET rc;
   type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
 
@@ -130,16 +153,27 @@
            lock->changed));
 
   return (PyThread_type_lock) lock;
+#endif
 }
 
 void 
 PyThread_free_lock(PyThread_type_lock aLock)
 {
+#if !defined(PYCC_GCC)
   type_os2_lock lock = (type_os2_lock)aLock;
+#endif
+
   dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
+#if defined(PYCC_GCC)
+  if (aLock) {
+    _fmutex_close((_fmutex *)aLock);
+    free((_fmutex *)aLock);
+  }
+#else
   DosCloseEventSem(lock->changed);
   free(aLock);
+#endif
 }
 
 /*
@@ -150,15 +184,22 @@
 int 
 PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
 {
+#if !defined(PYCC_GCC)
   int   done = 0;
   ULONG count;
   PID   pid = 0;
   TID   tid = 0;
   type_os2_lock lock = (type_os2_lock)aLock;
+#endif
 
   dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),
            aLock, waitflag));
 
+#if defined(PYCC_GCC)
+  /* always successful if the lock doesn't exist */
+  if (aLock && _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
+      return 0;
+#else
   while (!done) {
     /* if the lock is currently set, we have to wait for the state to change */
     if (lock->is_set) {
@@ -182,15 +223,23 @@
 
     DosExitCritSec();
   }
+#endif
 
   return 1;
 }
 
 void PyThread_release_lock(PyThread_type_lock aLock)
 {
+#if defined(PYCC_GCC)
   type_os2_lock lock = (type_os2_lock)aLock;
+#endif
+
   dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
 
+#if defined(PYCC_GCC)
+  if (aLock)
+    _fmutex_release((_fmutex *)aLock);
+#else
   if (!lock->is_set) {
     dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
              PyThread_get_thread_ident(), aLock, GetLastError()));
@@ -208,4 +257,5 @@
   DosPostEventSem(lock->changed);
   
   DosExitCritSec();
+#endif
 }