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;
}

Reply via email to