On Tue, Mar 8, 2022 at 7:26 AM Paolo Bonzini <[email protected]> wrote:

> On 3/8/22 15:09, Warner Losh wrote:
> >
> >     Yes, qatomic_foo is expected to work.  It's what we use across
> >     threads, and it is expected to work "in kernel mode", i.e. within
> cpu_loop().
> >
> > Even when the writers are done in the context of system calls to the
> kernel?
>
> Yes.
>
> That said, for the similar syscall in Linux we just forward it to the
> kernel (and the kernel obviously can only do an atomic---no
> start_exclusive/end_exclusive involved).
>

OK. It seemed similar to futex, but I didn't know if that worked because
it restricted itself, or because all atomics worked when used from the
kernel :)


> > And if the system call does this w/o using
> > the start_exclusive/end_exclusive stuff, is that a problem?
>
> If it does it without start_exclusive/end_exclusive they must use
> qatomic_foo().


So this answer is in the context *-user implementing a system call
that's executed as a callout from cpu_loop()? Or does the kernel
have to use the C11 atomics that qatomic_foo() is based on... I'm
thinking the former based on the above, but want to make sure.


> If it does it with start_exclusive/end_exclusive, they
> can even write a compare-and-exchange as
>
>      old = *(uint64_t *)g2h(cs, addr);
>      if (old == oldval)
>          *(uint64_t *)g2h(cs, addr) = new;
>

 Nice.

The test program that's seeing corrupted mutex state is just two threads.
I've simplified
it a bit (it's an ATF test, and there's a lot of boilerplate that I
removed, including validating
the return values). It looks pretty straight forward. Often it will work,
sometimes, though
it fails with an internal assertion in what implements pthread_mutex about
state that's
not possible w/o the atomics/system calls that implement the pthread_mutex
failing to
work.

Warner

P.S. Here's the code for reading purposes... W/o the headers it won't
compile and the
ATF stuff at the end comes from elsewhere...

static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
static int global_x;
bool thread3_started = false;

static void *
mutex3_threadfunc(void *arg) {
        long count = *(int *)arg;

        thread3_started = true;
        while (count--) {
                pthread_mutex_lock(&static_mutex);
                global_x++;
                pthread_mutex_unlock(&static_mutex);
        }
}

int main(int argc, char **argv) {
        int count, count2;
        pthread_t new;
        void *joinval;

        global_x = 0;
        count = count2 = 1000;
        pthread_mutex_lock(&static_mutex);
        pthread_create(&new, NULL, mutex3_threadfunc, &count2);
        while (!thread3_started) {
                /* Wait for thread 3 to start to increase chance of race */
        }
       pthread_mutex_unlock(&static_mutex);
       while (count--) {
                pthread_mutex_lock(&static_mutex);
                global_x++;
                pthread_mutex_unlock(&static_mutex);
        }

        pthread_join(new, &joinval);
        pthread_mutex_lock(&static_mutex);
        ATF_REQUIRE_EQ_MSG(count, -1, "%d", count);
        ATF_REQUIRE_EQ_MSG((long)joinval, -1, "%ld", (long)joinval);
        ATF_REQUIRE_EQ_MSG(global_x, 1000 * 2, "%d vs %d", globaol_x,
            1000 * 2);
}

Reply via email to