diff -Naurp glib-2.6.3-tests/glib/giochannel.c glib-2.6.3-atomic-ni/glib/giochannel.c
--- glib-2.6.3-tests/glib/giochannel.c	2004-11-08 19:49:35.000000000 +0100
+++ glib-2.6.3-atomic-ni/glib/giochannel.c	2005-03-11 12:38:55.000000000 +0100
@@ -96,7 +96,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;
 }
@@ -104,10 +104,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-2.6.3-tests/glib/gmain.c glib-2.6.3-atomic-ni/glib/gmain.c
--- glib-2.6.3-tests/glib/gmain.c	2004-11-08 19:49:35.000000000 +0100
+++ glib-2.6.3-atomic-ni/glib/gmain.c	2005-03-11 12:39:52.000000000 +0100
@@ -634,10 +634,14 @@ void
 g_main_context_unref (GMainContext *context)
 {
   GSource *source;
+  gboolean is_zero;
+
   g_return_if_fail (context != NULL);
   g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0); 
 
-  if (!g_atomic_int_dec_and_test (&context->ref_count))
+  is_zero =g_atomic_int_dec_and_test (&context->ref_count);
+
+  if (G_LIKELY (!is_zero))
     return;
 
   G_LOCK (main_context_list);
diff -Naurp glib-2.6.3-tests/gobject/gclosure.c glib-2.6.3-atomic-ni/gobject/gclosure.c
--- glib-2.6.3-tests/gobject/gclosure.c	2004-09-16 20:52:40.000000000 +0200
+++ glib-2.6.3-atomic-ni/gobject/gclosure.c	2005-03-31 16:12:15.927804744 +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(c)  							\
+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(c, 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-2.6.3-tests/gobject/gobject.c glib-2.6.3-atomic-ni/gobject/gobject.c
--- glib-2.6.3-tests/gobject/gobject.c	2004-09-16 20:52:40.000000000 +0200
+++ glib-2.6.3-atomic-ni/gobject/gobject.c	2005-03-31 18:20:45.329797496 +0200
@@ -111,6 +111,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
@@ -526,7 +527,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;
@@ -552,9 +553,11 @@ g_object_finalize (GObject *object)
 static void
 g_object_last_unref (GObject *object)
 {
+  gboolean is_zero;
+
   g_return_if_fail (object->ref_count > 0);
   
-  if (object->ref_count == 1)	/* may have been re-referenced meanwhile */
+  if (g_atomic_int_get (&object->ref_count) == 1)	/* may have been re-referenced meanwhile */
     G_OBJECT_GET_CLASS (object)->dispose (object);
   
 #ifdef	G_ENABLE_DEBUG
@@ -562,9 +565,10 @@ g_object_last_unref (GObject *object)
     G_BREAKPOINT ();
 #endif	/* G_ENABLE_DEBUG */
 
-  object->ref_count -= 1;
-  
-  if (object->ref_count == 0)	/* may have been re-referenced meanwhile */
+  is_zero = g_atomic_int_dec_and_test (&object->ref_count);
+
+  /* may have been re-referenced meanwhile */
+  if (G_LIKELY (is_zero)) 
     {
       g_signal_handlers_destroy (object);
       g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
@@ -608,12 +612,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
@@ -624,7 +631,8 @@ 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);
@@ -644,10 +652,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);
 }
@@ -658,16 +669,19 @@ 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);
 }
 
@@ -723,7 +737,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);
 }
@@ -1078,6 +1094,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);
   
@@ -1134,6 +1151,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
@@ -1239,6 +1257,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);
   
@@ -1264,6 +1283,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
@@ -1567,7 +1587,7 @@ g_object_ref (gpointer _object)
     G_BREAKPOINT ();
 #endif  /* G_ENABLE_DEBUG */
 
-  object->ref_count += 1;
+  g_atomic_int_inc (&object->ref_count);
   
   return object;
 }
@@ -1576,6 +1596,7 @@ void
 g_object_unref (gpointer _object)
 {
   GObject *object = _object;
+  gboolean is_zero;
 
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (object->ref_count > 0);
@@ -1585,10 +1606,16 @@ g_object_unref (gpointer _object)
     G_BREAKPOINT ();
 #endif  /* G_ENABLE_DEBUG */
 
-  if (object->ref_count > 1)
-    object->ref_count -= 1;
-  else
-    g_object_last_unref (object);
+  is_zero = g_atomic_int_dec_and_test (&object->ref_count);
+
+  if (G_UNLIKELY (is_zero))
+    {
+      /* inc again for performing last_unref, this temporarily
+       * introduces a refcount == 0 state, which is normally not
+       * visible to other threads as we hold the last ref. */
+      g_atomic_int_inc (&object->ref_count);
+      g_object_last_unref (object);
+    }
 }
 
 gpointer
@@ -1945,7 +1972,7 @@ g_object_watch_closure (GObject  *object
   g_return_if_fail (closure != NULL);
   g_return_if_fail (closure->is_invalid == FALSE);
   g_return_if_fail (closure->in_marshal == FALSE);
-  g_return_if_fail (object->ref_count > 0);	/* this doesn't work on finalizing objects */
+  g_return_if_fail (object->ref_count > 0); /* this doesn't work on finalizing objects */
   
   g_closure_add_invalidate_notifier (closure, object, object_remove_closure);
   g_closure_add_marshal_guards (closure,
@@ -1975,7 +2002,7 @@ g_closure_new_object (guint    sizeof_cl
   GClosure *closure;
 
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-  g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
+  g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
 
   closure = g_closure_new_simple (sizeof_closure, object);
   g_object_watch_closure (object, closure);
@@ -1990,7 +2017,7 @@ g_cclosure_new_object (GCallback callbac
   GClosure *closure;
 
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-  g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
+  g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
   g_return_val_if_fail (callback_func != NULL, NULL);
 
   closure = g_cclosure_new (callback_func, object, NULL);
@@ -2006,7 +2033,7 @@ g_cclosure_new_object_swap (GCallback ca
   GClosure *closure;
 
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-  g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
+  g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
   g_return_val_if_fail (callback_func != NULL, NULL);
 
   closure = g_cclosure_new_swap (callback_func, object, NULL);
diff -Naurp glib-2.6.3-tests/gobject/gparam.c glib-2.6.3-atomic-ni/gobject/gparam.c
--- glib-2.6.3-tests/gobject/gparam.c	2004-09-16 20:52:40.000000000 +0200
+++ glib-2.6.3-atomic-ni/gobject/gparam.c	2005-03-31 16:14:16.834424144 +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 --- */
@@ -164,43 +163,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);
     }
 }
 
@@ -208,29 +190,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-2.6.3-tests/gobject/gsignal.c glib-2.6.3-atomic-ni/gobject/gsignal.c
--- glib-2.6.3-tests/gobject/gsignal.c	2004-11-28 01:40:07.000000000 +0100
+++ glib-2.6.3-atomic-ni/gobject/gsignal.c	2005-03-31 16:20:56.275699840 +0200
@@ -219,8 +219,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;
@@ -564,12 +563,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
@@ -577,10 +571,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;
 
diff -Naurp glib-2.6.3-tests/gobject/gtype.c glib-2.6.3-atomic-ni/gobject/gtype.c
--- glib-2.6.3-tests/gobject/gtype.c	2004-11-01 19:47:12.000000000 +0100
+++ glib-2.6.3-atomic-ni/gobject/gtype.c	2005-03-31 18:58:09.053699616 +0200
@@ -1083,7 +1083,7 @@ type_data_ref_Wm (TypeNode *node)
     {
       g_assert (node->data->common.ref_count > 0);
       
-      node->data->common.ref_count += 1;
+      g_atomic_int_inc (&node->data->common.ref_count);
     }
 }
 
@@ -1091,12 +1091,17 @@ static inline void
 type_data_unref_Wm (TypeNode *node,
 		    gboolean  uncached)
 {
-  g_assert (node->data && node->data->common.ref_count);
+  gboolean is_zero;
+
+  g_assert (node->data->common.ref_count > 0);
   
-  if (node->data->common.ref_count > 1)
-    node->data->common.ref_count -= 1;
-  else
+  is_zero = g_atomic_int_dec_and_test (&node->data->common.ref_count);
+
+  if (G_UNLIKELY (is_zero)) 
     {
+      /* ref for last_unref call */
+      g_atomic_int_inc (&node->data->common.ref_count);
+
       if (!node->plugin)
 	{
 	  g_warning ("static type `%s' unreferenced too often",
@@ -1948,7 +1953,8 @@ type_data_finalize_class_ifaces_Wm (Type
 {
   guint i;
 
-  g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
+  g_assert (node->is_instantiatable && node->data && node->data->class.class && 
+		  node->data->common.ref_count == 0);
 
  reiterate:
   for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
@@ -2001,6 +2007,7 @@ type_data_last_unref_Wm (GType    type,
 			 gboolean uncached)
 {
   TypeNode *node = lookup_type_node_I (type);
+  gboolean is_zero;
   
   g_return_if_fail (node != NULL && node->plugin != NULL);
   
@@ -2027,7 +2034,7 @@ type_data_last_unref_Wm (GType    type,
 	  G_READ_UNLOCK (&type_rw_lock);
 	  need_break = cache_func (cache_data, node->data->class.class);
 	  G_READ_LOCK (&type_rw_lock);
-	  if (!node->data || node->data->common.ref_count == 0)
+          if (!node->data || node->data->common.ref_count == 0)
 	    INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
 	  if (need_break)
 	    break;
@@ -2035,16 +2042,14 @@ type_data_last_unref_Wm (GType    type,
       G_READ_UNLOCK (&type_rw_lock);
       G_WRITE_LOCK (&type_rw_lock);
     }
+
+  is_zero = g_atomic_int_dec_and_test (&node->data->common.ref_count);
   
-  if (node->data->common.ref_count > 1)	/* may have been re-referenced meanwhile */
-    node->data->common.ref_count -= 1;
-  else
+  if (G_LIKELY (is_zero)) /* may have been re-referenced meanwhile */
     {
       GType ptype = NODE_PARENT_TYPE (node);
       TypeData *tdata;
       
-      node->data->common.ref_count = 0;
-      
       if (node->is_instantiatable && node->data->instance.mem_chunk)
 	{
 	  g_mem_chunk_destroy (node->data->instance.mem_chunk);
