This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[vxworks] Fix ppc lock


I've applied this patch to fix a latent bug in the vxworks powerpc locking. The locking primitive vxworks provides on powerpc requires an aligned 4 byte object (this doesn't appear to be documented). We were just using a single byte, and most of the time we got lucky because the object being locked was a static object that was optimized to have 4 byte alignment and ended up with 3 bytes of trailing padding.

Unfortunately that sometimes fails. this is the least intrusive fix I could think of. For ppc we force the locking object to have 4 byte alignment and add 2 bytes of padding. Fortunately the locking operation only looks at one bit of the word, so it is ok to overlay the 'done' field onto the word that the ppc lock uses.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

2009-04-22  Nathan Sidwell  <nathan@codesourcery.com>

	* gthr-vxworks.h (struct __gthread_once_t): Add alignment and
	padding for PPC.
	(__GTHREAD_ONCE_INIT): Adjust ppc initializer.
	* config/vxlib.c (__gthread_once): Add race guard for PPC.

Index: gthr-vxworks.h
===================================================================
--- gthr-vxworks.h	(revision 146564)
+++ gthr-vxworks.h	(working copy)
@@ -115,17 +115,32 @@ __gthread_recursive_mutex_unlock (__gthr
 
 typedef struct
 {
-#ifndef __RTP__
+#if !defined(__RTP__)
+#if defined(__PPC__)
+  __attribute ((aligned (__alignof (unsigned))))
+#endif
   volatile unsigned char busy;
 #endif
   volatile unsigned char done;
+#if !defined(__RTP__) && defined(__PPC__)
+  /* PPC's test-and-set implementation requires a 4 byte aligned
+     object, of which it only sets the first byte.  We use padding
+     here, in order to maintain some amount of backwards
+     compatibility.  Without this padding, gthread_once objects worked
+     by accident because they happen to be static objects and the ppc
+     port automatically increased their alignment to 4 bytes.  */
+  unsigned char pad1;
+  unsigned char pad2;
+#endif
 }
 __gthread_once_t;
 
-#ifndef __RTP__
-# define __GTHREAD_ONCE_INIT { 0, 0 }
-#else
+#if defined (__RTP__)
 # define __GTHREAD_ONCE_INIT { 0 }
+#elif defined (__PPC__) 
+# define __GTHREAD_ONCE_INIT { 0, 0, 0, 0 }
+#else
+# define __GTHREAD_ONCE_INIT { 0, 0 }
 #endif
 
 extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void));
Index: config/vxlib.c
===================================================================
--- config/vxlib.c	(revision 146564)
+++ config/vxlib.c	(working copy)
@@ -65,7 +65,15 @@ __gthread_once (__gthread_once_t *guard,
   __gthread_lock_library ();
 #else
   while (!vxTas ((void *)&guard->busy))
-    taskDelay (1);
+    {
+#ifdef __PPC__
+      /* This can happen on powerpc, which is using all 32 bits
+	 of the gthread_once_t structure.  */
+      if (guard->done)
+	return;
+#endif
+      taskDelay (1);
+    }
 #endif
 
   /* Only one thread at a time gets here.  Check ->done again, then

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]