1 /* spinlock.h: Header file for cygwin time-sensitive synchronization primitive.
3 Copyright 2010 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 #define SPINLOCK_WAIT (15000LL * 10000LL)
27 InterlockedExchange (locker, what);
34 if (NtQuerySystemTime (&t) == STATUS_SUCCESS)
39 spinlock (LONG& locktest, LONG wanted_val = 1, LONGLONG timeout = SPINLOCK_WAIT):
40 locker (&locktest), setto (wanted_val)
42 /* Quick test to see if we're already initialized */
43 if ((val = locktest) == wanted_val)
45 /* Slightly less quick test to see if we are the first cygwin process */
46 else if ((val = InterlockedExchange (locker, -1)) == 0)
47 /* We're armed and dangerous */;
48 else if (val == wanted_val)
49 done (val); /* This was initialized while we weren't looking */
52 long long then = time ();
53 /* Loop waiting for some other process to set locktest to something
54 other than -1, indicating that initialization has finished. Or,
55 wait a default of 15 seconds for that to happen and, if it doesn't
56 just grab the lock ourselves. */
57 while ((val = InterlockedExchange (locker, -1)) == -1
58 && (time () - then) < timeout)
60 /* Reset the lock back to wanted_value under the assumption that is
61 what caused the above loop to kick out. */
63 val = 0; /* Timed out. We'll initialize things ourselves. */
65 done (val); /* Put back whatever was there before, assuming that
66 it is actually wanted_val. */
69 ~spinlock () {done (setto);}
70 operator LONG () const {return val;}
71 /* FIXME: This should be handled in a more general fashion, probably by
72 establishing a linked list of spinlocks which are freed on process exit. */
73 void multiple_cygwin_problem (const char *w, unsigned m, unsigned v)
76 ::multiple_cygwin_problem (w, m, v);
80 #endif /*_SPINLOCK_H*/