void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) { internal::AtomicWord state = internal::Acquire_Load(once); // Fast path. The provided closure was already executed. if (state == ONCE_STATE_DONE) { return; } // The closure execution did not complete yet. The once object can be in one // of the two following states: // - UNINITIALIZED: We are the first thread calling this function. // - EXECUTING_CLOSURE: Another thread is already executing the closure. // // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE // atomically. state = internal::Acquire_CompareAndSwap( once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE); if (state == ONCE_STATE_UNINITIALIZED) { // We are the first thread to call this function, so we have to call the // closure. closure->Run(); internal::Release_Store(once, ONCE_STATE_DONE); } else { // Another thread has already started executing the closure. We need to // wait until it completes the initialization. while (state == ONCE_STATE_EXECUTING_CLOSURE) { // Note that futex() could be used here on Linux as an improvement. SchedYield(); state = internal::Acquire_Load(once); } } }
static NTSTATUS GnttabRevokeForeignAccess( IN PINTERFACE Interface, IN PXENBUS_GNTTAB_CACHE Cache, IN BOOLEAN Locked, IN PXENBUS_GNTTAB_ENTRY Entry ) { PXENBUS_GNTTAB_CONTEXT Context = Interface->Context; volatile SHORT *flags; ULONG Attempt; NTSTATUS status; ASSERT3U(Entry->Magic, ==, XENBUS_GNTTAB_ENTRY_MAGIC); ASSERT3U(Entry->Reference, >=, XENBUS_GNTTAB_RESERVED_ENTRY_COUNT); ASSERT3U(Entry->Reference, <, (Context->FrameIndex + 1) * XENBUS_GNTTAB_ENTRY_PER_FRAME); flags = (volatile SHORT *)&Context->Table[Entry->Reference].flags; Attempt = 0; while (Attempt++ < 100) { uint16_t Old; uint16_t New; Old = *flags; Old &= ~(GTF_reading | GTF_writing); New = Old & ~GTF_permit_access; if (InterlockedCompareExchange16(flags, New, Old) == Old) break; SchedYield(); } status = STATUS_UNSUCCESSFUL; if (Attempt == 100) goto fail1; RtlZeroMemory(&Context->Table[Entry->Reference], sizeof (grant_entry_v1_t)); RtlZeroMemory(&Entry->Entry, sizeof (grant_entry_v1_t)); XENBUS_CACHE(Put, &Context->CacheInterface, Cache->Cache, Entry, Locked); return STATUS_SUCCESS; fail1: Error("fail1 (%08x)\n", status); return status; }
static NTSTATUS GnttabRevokeForeignAccess( IN PXENBUS_GNTTAB_CONTEXT Context, IN PXENBUS_GNTTAB_CACHE Cache, IN BOOLEAN Locked, IN PXENBUS_GNTTAB_DESCRIPTOR Descriptor ) { grant_entry_v1_t *Entry; volatile SHORT *Flags; ULONG Attempt; NTSTATUS status; ASSERT3U(Descriptor->Magic, ==, GNTTAB_DESCRIPTOR_MAGIC); ASSERT3U(Descriptor->Reference, >=, GNTTAB_RESERVED_ENTRY_COUNT); ASSERT3U(Descriptor->Reference, <, (Context->FrameIndex + 1) * GNTTAB_ENTRY_PER_FRAME); Entry = &Context->Entry[Descriptor->Reference]; Flags = (volatile SHORT *)&Entry->flags; Attempt = 0; while (Attempt++ < 100) { uint16_t Old; uint16_t New; Old = *Flags; Old &= ~(GTF_reading | GTF_writing); New = Old & ~GTF_permit_access; if (InterlockedCompareExchange16(Flags, New, Old) == Old) break; SchedYield(); } status = STATUS_UNSUCCESSFUL; if (Attempt == 100) goto fail1; RtlZeroMemory(Entry, sizeof (grant_entry_v1_t)); RtlZeroMemory(&Descriptor->Entry, sizeof (grant_entry_v1_t)); CACHE(Put, Context->CacheInterface, Cache->Cache, Descriptor, Locked); return STATUS_SUCCESS; fail1: Error("fail1 (%08x)\n", status); return status; }
int main() { SchedSet(NULL, NULL, SCHED_RR, NULL); SyncTypeCreate(_NTO_SYNC_SEM, &Semaphore, NULL); // initial count: 0 ThreadCreate(NULL, Thread1, NULL, NULL); ThreadCreate(NULL, Thread1, NULL, NULL); sleep(3); ThreadCreate(NULL, Thread2, NULL, NULL); SchedYield(); sleep(11); return(0); }
/*- *----------------------------------------------------------------------- * Reset -- * Tell DIX to reset itself when SIG_TERM is received. * * Results: * None. * * Side Effects: * clientsDoomed is set 1 and the dispatched is told to yield... * *----------------------------------------------------------------------- */ int Reset() { clientsDoomed = 1; SchedYield(); }