On Wed, Jul 08, 2020 at 09:36:03AM -0600, Theo de Raadt wrote:
> Christian Weisgerber <[email protected]> wrote:
>
> > On 2020-06-26, George Koehler <[email protected]> wrote:
> >
> > > Here's macppc again. My macppc isn't using your newest diff but does
> > > now need to define TC_TB in <machine/timetc.h>.
> >
> > Crucial question: How confident are we that TB is in sync on
> > multiprocessor machines?
>
> Ugly test program (not showing it) seems to show syncronized clocks on
> powerpc, or at least closely sycronized. It might be one register.
I guess I'll share mine, then.
With this program I can consistently catch an offset of -2 to -1 on my
G5. Such a small offset is probably fine, right? I'm curious if it
gets any larger on other machines.
peanut$ cc -o tb-sync-check tb-sync-check.c -lpthread
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 91661686941 global 91661686943 (-2)
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 91721148999 global 91721149000 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 91773944538 global 91773944539 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T2: regression: local 91839284894 global 91839284895 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 91885196234 global 91885196235 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T2: regression: local 92460898355 global 92460898356 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T2: regression: local 92553793423 global 92553793424 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 92602154422 global 92602154423 (-1)
peanut$ ./tb-sync-check
tb-sync-check: T1: regression: local 92643366617 global 92643366619 (-2)
$
$ cat tb-sync-check.c
#include <sys/param.h>
#include <sys/atomic.h>
#include <err.h>
#include <pthread.h>
#include <stdint.h>
#include <signal.h>
uint64_t tb_global_max;
pthread_mutex_t tb_mtx = PTHREAD_MUTEX_INITIALIZER;
volatile sig_atomic_t uninterrupted = 1;
void handle_int(int);
uint64_t mftb(void);
void *tb_sync_test(void *);
int
main(int argc, char *argv[])
{
pthread_t thread[2];
sigset_t empty;
int error, i;
signal(SIGINT, handle_int);
tb_global_max = mftb();
for (i = 0; i < nitems(thread); i++) {
error = pthread_create(&thread[i], NULL, tb_sync_test,
(void *)(i + 1));
if (error)
errc(1, error, "pthread_create");
}
sigemptyset(&empty);
sigsuspend(&empty);
for (i = 0; i < nitems(thread); i++) {
error = pthread_join(thread[i], NULL);
if (error)
errc(1, error, "pthread_join");
}
return 0;
}
void
handle_int(int signo)
{
uninterrupted = 0;
}
/*
* Cribbed from sys/arch/powerpc/include/cpu.h.
*
* Hopefully it's correct.
*/
uint64_t
mftb(void)
{
u_long scratch;
u_int64_t tb;
asm volatile ("1: mftbu %0; mftb %L0; mftbu %1;"
" cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch));
return tb;
}
void *
tb_sync_test(void *id)
{
uint64_t tb_local;
unsigned int thread_id = (unsigned int)id;
while (uninterrupted) {
pthread_mutex_lock(&tb_mtx);
tb_local = mftb();
/*
* Does the local TimeBase lag behind the global maximum?
*/
if (tb_local < tb_global_max) {
errx(1, "T%u: regression: local %llu global %llu
(%lld)",
thread_id,
(unsigned long long)tb_local,
(unsigned long long)tb_global_max,
(long long)(tb_local - tb_global_max));
}
/*
* Update the global maximum.
*/
tb_global_max = tb_local;
pthread_mutex_unlock(&tb_mtx);
}
return NULL;
}