Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jun 2014 08:39:46 -0700
From:      Justin Hibbits <chmeeedalf@gmail.com>
To:        Julio Merino <jmmv@freebsd.org>
Cc:        freebsd-ppc@freebsd.org
Subject:   Re: Fix db48 in powerpc64
Message-ID:  <20140612083946.53a09762@zhabar.att.net>
In-Reply-To: <13D61493-60D9-480A-A0ED-DC29C3795C73@freebsd.org>
References:  <13D61493-60D9-480A-A0ED-DC29C3795C73@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 10 Apr 2014 18:58:02 -0400
Julio Merino <jmmv@freebsd.org> wrote:

> Hello,
> 
> The databases/db48 port does not build under FreeBSD powerpc64 due to
> a return type mismatch in an assembly routine.
> 
> The patch below fixes the *build*, but I have zero clue if it's
> correct or not; I'm just following the structure of all other
> routines.  I'm also pasting below everything related to powerpc in
> the relevant files, hoping that the comments give enough context.
> 
> Could someone that understands powerpc assembly please review this?
> 
> Thanks!
> 
> 
> ----- existing contents -----
> 
> /*********************************************************************
>  * PowerPC/gcc assembly.
>  *********************************************************************/
> #if defined(HAVE_MUTEX_PPC_GCC_ASSEMBLY)
> typedef u_int32_t tsl_t;
> 
> #ifdef LOAD_ACTUAL_MUTEX_CODE
> /*
>  * The PowerPC does a sort of pseudo-atomic locking.  You set up a
>  * 'reservation' on a chunk of memory containing a mutex by loading
> the
>  * mutex value with LWARX.  If the mutex has an 'unlocked' (arbitrary)
>  * value, you then try storing into it with STWCX.  If no other
> process or
>  * thread broke your 'reservation' by modifying the memory containing
> the
>  * mutex, then the STCWX succeeds; otherwise it fails and you try to
> get
>  * a reservation again.
>  *
>  * While mutexes are explicitly 4 bytes, a 'reservation' applies to an
>  * entire cache line, normally 32 bytes, aligned naturally.  If the
> mutex
>  * lives near data that gets changed a lot, there's a chance that
> you'll
>  * see more broken reservations than you might otherwise.  The only
>  * situation in which this might be a problem is if one processor is
>  * beating on a variable in the same cache block as the mutex while
> another
>  * processor tries to acquire the mutex.  That's bad news regardless
>  * because of the way it bashes caches, but if you can't guarantee
> that a
>  * mutex will reside in a relatively quiescent cache line, you might
>  * consider padding the mutex to force it to live in a cache line by
>  * itself.  No, you aren't guaranteed that cache lines are 32 bytes.
> Some
>  * embedded processors use 16-byte cache lines, while some 64-bit
>  * processors use 128-bit cache lines.  But assuming a 32-byte cache
> line
>  * won't get you into trouble for now.
>  *
>  * If mutex locking is a bottleneck, then you can speed it up by
> adding a
>  * regular LWZ load before the LWARX load, so that you can test for
> the
>  * common case of a locked mutex without wasting cycles making a
> reservation. *
>  * gcc/ppc: 0 is clear, 1 is set.
>  */
> static inline int
> MUTEX_SET(int *tsl)  {
>         int __r;
>         __asm__ volatile (
> "0:                             \n\t"
> "       lwarx   %0,0,%1         \n\t"
> "       cmpwi   %0,0            \n\t"
> "       bne-    1f              \n\t"
> "       stwcx.  %1,0,%1         \n\t"
> "       isync                   \n\t"
> "       beq+    2f              \n\t"
> "       b       0b              \n\t"
> "1:                             \n\t"
> "       li      %1,0            \n\t"
> "2:                             \n\t"
>          : "=&r" (__r), "+r" (tsl)
>          :
>          : "cr0", "memory");
>          return (int)tsl;
> }
> 
> static inline int
> MUTEX_UNSET(tsl_t *tsl) {
>          __asm__ volatile("sync" : : : "memory");
>          return *tsl = 0;
> }
> #define MUTEX_INIT(tsl)         MUTEX_UNSET(tsl)
> #endif
> #endif
> 
> 
> ----- diff -----
> 
> Index: files/patch-dbinc_mutex_int.h
> ===================================================================
> --- files/patch-dbinc_mutex_int.h	(revision 0)
> +++ files/patch-dbinc_mutex_int.h	(working copy)
> @@ -0,0 +1,11 @@
> +--- ../dbinc/mutex_int.h.orig	2014-04-04 12:52:15.255739375
> -0400 ++++ ../dbinc/mutex_int.h	2014-04-04 12:52:27.454733578
> -0400 +@@ -596,7 +596,7 @@ MUTEX_SET(int *tsl)  {
> + 	 : "=&r" (__r), "+r" (tsl)
> + 	 :
> + 	 : "cr0", "memory");
> +-	 return (int)tsl;
> ++	 return !__r;
> + }
> + 
> + static inline int

It looks like the 'correct' solution is 'return (tsl != NULL);' or
'return (tsl != 0);'

I just ran into this problem again myself.

With that, a bug should be filed so that in the future we can have a
working db4x (my db48 working dir was just erased by portmaster).

- Justin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140612083946.53a09762>