/* SPDX-License-Identifier: MIT */ #include #include #include #include #include #include "service-lock.h" static struct guest_service_lock fresh(void) { struct guest_service_lock lock={0}; assert(!guest_service_reusable(&lock)); assert(guest_service_boot(&lock)==SERVICE_OK); assert(guest_service_boot(&lock)==SERVICE_BAD_STATE); assert(guest_service_try(&lock,0)==SERVICE_OK); return lock; } struct racing_stop { struct guest_service_lock *lock; unsigned ready; }; static void *stop_thread(void *opaque) { struct racing_stop *r=opaque; __atomic_store_n(&r->ready,1,__ATOMIC_RELEASE); guest_service_stop(r->lock,0,SERVICE_STOP_NORMAL); return NULL; } int main(void) { struct guest_service_lock aborted=fresh(); assert(guest_service_finish(&aborted,0)==SERVICE_ABORTED); assert(guest_service_stopped(&aborted)==((UINT64_C(2)<<32)|1)); assert(guest_service_reusable(&aborted)); assert(guest_service_finish(&aborted,0)==SERVICE_OK); struct guest_service_lock peer=fresh(); assert(guest_service_reserve(&peer,0,1)==SERVICE_OK); assert(guest_service_release(&peer,0)==SERVICE_OK); assert(guest_service_arrive(&peer,1)==SERVICE_OK); assert(guest_service_try(&peer,1)==SERVICE_OK); assert(guest_service_finish(&peer,0)==SERVICE_OK); assert(guest_service_owner(&peer)==2); /* Never steal another executor. */ assert(!guest_service_reusable(&peer)); assert(guest_service_finish(&peer,1)==SERVICE_ABORTED); assert(!guest_service_reusable(&peer)); assert(guest_service_confirm_off(&peer,0,1,1)==SERVICE_OK); assert(guest_service_reusable(&peer)); for (unsigned cpu=1; cpu