This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[vxworks] Fix ppc lock
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 22 Apr 2009 11:59:43 +0100
- Subject: [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