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