diff -Naurp glib-tests/glib/giochannel.c glib-atomic-ni/glib/giochannel.c
--- glib-tests/glib/giochannel.c	2005-07-08 12:57:38.000000000 +0200
+++ glib-atomic-ni/glib/giochannel.c	2005-07-08 13:45:40.000000000 +0200
@@ -97,7 +97,7 @@ g_io_channel_ref (GIOChannel *channel)
 {
   g_return_val_if_fail (channel != NULL, NULL);
 
-  channel->ref_count++;
+  g_atomic_int_inc (&channel->ref_count);
 
   return channel;
 }
@@ -105,10 +105,13 @@ g_io_channel_ref (GIOChannel *channel)
 void 
 g_io_channel_unref (GIOChannel *channel)
 {
+  gboolean is_zero;
+
   g_return_if_fail (channel != NULL);
 
-  channel->ref_count--;
-  if (channel->ref_count == 0)
+  is_zero = g_atomic_int_dec_and_test (&channel->ref_count);
+
+  if (G_UNLIKELY (is_zero))
     {
       if (channel->close_on_unref)
         g_io_channel_shutdown (channel, TRUE, NULL);
diff -Naurp glib-tests/gobject/gclosure.c glib-atomic-ni/gobject/gclosure.c
--- glib-tests/gobject/gclosure.c	2005-07-08 12:57:38.000000000 +0200
+++ glib-atomic-ni/gobject/gclosure.c	2005-07-08 13:52:47.000000000 +0200
@@ -36,6 +36,34 @@
 #define	CLOSURE_N_NOTIFIERS(cl)		(CLOSURE_N_MFUNCS (cl) + \
                                          (cl)->n_fnotifiers + \
                                          (cl)->n_inotifiers)
+#define REFCOUNT_MASK	0x7fff
+#define REFCOUNT_SHIFT	0
+#define REFCOUNT_ZERO	(0 << REFCOUNT_SHIFT)
+#define REFCOUNT_ONE	(1 << REFCOUNT_SHIFT)
+
+#define CLOSURE_REF(closure)  							\
+G_STMT_START {									\
+  guint32 old, new;								\
+  do {										\
+    old = g_atomic_int_get (((guint32*)(closure)));				\
+    new = (old + REFCOUNT_ONE);							\
+  }										\
+  while (!g_atomic_int_compare_and_exchange ((guint32*)(closure), old, new));	\
+} G_STMT_END
+
+#define CLOSURE_UNREF(closure, is_zero)  					\
+G_STMT_START {									\
+  guint32 old, new;								\
+  do {										\
+    old = g_atomic_int_get (((guint32*)(closure)));				\
+    if ((old & REFCOUNT_MASK) == REFCOUNT_ONE)	/* last unref, invalidate first */	\
+      g_closure_invalidate ((closure));						\
+    new = (old - REFCOUNT_ONE);							\
+    is_zero = ((new & REFCOUNT_MASK) == 0);					\
+  }										\
+  while (!g_atomic_int_compare_and_exchange ((guint32*)(closure), old, new));	\
+} G_STMT_END
+
 enum {
   FNOTIFY,
   INOTIFY,
@@ -312,7 +340,7 @@ g_closure_ref (GClosure *closure)
   g_return_val_if_fail (closure->ref_count > 0, NULL);
   g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL);
 
-  closure->ref_count += 1;
+  CLOSURE_REF (closure);
 
   return closure;
 }
@@ -324,7 +352,7 @@ g_closure_invalidate (GClosure *closure)
 
   if (!closure->is_invalid)
     {
-      closure->ref_count += 1;	/* preserve floating flag */
+      CLOSURE_REF (closure); 	/* preserve floating flag */
       closure->is_invalid = TRUE;
       closure_invoke_notifiers (closure, INOTIFY);
       g_closure_unref (closure);
@@ -334,15 +362,14 @@ g_closure_invalidate (GClosure *closure)
 void
 g_closure_unref (GClosure *closure)
 {
+  gboolean is_zero;
+
   g_return_if_fail (closure != NULL);
   g_return_if_fail (closure->ref_count > 0);
 
-  if (closure->ref_count == 1)	/* last unref, invalidate first */
-    g_closure_invalidate (closure);
-
-  closure->ref_count -= 1;
+  CLOSURE_UNREF (closure, is_zero);
 
-  if (closure->ref_count == 0)
+  if (G_UNLIKELY (is_zero))
     {
       closure_invoke_notifiers (closure, FNOTIFY);
       g_free (closure->notifiers);
@@ -364,10 +391,7 @@ g_closure_sink (GClosure *closure)
   if (closure->floating)
     {
       closure->floating = FALSE;
-      if (closure->ref_count > 1)
-	closure->ref_count -= 1;
-      else
-	g_closure_unref (closure);
+      g_closure_unref (closure);
     }
 }
 
@@ -420,7 +444,7 @@ g_closure_invoke (GClosure       *closur
 
       g_return_if_fail (closure->marshal || closure->meta_marshal);
 
-      closure->ref_count += 1;	/* preserve floating flag */
+      CLOSURE_REF (closure); 	/* preserve floating flag */
       closure->in_marshal = TRUE;
       if (closure->meta_marshal)
 	{
diff -Naurp glib-tests/gobject/gobject.c glib-atomic-ni/gobject/gobject.c
--- glib-tests/gobject/gobject.c	2005-07-08 12:57:38.000000000 +0200
+++ glib-atomic-ni/gobject/gobject.c	2005-07-08 16:09:27.000000000 +0200
@@ -66,7 +66,6 @@ static void	g_object_init				(GObject	*o
 static GObject*	g_object_constructor			(GType                  type,
 							 guint                  n_construct_properties,
 							 GObjectConstructParam *construct_params);
-static void	g_object_last_unref			(GObject	*object);
 static void	g_object_real_dispose			(GObject	*object);
 static void	g_object_finalize			(GObject	*object);
 static void	g_object_do_set_property		(GObject        *object,
@@ -117,6 +116,7 @@ static gulong	            gobject_signal
 G_LOCK_DEFINE_STATIC (construct_objects_lock);
 static GSList *construct_objects = NULL;
 
+static GStaticRecMutex notify_mutex = G_STATIC_REC_MUTEX_INIT;
 
 /* --- functions --- */
 #ifdef	G_ENABLE_DEBUG
@@ -533,7 +533,7 @@ g_object_real_dispose (GObject *object)
   /* yes, temporarily altering the ref_count is hackish, but that
    * enforces people not jerking around with weak_ref notifiers
    */
-  ref_count = object->ref_count;
+  ref_count = g_atomic_int_get (&object->ref_count);
   object->ref_count = 0;
   g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
   object->ref_count = ref_count;
@@ -556,38 +556,6 @@ g_object_finalize (GObject *object)
 #endif	/* G_ENABLE_DEBUG */
 }
 
-static void
-g_object_last_unref (GObject *object)
-{
-  g_return_if_fail (object->ref_count > 0);
-  
-  if (object->ref_count == 1)	/* may have been re-referenced meanwhile */
-    G_OBJECT_GET_CLASS (object)->dispose (object);
-  
-#ifdef	G_ENABLE_DEBUG
-  if (g_trap_object_ref == object)
-    G_BREAKPOINT ();
-#endif	/* G_ENABLE_DEBUG */
-
-  object->ref_count -= 1;
-  
-  if (object->ref_count == 0)	/* may have been re-referenced meanwhile */
-    {
-      g_signal_handlers_destroy (object);
-      g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
-      G_OBJECT_GET_CLASS (object)->finalize (object);
-#ifdef	G_ENABLE_DEBUG
-      IF_DEBUG (OBJECTS)
-	{
-	  /* catch objects not chaining finalize handlers */
-	  G_LOCK (debug_objects);
-	  g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
-	  G_UNLOCK (debug_objects);
-	}
-#endif	/* G_ENABLE_DEBUG */
-      g_type_free_instance ((GTypeInstance*) object);
-    }
-}
 
 static void
 g_object_dispatch_properties_changed (GObject     *object,
@@ -615,12 +583,15 @@ void
 g_object_freeze_notify (GObject *object)
 {
   g_return_if_fail (G_IS_OBJECT (object));
-  if (!object->ref_count)
+
+  if (g_atomic_int_get (&object->ref_count) == 0)
     return;
 
+  g_static_rec_mutex_lock (&notify_mutex);
   g_object_ref (object);
   g_object_notify_queue_freeze (object, &property_notify_context);
   g_object_unref (object);
+  g_static_rec_mutex_unlock (&notify_mutex);
 }
 
 void
@@ -631,7 +602,7 @@ g_object_notify (GObject     *object,
   
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (property_name != NULL);
-  if (!object->ref_count)
+  if (g_atomic_int_get (&object->ref_count) == 0)
     return;
   
   g_object_ref (object);
@@ -651,10 +622,13 @@ g_object_notify (GObject     *object,
 	       property_name);
   else
     {
-      GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
-
+      GObjectNotifyQueue *nqueue;
+      
+      g_static_rec_mutex_lock (&notify_mutex);
+      nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
       g_object_notify_queue_add (object, nqueue, pspec);
       g_object_notify_queue_thaw (object, nqueue);
+      g_static_rec_mutex_unlock (&notify_mutex);
     }
   g_object_unref (object);
 }
@@ -665,16 +639,18 @@ g_object_thaw_notify (GObject *object)
   GObjectNotifyQueue *nqueue;
   
   g_return_if_fail (G_IS_OBJECT (object));
-  if (!object->ref_count)
+  if (g_atomic_int_get (&object->ref_count) == 0)
     return;
   
   g_object_ref (object);
+  g_static_rec_mutex_lock (&notify_mutex);
   nqueue = g_object_notify_queue_from_object (object, &property_notify_context);
   if (!nqueue || !nqueue->freeze_count)
     g_warning ("%s: property-changed notification for %s(%p) is not frozen",
 	       G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
   else
     g_object_notify_queue_thaw (object, nqueue);
+  g_static_rec_mutex_unlock (&notify_mutex);
   g_object_unref (object);
 }
 
@@ -730,7 +706,9 @@ object_set_property (GObject            
   else
     {
       class->set_property (object, param_id, &tmp_value, pspec);
+      g_static_rec_mutex_lock (&notify_mutex);
       g_object_notify_queue_add (object, nqueue, pspec);
+      g_static_rec_mutex_unlock (&notify_mutex);
     }
   g_value_unset (&tmp_value);
 }
@@ -1085,6 +1063,7 @@ g_object_set_valist (GObject	 *object,
   
   g_return_if_fail (G_IS_OBJECT (object));
   
+  g_static_rec_mutex_lock (&notify_mutex);
   g_object_ref (object);
   nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
   
@@ -1141,6 +1120,7 @@ g_object_set_valist (GObject	 *object,
 
   g_object_notify_queue_thaw (object, nqueue);
   g_object_unref (object);
+  g_static_rec_mutex_unlock (&notify_mutex);
 }
 
 void
@@ -1246,6 +1226,7 @@ g_object_set_property (GObject	    *obje
   g_return_if_fail (property_name != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   
+  g_static_rec_mutex_lock (&notify_mutex);
   g_object_ref (object);
   nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
   
@@ -1271,6 +1252,7 @@ g_object_set_property (GObject	    *obje
   
   g_object_notify_queue_thaw (object, nqueue);
   g_object_unref (object);
+  g_static_rec_mutex_unlock (&notify_mutex);
 }
 
 void
@@ -1663,6 +1645,7 @@ gpointer
 g_object_ref (gpointer _object)
 {
   GObject *object = _object;
+  gint old_val;
 
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (object->ref_count > 0, NULL);
@@ -1672,8 +1655,10 @@ g_object_ref (gpointer _object)
     G_BREAKPOINT ();
 #endif  /* G_ENABLE_DEBUG */
 
-  object->ref_count += 1;
-  if (object->ref_count == 2 && OBJECT_HAS_TOGGLE_REF (object))
+
+  old_val = g_atomic_int_exchange_and_add (&object->ref_count, 1);
+
+  if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object))
     toggle_refs_notify (object, FALSE);
   
   return object;
@@ -1683,6 +1668,8 @@ void
 g_object_unref (gpointer _object)
 {
   GObject *object = _object;
+  gint old_val;
+  gboolean is_zero;
 
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (object->ref_count > 0);
@@ -1692,14 +1679,60 @@ g_object_unref (gpointer _object)
     G_BREAKPOINT ();
 #endif  /* G_ENABLE_DEBUG */
 
-  if (object->ref_count > 1)
+retry1:
+  old_val = g_atomic_int_get (&object->ref_count);
+  if (old_val > 1)
     {
-      object->ref_count -= 1;
-      if (object->ref_count == 1 && OBJECT_HAS_TOGGLE_REF (object))
+      if (!g_atomic_int_compare_and_exchange (&object->ref_count, old_val, old_val-1))
+	goto retry1;
+
+      /* if we went from 2->1 we need to notify toggle refs if any */
+      if (old_val == 2 && OBJECT_HAS_TOGGLE_REF (object))
 	toggle_refs_notify (object, TRUE);
     }
   else
-    g_object_last_unref (object);
+    {
+      /* removing the last ref */
+      G_OBJECT_GET_CLASS (object)->dispose (object);
+
+      /* dispose could have resurected the object */
+retry2:
+      old_val = g_atomic_int_get (&object->ref_count);
+      if (old_val > 1)
+        {
+          if (!g_atomic_int_compare_and_exchange (&object->ref_count, old_val, old_val-1))
+	    goto retry2;
+
+          /* if we went from 2->1 we need to notify toggle refs if any */
+          if (old_val == 2 && OBJECT_HAS_TOGGLE_REF (object))
+	    toggle_refs_notify (object, TRUE);
+
+	  return;
+	}
+
+      /* we are still taking away the last ref */
+      g_signal_handlers_destroy (object);
+      g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
+
+      /* now we really take away the last ref */
+      is_zero = g_atomic_int_dec_and_test (&object->ref_count);
+
+      /* may have been re-referenced meanwhile */
+      if (G_LIKELY (is_zero)) 
+	{
+          G_OBJECT_GET_CLASS (object)->finalize (object);
+#ifdef	G_ENABLE_DEBUG
+          IF_DEBUG (OBJECTS)
+	    {
+	      /* catch objects not chaining finalize handlers */
+	      G_LOCK (debug_objects);
+	      g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
+	      G_UNLOCK (debug_objects);
+	    }
+#endif	/* G_ENABLE_DEBUG */
+          g_type_free_instance ((GTypeInstance*) object);
+	}
+    }
 }
 
 gpointer
diff -Naurp glib-tests/gobject/gparam.c glib-atomic-ni/gobject/gparam.c
--- glib-tests/gobject/gparam.c	2005-07-08 12:57:38.000000000 +0200
+++ glib-atomic-ni/gobject/gparam.c	2005-07-08 14:02:25.000000000 +0200
@@ -64,7 +64,6 @@ static gchar*	value_param_lcopy_value		(
 
 /* --- variables --- */
 static GQuark quark_floating = 0;
-G_LOCK_DEFINE_STATIC (pspec_ref_count);
 
 
 /* --- functions --- */
@@ -169,43 +168,26 @@ GParamSpec*
 g_param_spec_ref (GParamSpec *pspec)
 {
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+  g_return_val_if_fail (pspec->ref_count > 0, NULL);
+
+  g_atomic_int_inc (&pspec->ref_count);
 
-  G_LOCK (pspec_ref_count);
-  if (pspec->ref_count > 0)
-    {
-      pspec->ref_count += 1;
-      G_UNLOCK (pspec_ref_count);
-    }
-  else
-    {
-      G_UNLOCK (pspec_ref_count);
-      g_return_val_if_fail (pspec->ref_count > 0, NULL);
-    }
-  
   return pspec;
 }
 
 void
 g_param_spec_unref (GParamSpec *pspec)
 {
+  gboolean is_zero;
+
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (pspec->ref_count > 0);
 
-  G_LOCK (pspec_ref_count);
-  if (pspec->ref_count > 0)
-    {
-      gboolean need_finalize;
+  is_zero = g_atomic_int_dec_and_test (&pspec->ref_count);
 
-      /* sync with _sink */
-      pspec->ref_count -= 1;
-      need_finalize = pspec->ref_count == 0;
-      G_UNLOCK (pspec_ref_count);
-      if (need_finalize)
-	G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
-    }
-  else
+  if (G_UNLIKELY (is_zero))
     {
-      G_UNLOCK (pspec_ref_count);
-      g_return_if_fail (pspec->ref_count > 0);
+      G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
     }
 }
 
@@ -213,29 +195,11 @@ void
 g_param_spec_sink (GParamSpec *pspec)
 {
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (pspec->ref_count > 0);
 
-  G_LOCK (pspec_ref_count);
-  if (pspec->ref_count > 0)
-    {
-      if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
-	{
-	  /* sync with _unref */
-	  if (pspec->ref_count > 1)
-	    pspec->ref_count -= 1;
-	  else
-	    {
-	      G_UNLOCK (pspec_ref_count);
-	      g_param_spec_unref (pspec);
-
-	      return;
-	    }
-	}
-      G_UNLOCK (pspec_ref_count);
-    }
-  else
+  if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
     {
-      G_UNLOCK (pspec_ref_count);
-      g_return_if_fail (pspec->ref_count > 0);
+      g_param_spec_unref (pspec);
     }
 }
 
diff -Naurp glib-tests/gobject/gsignal.c glib-atomic-ni/gobject/gsignal.c
--- glib-tests/gobject/gsignal.c	2005-07-08 12:57:39.000000000 +0200
+++ glib-atomic-ni/gobject/gsignal.c	2005-07-08 14:04:10.000000000 +0200
@@ -222,8 +222,7 @@ struct _Handler
   Handler      *next;
   Handler      *prev;
   GQuark	detail;
-  guint         ref_count : 16;
-#define HANDLER_MAX_REF_COUNT   (1 << 16)
+  guint         ref_count;	/* ABI change, was 16 bits but since it's internal... */
   guint         block_count : 12;
 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
   guint         after : 1;
@@ -567,12 +566,7 @@ handler_ref (Handler *handler)
 {
   g_return_if_fail (handler->ref_count > 0);
   
-#ifndef G_DISABLE_CHECKS
-  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
-    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
-#endif
-  
-  handler->ref_count += 1;
+  g_atomic_int_inc (&handler->ref_count);
 }
 
 static inline void
@@ -580,10 +574,13 @@ handler_unref_R (guint    signal_id,
 		 gpointer instance,
 		 Handler *handler)
 {
+  gboolean is_zero;
+
   g_return_if_fail (handler->ref_count > 0);
   
-  handler->ref_count -= 1;
-  if (!handler->ref_count)
+  is_zero = g_atomic_int_dec_and_test (&handler->ref_count);
+
+  if (G_UNLIKELY (is_zero))
     {
       HandlerList *hlist = NULL;
 
