Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 May 2015 15:00:48 +0200
From:      Sebastian Huber <sebastian.huber@embedded-brains.de>
To:        freebsd-hackers@freebsd.org
Cc:        phk@phk.freebsd.dk
Subject:   Problem with timecounters and memory model
Message-ID:  <55686300.3080100@embedded-brains.de>

next in thread | raw e-mail | index | archive | help
Hello,

we ported the FreeBSD timecounters to the RTEMS real-time operating=20
system. On PowerPC with GCC 4.9 I noticed the following problem.  We have

void
binuptime(struct bintime *bt)
{
     struct timehands *th;
     u_int gen;

     do {
         th =3D timehands;
         gen =3D th->th_generation;
         *bt =3D th->th_offset;
         bintime_addx(bt, th->th_scale * tc_delta(th));
     } while (gen =3D=3D 0 || gen !=3D th->th_generation);
}

This is only valid if th->th_offset is read after th->th_generation and=20
the last write to th->th_generation is observable to all consumers=20
before the next write to th->th_offset etc.

On PowerPC we get the following code via GCC 4.9:

binuptime:
     stwu 1,-32(1)     #,,
     mflr 0     #,
     stw 26,8(1)     #,
     stw 0,36(1)     #,
     stw 27,12(1)     #,
     stw 28,16(1)     #,
     stw 29,20(1)     #,
     stw 31,28(1)     #,
     stw 30,24(1)     #,
     mr 30,3     # bt, bt
.L41:
     lwz 31,timehands@sdarel(13)     # timehands, th
     lwz 28,0(31)     # th_3->th_counter, tc
     lwz 8,40(31)     # th_3->th_offset, th_3->th_offset
     lwz 9,0(28)     # tc_13->tc_get_timecount, tc_13->tc_get_timecount
     mr 3,28     #, tc
     lwz 10,44(31)     # th_3->th_offset, th_3->th_offset
     lwz 6,32(31)     # th_3->th_offset, th_3->th_offset
     mtctr 9     #, tc_13->tc_get_timecount
     lwz 7,36(31)     # th_3->th_offset, th_3->th_offset

<- we read th_generation after th_offset

     lwz 27,64(31)     # th_3->th_generation, gen
     stw 8,8(30)     # *bt_5(D), th_3->th_offset
     stw 10,12(30)     # *bt_5(D), th_3->th_offset
     stw 6,0(30)     # *bt_5(D), th_3->th_offset
     stw 7,4(30)     # *bt_5(D), th_3->th_offset
     lwz 26,20(31)     # th_3->th_scale, D.6097
     lwz 29,16(31)     # th_3->th_scale, D.6097
     bctrl     #

Adding a compiler memory barrier yields:

void
binuptime(struct bintime *bt)
{
     struct timehands *th;
     uint32_t gen;

     do {
         th =3D timehands;
         gen =3D th->th_generation;
         __asm__ volatile("" ::: "memory");
         *bt =3D th->th_offset;
         bintime_addx(bt, th->th_scale * tc_delta(th));
     } while (gen =3D=3D 0 || gen !=3D th->th_generation);
}

binuptime:
     stwu 1,-32(1)     #,,
     mflr 0     #,
     stw 26,8(1)     #,
     stw 0,36(1)     #,
     stw 27,12(1)     #,
     stw 28,16(1)     #,
     stw 29,20(1)     #,
     stw 31,28(1)     #,
     stw 30,24(1)     #,
     mr 30,3     # bt, bt
.L41:
     lwz 31,timehands@sdarel(13)     # timehands, th
     lwz 27,64(31)     # th_3->th_generation, gen

<- we read th_generation before th_offset

     lwz 28,0(31)     # th_3->th_counter, tc
     lwz 9,44(31)     # th_3->th_offset, th_3->th_offset
     lwz 8,36(31)     # th_3->th_offset, th_3->th_offset
     mr 3,28     #, tc
     lwz 10,40(31)     # th_3->th_offset, th_3->th_offset
     lwz 7,32(31)     # th_3->th_offset, th_3->th_offset
     stw 9,12(30)     # *bt_6(D), th_3->th_offset
     lwz 9,0(28)     # tc_14->tc_get_timecount, tc_14->tc_get_timecount
     stw 8,4(30)     # *bt_6(D), th_3->th_offset
     mtctr 9     #, tc_14->tc_get_timecount
     stw 10,8(30)     # *bt_6(D), th_3->th_offset
     stw 7,0(30)     # *bt_6(D), th_3->th_offset
     lwz 26,20(31)     # th_3->th_scale, D.6097
     lwz 29,16(31)     # th_3->th_scale, D.6097
     bctrl     #

This version seems to work at least on uni-processor systems. Shouldn't=20
there be real memory barriers the synchronize the reads/writes to=20
th_generation for SMP machines?

--=20
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine gesch=C3=A4ftliche Mitteilung im Sinne des EHUG=
.




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