Index: docs/reference/glib/glib-sections.txt
===================================================================
--- docs/reference/glib/glib-sections.txt	(revision 5648)
+++ docs/reference/glib/glib-sections.txt	(working copy)
@@ -1077,6 +1077,9 @@
 <SUBSECTION>
 GMappedFile
 g_mapped_file_new
+g_mapped_file_shared_new
+g_mapped_file_ref
+g_mapped_file_unref
 g_mapped_file_free
 g_mapped_file_get_length
 g_mapped_file_get_contents
Index: glib/glib.symbols
===================================================================
--- glib/glib.symbols	(revision 5648)
+++ glib/glib.symbols	(working copy)
@@ -631,8 +631,11 @@
 #if IN_HEADER(__G_MAPPED_FILE_H__)
 #if IN_FILE(__G_MAPPED_FILE_C__)
 g_mapped_file_new G_GNUC_MALLOC
+g_mapped_file_shared_new G_GNUC_MALLOC
 g_mapped_file_get_length
 g_mapped_file_get_contents
+g_mapped_file_ref
+g_mapped_file_unref
 g_mapped_file_free
 #endif
 #endif
Index: glib/gmappedfile.c
===================================================================
--- glib/gmappedfile.c	(revision 5648)
+++ glib/gmappedfile.c	(working copy)
@@ -47,6 +47,7 @@
 #include "gmessages.h"
 #include "gstdio.h"
 #include "gstrfuncs.h"
+#include "gatomic.h"
 
 #include "glibintl.h"
 
@@ -64,38 +65,17 @@
 {
   gsize  length;
   gchar *contents;
+  int    ref_count;
 #ifdef G_OS_WIN32
   HANDLE mapping;
 #endif
 };
 
-/**
- * g_mapped_file_new:
- * @filename: The path of the file to load, in the GLib filename encoding
- * @writable: wether the mapping should be writable
- * @error: return location for a #GError, or %NULL
- *
- * Maps a file into memory. On UNIX, this is using the mmap() function.
- *
- * If @writable is %TRUE, the mapped buffer may be modified, otherwise
- * it is an error to modify the mapped buffer. Modifications to the buffer 
- * are not visible to other processes mapping the same file, and are not 
- * written back to the file.
- *
- * Note that modifications of the underlying file might affect the contents
- * of the #GMappedFile. Therefore, mapping should only be used if the file 
- * will not be modified, or if all modifications of the file are done
- * atomically (e.g. using g_file_set_contents()). 
- *
- * Return value: a newly allocated #GMappedFile which must be freed
- *    with g_mapped_file_free(), or %NULL if the mapping failed. 
- *
- * Since: 2.8
- */
 GMappedFile *
-g_mapped_file_new (const gchar  *filename,
-		   gboolean      writable,
-		   GError      **error)
+g_mapped_file_new_internal (const gchar  *filename,
+                            gboolean      writable,
+                            gboolean      shared,
+                            GError      **error)
 {
   GMappedFile *file;
   int fd;
@@ -104,7 +84,11 @@
   g_return_val_if_fail (filename != NULL, NULL);
   g_return_val_if_fail (!error || *error == NULL, NULL);
 
-  fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
+  /* the file is only modified if readwrite & shared */
+  fd = g_open (filename,
+               ((writable & shared) ? O_RDWR : O_RDONLY) | _O_BINARY,
+               0666);
+
   if (fd == -1)
     {
       int save_errno = errno;
@@ -120,7 +104,8 @@
       return NULL;
     }
 
-  file = g_new0 (GMappedFile, 1);
+  file = g_slice_new0 (GMappedFile);
+  file->ref_count = 1;
 
   if (fstat (fd, &st) == -1)
     {
@@ -157,19 +142,26 @@
       file->length = (gsize) st.st_size;
       file->contents = (gchar *) mmap (NULL,  file->length,
 				       writable ? PROT_READ|PROT_WRITE : PROT_READ,
-				       MAP_PRIVATE, fd, 0);
+				       shared ? MAP_SHARED : MAP_PRIVATE,
+				       fd, 0);
     }
 #endif
 #ifdef G_OS_WIN32
   file->length = st.st_size;
   file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL,
-				     writable ? PAGE_WRITECOPY : PAGE_READONLY,
+				     writable ?
+				       (shared ?
+					 PAGE_READWRITE : PAGE_WRITECOPY)
+				       : PAGE_READONLY,
 				     0, 0,
 				     NULL);
   if (file->mapping != NULL)
     {
       file->contents = MapViewOfFile (file->mapping,
-				      writable ? FILE_MAP_COPY : FILE_MAP_READ,
+				      writable ?
+					(shared ?
+					  FILE_MAP_WRITE : FILE_MAP_COPY)
+					: FILE_MAP_READ,
 				      0, 0,
 				      0);
       if (file->contents == NULL)
@@ -202,12 +194,69 @@
 
  out:
   close (fd);
-  g_free (file);
+  g_slice_free (GMappedFile, file);
 
   return NULL;
 }
 
 /**
+ * g_mapped_file_new:
+ * @filename: The path of the file to load, in the GLib filename encoding
+ * @writable: whether the mapping should be writable
+ * @error: return location for a #GError, or %NULL
+ *
+ * Maps a file into memory. On UNIX, this is using the mmap() function.
+ *
+ * If @writable is %TRUE, the mapped buffer may be modified, otherwise
+ * it is an error to modify the mapped buffer. Modifications to the buffer 
+ * are not visible to other processes mapping the same file, and are not 
+ * written back to the file.
+ *
+ * Note that modifications of the underlying file might affect the contents
+ * of the #GMappedFile. Therefore, mapping should only be used if the file 
+ * will not be modified, or if all modifications of the file are done
+ * atomically (e.g. using g_file_set_contents()). 
+ *
+ * Return value: a newly allocated #GMappedFile which must be freed
+ *    with g_mapped_file_unref(), or %NULL if the mapping failed. 
+ *
+ * Since: 2.8
+ */
+GMappedFile *
+g_mapped_file_new (const gchar  *filename,
+                   gboolean      writable,
+                   GError      **error)
+{
+  return g_mapped_file_new_internal (filename, writable, FALSE, error);
+}
+
+/**
+ * g_mapped_file_shared_new:
+ * @filename: The path of the file to load, in the GLib filename encoding
+ * @writable: whether the mapping should be writable
+ * @error: return location for a #GError, or %NULL
+ *
+ * Maps a file into memory. On UNIX, this is using the mmap() function.
+ *
+ * If @writable is %TRUE, the mapped buffer may be modified, otherwise
+ * it is an error to modify the mapped buffer. Modifications to the buffer 
+ * are visible to other processes mapping the same file, and modifications
+ * made by other processes are visible to this one.
+ *
+ * Return value: a newly allocated #GMappedFile which must be freed
+ *    with g_mapped_file_unref(), or %NULL if the mapping failed. 
+ *
+ * Since: 2.16
+ */
+GMappedFile *
+g_mapped_file_shared_new (const gchar  *filename,
+                          gboolean      writable,
+                          GError      **error)
+{
+  return g_mapped_file_new_internal (filename, writable, TRUE, error);
+}
+
+/**
  * g_mapped_file_get_length:
  * @file: a #GMappedFile
  *
@@ -250,29 +299,77 @@
  * g_mapped_file_free:
  * @file: a #GMappedFile
  *
- * Unmaps the buffer of @file and frees it. 
+ * Atomically decrements the reference count of @hash_table by one.
+ * If the reference count drops to 0, unmaps the buffer of @file and
+ * frees it. This function is MT-safe and may be called from any thread.
  *
+ * This call existed before #GMappedFile had refcounting and is currently
+ * exactly the same as g_mapped_file_unref().
+ *
  * Since: 2.8
  */
 void
 g_mapped_file_free (GMappedFile *file)
 {
   g_return_if_fail (file != NULL);
+  g_return_if_fail (file->ref_count > 0);
 
-  if (file->length)
+  if (g_atomic_int_exchange_and_add (&file->ref_count, -1) - 1 == 0)
   {
+    if (file->length)
+    {
 #ifdef HAVE_MMAP
-    munmap (file->contents, file->length);
+      munmap (file->contents, file->length);
 #endif
 #ifdef G_OS_WIN32
-    UnmapViewOfFile (file->contents);
-    CloseHandle (file->mapping);
+      UnmapViewOfFile (file->contents);
+      CloseHandle (file->mapping);
 #endif
+    }
+
+    g_slice_free (GMappedFile, file);
   }
+}
 
-  g_free (file);
+/**
+ * g_mapped_file_ref:
+ * @file: a #GMappedFile
+ *
+ * Atomically increments the reference count of @file by one.
+ * This function is MT-safe and may be called from any thread.
+ *
+ * Return value: the passed in #GMappedFile.
+ *
+ * Since: 2.16
+ **/
+GMappedFile *
+g_mapped_file_ref (GMappedFile *file)
+{
+  g_return_val_if_fail (file != NULL, NULL);
+  g_return_val_if_fail (file->ref_count > 0, file);
+
+  g_atomic_int_add (&file->ref_count, 1);
+
+  return file;
 }
 
+/**
+ * g_mapped_file_unref:
+ * @file: a #GMappedFile
+ *
+ * Atomically decrements the reference count of @hash_table by one.
+ * If the reference count drops to 0, unmaps the buffer of @file and
+ * frees it. This function is MT-safe and may be called from any thread.
+ *
+ * This call is exactly the same as g_mapped_file_free().
+ *
+ * Since 2.16
+ **/
+void
+g_mapped_file_unref (GMappedFile *file)
+{
+  g_mapped_file_free (file);
+}
 
 #define __G_MAPPED_FILE_C__
 #include "galiasdef.c"
Index: glib/gmappedfile.h
===================================================================
--- glib/gmappedfile.h	(revision 5648)
+++ glib/gmappedfile.h	(working copy)
@@ -30,9 +30,14 @@
 GMappedFile *g_mapped_file_new          (const gchar  *filename,
 				         gboolean      writable,
 				         GError      **error) G_GNUC_MALLOC;
+GMappedFile *g_mapped_file_shared_new   (const gchar  *filename,
+                                         gboolean      writable,
+                                         GError      **error) G_GNUC_MALLOC;
 gsize        g_mapped_file_get_length   (GMappedFile  *file);
 gchar       *g_mapped_file_get_contents (GMappedFile  *file);
 void         g_mapped_file_free         (GMappedFile  *file);
+GMappedFile *g_mapped_file_ref          (GMappedFile  *file);
+void         g_mapped_file_unref        (GMappedFile  *file);
 
 G_END_DECLS
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5648)
+++ ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2007-99-99(after freeze)  Ryan Lortie  <desrt@desrt.ca>
+
+	* docs/reference/glib/glib-sections.txt:
+	* glib/glib.symbols:
+	* glib/gmappedfile.[ch]:
+	New functions g_mapped_file_shared_new for MAP_SHARED.
+	Add reference counting -- g_mapped_file_{ref,unref}.
+	Use GSlice instead of g_malloc for GMappedFile struct.
+
+	Bug #458796.
+
 2007-07-20  Alexander Larsson  <alexl@redhat.com>
 
         * configure.in:
