Added pluggable memory allocator and threading stub.
diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index 9d5ae7b..ee622b2 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -463,6 +463,8 @@
 typedef void (* GLFWscrollfun)(GLFWwindow,int,int);
 typedef void (* GLFWkeyfun)(GLFWwindow,int,int);
 typedef void (* GLFWcharfun)(GLFWwindow,int);
+typedef void* (* GLFWmallocfun)(size_t);
+typedef void (* GLFWfreefun)(void*);
 
 /* The video mode structure used by glfwGetVideoModes */
 typedef struct
@@ -482,6 +484,18 @@
     unsigned short blue[GLFW_GAMMA_RAMP_SIZE];
 } GLFWgammaramp;
 
+/* Custom memory allocator interface */
+typedef struct
+{
+    GLFWmallocfun malloc;
+    GLFWfreefun free;
+} GLFWallocator;
+
+/* Custom threading model interface */
+typedef struct
+{
+} GLFWthreadmodel;
+
 
 /*************************************************************************
  * Prototypes
@@ -489,6 +503,7 @@
 
 /* Initialization, termination and version querying */
 GLFWAPI int  glfwInit(void);
+GLFWAPI int  glfwInitWithModels(GLFWthreadmodel* threading, GLFWallocator* allocator);
 GLFWAPI void glfwTerminate(void);
 GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
 GLFWAPI const char* glfwGetVersionString(void);
diff --git a/readme.html b/readme.html
index c373a4b..6d54174 100644
--- a/readme.html
+++ b/readme.html
@@ -272,6 +272,7 @@
   <li>Added <code>glfwSetWindowFocusCallback</code> function and <code>GLFWwindowfocusfun</code> type for receiving window focus events</li>
   <li>Added <code>glfwSetWindowIconifyCallback</code> function and <code>GLFWwindowiconifyfun</code> type for receiving window iconification events</li>
   <li>Added <code>glfwGetCurrentWindow</code> function for retrieving the window whose OpenGL context is current</li>
+  <li>Added <code>glfwInitWithModels</code> function and <code>GLFWallocator</code> and <code>GLFWthreadmodel</code> types for pluggable memory allocation and threading models</li>
   <li>Added <code>GLFW_OPENGL_ES2_PROFILE</code> profile for creating OpenGL ES 2.0 contexts using the <code>GLX_EXT_create_context_es2_profile</code> and <code>WGL_EXT_create_context_es2_profile</code> extensions</li>
   <li>Added <code>windows</code> simple multi-window test program</li>
   <li>Added <code>sharing</code> simple OpenGL object sharing test program</li>
diff --git a/src/init.c b/src/init.c
index 99f0fd9..d83c19e 100644
--- a/src/init.c
+++ b/src/init.c
@@ -46,6 +46,30 @@
 
 
 //////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+//========================================================================
+// Allocate memory using the allocator
+//========================================================================
+
+void* _glfwMalloc(size_t size)
+{
+    return _glfwLibrary.allocator.malloc(size);
+}
+
+
+//========================================================================
+// Free memory using the allocator
+//========================================================================
+
+void _glfwFree(void* ptr)
+{
+    _glfwLibrary.allocator.free(ptr);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
 //////                        GLFW public API                       //////
 //////////////////////////////////////////////////////////////////////////
 
@@ -55,11 +79,42 @@
 
 GLFWAPI int glfwInit(void)
 {
+    return glfwInitWithModels(NULL, NULL);
+}
+
+
+//========================================================================
+// Initialize various GLFW state using custom model interfaces
+//========================================================================
+
+GLFWAPI int glfwInitWithModels(GLFWthreadmodel* threading, GLFWallocator* allocator)
+{
     if (_glfwInitialized)
         return GL_TRUE;
 
     memset(&_glfwLibrary, 0, sizeof(_glfwLibrary));
 
+    if (threading)
+        _glfwLibrary.threading = *threading;
+
+    if (allocator)
+    {
+        // Verify that the specified model is complete
+        if (!allocator->malloc || !allocator->free)
+        {
+            _glfwSetError(GLFW_INVALID_VALUE, NULL);
+            return GL_FALSE;
+        }
+
+        _glfwLibrary.allocator = *allocator;
+    }
+    else
+    {
+        // Use the libc malloc and free
+        _glfwLibrary.allocator.malloc = malloc;
+        _glfwLibrary.allocator.free = free;
+    }
+
     // Not all window hints are cleared to zero, so this needs to be here
     // despite the memset above
     _glfwClearWindowHints();
diff --git a/src/internal.h b/src/internal.h
index b0465e1..a9fbe16 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -228,6 +228,9 @@
     GLFWkeyfun           keyCallback;
     GLFWcharfun          charCallback;
 
+    GLFWthreadmodel      threading;
+    GLFWallocator        allocator;
+
     GLFWgammaramp currentRamp;
     GLFWgammaramp originalRamp;
     int           originalRampSize;
@@ -310,6 +313,10 @@
 // Prototypes for platform independent internal functions
 //========================================================================
 
+// Memory management (init.c)
+void* _glfwMalloc(size_t size);
+void _glfwFree(void* ptr);
+
 // Fullscren management (fullscreen.c)
 void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
 
diff --git a/src/win32/win32_window.c b/src/win32/win32_window.c
index 98c4daf..2def3a8 100644
--- a/src/win32/win32_window.c
+++ b/src/win32/win32_window.c
@@ -188,7 +188,7 @@
         return NULL;
     }
 
-    result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count);
+    result = (_GLFWfbconfig*) _glfwMalloc(sizeof(_GLFWfbconfig) * count);
     if (!result)
     {
         _glfwSetError(GLFW_OUT_OF_MEMORY, "Win32/WGL: Failed to allocate _GLFWfbconfig array");
@@ -1182,13 +1182,13 @@
     closest = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount);
     if (!closest)
     {
-        free(fbconfigs);
+        _glfwFree(fbconfigs);
         return 0;
     }
 
     pixelFormat = (int) closest->platformID;
 
-    free(fbconfigs);
+    _glfwFree(fbconfigs);
     fbconfigs = NULL;
     closest = NULL;
 
diff --git a/src/window.c b/src/window.c
index 8e16ad2..de497f7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -360,7 +360,7 @@
         return NULL;
     }
 
-    window = (_GLFWwindow*) malloc(sizeof(_GLFWwindow));
+    window = (_GLFWwindow*) _glfwMalloc(sizeof(_GLFWwindow));
     if (!window)
     {
         _glfwSetError(GLFW_OUT_OF_MEMORY, "glfwOpenWindow: Failed to allocate window structure");
@@ -692,7 +692,7 @@
         *prev = window->next;
     }
 
-    free(window);
+    _glfwFree(window);
 }
 
 
diff --git a/src/x11/x11_fullscreen.c b/src/x11/x11_fullscreen.c
index 40b85f9..c154fe3 100644
--- a/src/x11/x11_fullscreen.c
+++ b/src/x11/x11_fullscreen.c
@@ -356,7 +356,7 @@
         return 0;
     }
 
-    rgbarray = (int*) malloc(sizeof(int) * viscount);
+    rgbarray = (int*) _glfwMalloc(sizeof(int) * viscount);
     rgbcount = 0;
 
     // Build RGB array
@@ -400,7 +400,7 @@
         sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
         sizelist = XRRConfigSizes(sc, &sizecount);
 
-        resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * sizecount);
+        resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * sizecount);
 
         for (k = 0;  k < sizecount;  k++)
         {
@@ -417,7 +417,7 @@
 #if defined(_GLFW_HAS_XF86VIDMODE)
         XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, &modecount, &modelist);
 
-        resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * modecount);
+        resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * modecount);
 
         for (k = 0;  k < modecount;  k++)
         {
@@ -446,7 +446,7 @@
     if (!resarray)
     {
         rescount = 1;
-        resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * rescount);
+        resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * rescount);
 
         resarray[0].width = DisplayWidth(_glfwLibrary.X11.display, screen);
         resarray[0].height = DisplayHeight(_glfwLibrary.X11.display, screen);
@@ -470,8 +470,8 @@
     // Free visuals list
     XFree(vislist);
 
-    free(resarray);
-    free(rgbarray);
+    _glfwFree(resarray);
+    _glfwFree(rgbarray);
 
     return count;
 }
diff --git a/src/x11/x11_window.c b/src/x11/x11_window.c
index abafe39..3ecb15a 100644
--- a/src/x11/x11_window.c
+++ b/src/x11/x11_window.c
@@ -304,7 +304,7 @@
         }
     }
 
-    result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count);
+    result = (_GLFWfbconfig*) _glfwMalloc(sizeof(_GLFWfbconfig) * count);
     if (!result)
     {
         _glfwSetError(GLFW_OUT_OF_MEMORY, "X11/GLX: Failed to allocate _GLFWfbconfig array");
@@ -1341,12 +1341,12 @@
         result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount);
         if (!result)
         {
-            free(fbconfigs);
+            _glfwFree(fbconfigs);
             return GL_FALSE;
         }
 
         closest = *result;
-        free(fbconfigs);
+        _glfwFree(fbconfigs);
     }
 
     if (!createContext(window, wndconfig, (GLXFBConfigID) closest.platformID))