Attempting to port pthreads to the ColdFire (was: RE: [uClibc]Status of POSIX Thread Support in uClibc)

David McCullough davidm at snapgear.com
Sun Aug 25 03:22:57 UTC 2002


Jivin David Chan lays it down ...
> > Looks like it supports m68k but not the Coldfire and needs to be
> ported.
> > The missing instructions and addressing modes in the coldfire mean a 
> > little bit of work is needed here :-)
> 
> touche Davidm. 
> 
> I spent all morning trying to do just that and I was wondering if I
> could get a hand with it. I'm a bit new to the m68k platform, but I
> decided to give it the old college try. I did some poking around and
> decided that I wanted to edit
> libpthread/linuxthreads/sysdeps/m68k/pt-machine.h. (And when we have the
> bloody thing working, make a new arch called m68knommu or something.) 


You probably just need some 'ifdef __mcf5200' defines in the appropriate
places.  Or if it is possible to rewrite small portions to work on both
without hurting performance just do that.


> So, from examining the errors and source: 
> 
> /* Spinlock implementation; required.  */
> PT_EI int
> testandset (int *spinlock)
> {
>   char ret;
> 
>   __asm__ __volatile__("tas %1; sne %0"
>        : "=dm"(ret), "=m"(*spinlock)
>        : "m"(*spinlock) 
>        : "cc");
> 	   
>   return ret;
> }
> 
> 
> Error: invalid instruction for this architecture;
> needs 68000 or higher -- statement `tas (%a0)' ignored
> 
> - The tas instruction was eliminated from all ColdFire cores except for
> v4 cores. This 'test and set' routine is intended to guarantee an atomic
> read, modify, set behavior. This statement is intended to compare the
> operand (%a0) to zero and set the CC flags as necessary (N, Z), and then
> set the most significant bit of the byte to 1. This is supposed to be
> performed without interruption. Theoretically, we could replace this
> statement with a series of tst and andi instructions. But doesn't this
> lose the no-interruption behavior we want from the tas instruction?
> Could we suspend interrupts surrounding a replacement block to ensure
> its atomic behavior, since we're really not going to be running on
> multiple processors?


Not from within a user program.  Changing the SR register can only be done
in privileged mode and apps run in use rmode.

The only way I can think of doing this properly is to use semaphores or
some kind of kernel help.

You might want to code this one in 'C'.


> Error: operands mismatch -- statement `sne -1(%a6)' ignored
> 
> - So, some documentation I found said that a few addressing modes were
> omitted from the ColdFire. However, this "Address Register Indirect with
> Displacement Mode" should still be there. However, the syntax has
> changed from x(An) to (x,An). I have no idea where to change this
> behavior.
> 
> 
> 
> /* Compare-and-swap for semaphores. */
> 
> #define HAS_COMPARE_AND_SWAP
> PT_EI int
> __compare_and_swap (long int *p, long int oldval, long int newval)
> {
>   char ret;
>   long int readval;
> 
>   __asm__ __volatile__ ("casl %2, %3, %1; seq %0"
> 			: "=dm" (ret), "=m" (*p), "=d" (readval)
> /* output */
> 			: "d" (newval), "m" (*p), "2" (oldval));
> /* input */
> 
>   return ret;
> }
> 
> 
> Error: invalid instruction for this architecture;
> needs 68020 or higher -- statement `casl %d2,%d0,(%a0)' ignored
> 
> - The cas instruction has been completely omitted from the ColdFire
> instruction set. This 'compare and swap' instruction's behavior can
> essentially be summed up by this pseudo-code: 
> 
> [CAS d0,d1,(a0)] 
> 
> if (d0 == (a0)) {
> 	(a0) = d1;
> } else {
> 	d0 = (a0);
> }
> 
> So, this instruction could be replaced with something like:
> 
> 	cmp.l	(a0), d0
> 	bne.b	other
> 	move	d1, (a0)
> 	jmp	end
> other:
> 	move	(a0), d0
> end:
> 
> or... it looks like there's #define there. I wonder if the surrounding
> code would allow us to omit that #define and the associated function and
> take care of compare-and-swap by itself.

SOunds like the way to go.

> Error: operands mismatch -- statement `seq -1(%a6)' ignored
> 
> - See above.
> 
> Any help or advice on why this hasn't been done before would be nice.


I think your best choice is to re-implement testandset functions in 'C'
and get it going.  It hasn't been done before because no one has wanted it bad
enough I guess :-)

You can probably get away without any locking to begin with anyway. Just
remember to add it later ;-)

Comment out the __compare_and_swap stuff based on the __mcf5200 define
which is defined for all coldfire platforms by gcc,

Cheers,
Davidm

-- 
David McCullough:    Ph: +61 7 3435 2815  http://www.SnapGear.com
davidm at snapgear.com  Fx: +61 7 3891 3630  Custom Embedded Solutions + Security



More information about the uClibc mailing list