Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2010-03-16 00:29:15 +0300
committerChristopher Faylor <me@cgf.cx>2010-03-16 00:29:15 +0300
commitcef5dfd75aca85d5fd3996d387cfee5a28b467c7 (patch)
tree118617d399410aeb76a778c48c7de8dbaed5df66
parent654e623ce009fc0d430eed044519539e624938cc (diff)
* shared_info.h (user_info): Add dll_crt0_1 as a friend.
(user_info::version): Make LONG to accommodate spinlock use. (user_info::create): New static function renamed from user_info_create. (user_info::initialize): New private function renamed from user_info_initialize. (SHARED_VERSION): Delete. (SHARED_VERSION_MAGIC): Ditto. (USER_VERSION_MAGIC): Ditto. (SHARED_INFO_CB): Ditto. (USER_VERSION): Ditto. (USER_VERSION_MAGIC): Ditto. (CURR_SHARED_MAGIC): Update. (CURR_USER_MAGIC): Ditto. (shared_info::version): Make LONG to accommodate spinlock use. (shared_info::create): New static function mirroring user_info::create. (dll_crt0_1): Accommodate change to user_info::initialize. * spinlock.h (spinlock::setto): New variable member. (spinlock::done): New function. (spinlock::spinlock): Generalize to allow arbitrary values and timeouts. Call done() when lock is not needed. * ntdll.h: Make multiple-inclusion safe. (NtQuerySystemTime): Declare. * shared.cc (installation_root_inited): Rename from shared_mem_inited. (init_installation_root): Make inline. Use a spinlock to ensure that this is initialized only once per session. (user_info::initialize): Rename from user_shared_initialize. Protect with spinlock on sversion and remove other spinlock-like things. Remove reference to user_shared since it is now implicit. Refer to spinlock version of multiple_cygwin_problem to ensure that any spinlock is released. (user_info::create): Rename from user_shared_create. Accommodate change from user_shared_initialize to user_info::initialize. (shared_info::create): New inline function. (shared_info::initialize): Protect with spinlock on sversion. Move heap_init back under specific control of shared_info spinlock. Remove reference to SHARED_INFO_CB and just use sizeof(*this). (memory_init): Move all locking into respective functions where it is needed. Accommodate name changes. Remove call to heap_init(). * syscalls.cc (seteuid32): Accommodate name change to user_info::create(). * mount.cc (mount_info::create_root_entry): Report on errors from add_item since they should be nonexistent. (mount_info::init): Don't initialize nmounts. It should already be zero. Give more verbose error when root_idx < 0. Implicitly use this pointer rather than explicitly referencing mount_table->. (mount_info::add_item): Minor whitespace fix.
-rw-r--r--winsup/cygwin/ChangeLog50
-rw-r--r--winsup/cygwin/dcrt0.cc2
-rw-r--r--winsup/cygwin/mount.cc21
-rw-r--r--winsup/cygwin/ntdll.h6
-rw-r--r--winsup/cygwin/shared.cc178
-rw-r--r--winsup/cygwin/shared_info.h21
-rw-r--r--winsup/cygwin/spinlock.h66
-rw-r--r--winsup/cygwin/syscalls.cc2
8 files changed, 218 insertions, 128 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 24ad6aa8a..141bf302b 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,55 @@
2010-03-15 Christopher Faylor <me+cygwin@cgf.cx>
+ * shared_info.h (user_info): Add dll_crt0_1 as a friend.
+ (user_info::version): Make LONG to accommodate spinlock use.
+ (user_info::create): New static function renamed from user_info_create.
+ (user_info::initialize): New private function renamed from
+ user_info_initialize.
+ (SHARED_VERSION): Delete.
+ (SHARED_VERSION_MAGIC): Ditto.
+ (USER_VERSION_MAGIC): Ditto.
+ (SHARED_INFO_CB): Ditto.
+ (USER_VERSION): Ditto.
+ (USER_VERSION_MAGIC): Ditto.
+ (CURR_SHARED_MAGIC): Update.
+ (CURR_USER_MAGIC): Ditto.
+ (shared_info::version): Make LONG to accommodate spinlock use.
+ (shared_info::create): New static function mirroring user_info::create.
+ (dll_crt0_1): Accommodate change to user_info::initialize.
+ * spinlock.h (spinlock::setto): New variable member.
+ (spinlock::done): New function.
+ (spinlock::spinlock): Generalize to allow arbitrary values and
+ timeouts. Call done() when lock is not needed.
+ * ntdll.h: Make multiple-inclusion safe.
+ (NtQuerySystemTime): Declare.
+ * shared.cc (installation_root_inited): Rename from shared_mem_inited.
+ (init_installation_root): Make inline. Use a spinlock to ensure that
+ this is initialized only once per session.
+ (user_info::initialize): Rename from user_shared_initialize. Protect
+ with spinlock on sversion and remove other spinlock-like things.
+ Remove reference to user_shared since it is now implicit. Refer to
+ spinlock version of multiple_cygwin_problem to ensure that any spinlock
+ is released.
+ (user_info::create): Rename from user_shared_create. Accommodate
+ change from user_shared_initialize to user_info::initialize.
+ (shared_info::create): New inline function.
+ (shared_info::initialize): Protect with spinlock on sversion. Move
+ heap_init back under specific control of shared_info spinlock. Remove
+ reference to SHARED_INFO_CB and just use sizeof(*this).
+ (memory_init): Move all locking into respective functions where it is
+ needed. Accommodate name changes. Remove call to heap_init().
+ * syscalls.cc (seteuid32): Accommodate name change to
+ user_info::create().
+
+ * mount.cc (mount_info::create_root_entry): Report on errors from
+ add_item since they should be nonexistent.
+ (mount_info::init): Don't initialize nmounts. It should already be
+ zero. Give more verbose error when root_idx < 0. Implicitly use this
+ pointer rather than explicitly referencing mount_table->.
+ (mount_info::add_item): Minor whitespace fix.
+
+2010-03-15 Christopher Faylor <me+cygwin@cgf.cx>
+
* sigproc.cc (no_signals_available): Get sense of the test right for
previous botched change.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 5cee9f886..6a1a341aa 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -778,7 +778,7 @@ dll_crt0_1 (void *)
have overridden malloc. We only know about that at this stage,
unfortunately. */
malloc_init ();
- user_shared_initialize ();
+ user_shared->initialize ();
#ifdef CGF
int i = 0;
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index e8d181125..d8dbb7662 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -338,8 +338,11 @@ mount_info::create_root_entry (const PWCHAR root)
The entry is immutable, unless the "override" option is given in /etc/fstab. */
char native_root[PATH_MAX];
sys_wcstombs (native_root, PATH_MAX, root);
- mount_table->add_item (native_root, "/",
- MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC);
+ assert (*native_root != '\0');
+ if (add_item (native_root, "/",
+ MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC)
+ < 0)
+ api_fatal ("add_item (\"%W\", \"/\", ...) failed, errno %d", native_root, errno);
/* Create a default cygdrive entry. Note that this is a user entry.
This allows to override it with mount, unless the sysadmin created
a cygdrive entry in /etc/fstab. */
@@ -353,7 +356,6 @@ mount_info::create_root_entry (const PWCHAR root)
void
mount_info::init ()
{
- nmounts = 0;
PWCHAR pathend;
WCHAR path[PATH_MAX];
@@ -367,19 +369,20 @@ mount_info::init ()
if (!got_usr_bin || !got_usr_lib)
{
char native[PATH_MAX];
- assert (root_idx != -1);
+ if (root_idx < 0)
+ api_fatal ("root_idx %d, user_shared magic %p, nmounts %d", root_idx, user_shared->version, nmounts);
char *p = stpcpy (native, mount[root_idx].native_path);
if (!got_usr_bin)
{
stpcpy (p, "\\bin");
- mount_table->add_item (native, "/usr/bin",
- MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC);
+ add_item (native, "/usr/bin",
+ MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC);
}
if (!got_usr_lib)
{
stpcpy (p, "\\lib");
- mount_table->add_item (native, "/usr/lib",
- MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC);
+ add_item (native, "/usr/lib",
+ MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC);
}
}
}
@@ -1285,7 +1288,7 @@ mount_info::add_item (const char *native, const char *posix,
if (nativeerr || posixerr)
{
- set_errno (nativeerr?:posixerr);
+ set_errno (nativeerr ?: posixerr);
return -1;
}
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 465d52782..7ac15cb18 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -9,6 +9,8 @@
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+#ifndef _NTDLL_H
+#define _NTDLL_H 1
#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
#define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
@@ -937,6 +939,9 @@ extern "C"
ULONG, ULONG *);
NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG);
+
+ NTSTATUS WINAPI NtQuerySystemTime (PLARGE_INTEGER);
+
NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, ULONG, PULONG);
NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS,
@@ -1094,3 +1099,4 @@ extern "C"
return NtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
}
}
+#endif /*_NTDLL_H*/
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index 6e166f3fa..4ef8807aa 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -24,7 +24,6 @@ details. */
#include "cygwin_version.h"
#include "pwdgrp.h"
#include "spinlock.h"
-#include "ntdll.h"
#include <alloca.h>
#include <wchar.h>
#include <wingdi.h>
@@ -38,7 +37,9 @@ HANDLE NO_COPY cygwin_user_h;
WCHAR installation_root[PATH_MAX] __attribute__((section (".cygwin_dll_common"), shared));
UNICODE_STRING installation_key __attribute__((section (".cygwin_dll_common"), shared));
WCHAR installation_key_buf[18] __attribute__((section (".cygwin_dll_common"), shared));
-static LONG shared_mem_inited __attribute__((section (".cygwin_dll_common"), shared));
+static LONG installation_root_inited __attribute__((section (".cygwin_dll_common"), shared));
+
+#define SPIN_WAIT 10000
/* Use absolute path of cygwin1.dll to derive the Win32 dir which
is our installation_root. Note that we can't handle Cygwin installation
@@ -63,58 +64,61 @@ static LONG shared_mem_inited __attribute__((section (".cygwin_dll_common"), sha
multiple Cygwin DLLs, which we're just not aware of right now. Cygcheck
can be used to change the value in an existing Cygwin DLL binary. */
-void
+void inline
init_installation_root ()
{
- if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX))
- api_fatal ("Can't initialize Cygwin installation root dir.\n"
- "GetModuleFileNameW(%p, %p, %u), %E",
- cygwin_hmodule, installation_root, PATH_MAX);
- PWCHAR p = installation_root;
- if (wcsncmp (p, L"\\\\?\\", 4)) /* No long path prefix. */
+ if (!spinlock (installation_root_inited))
{
- if (!wcsncasecmp (p, L"\\\\", 2)) /* UNC */
+ if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX))
+ api_fatal ("Can't initialize Cygwin installation root dir.\n"
+ "GetModuleFileNameW(%p, %p, %u), %E",
+ cygwin_hmodule, installation_root, PATH_MAX);
+ PWCHAR p = installation_root;
+ if (wcsncmp (p, L"\\\\?\\", 4)) /* No long path prefix. */
{
- p = wcpcpy (p, L"\\??\\UN");
- GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6);
- *p = L'C';
+ if (!wcsncasecmp (p, L"\\\\", 2)) /* UNC */
+ {
+ p = wcpcpy (p, L"\\??\\UN");
+ GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6);
+ *p = L'C';
+ }
+ else
+ {
+ p = wcpcpy (p, L"\\??\\");
+ GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4);
+ }
}
- else
- {
- p = wcpcpy (p, L"\\??\\");
- GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4);
- }
- }
- installation_root[1] = L'?';
+ installation_root[1] = L'?';
- RtlInitEmptyUnicodeString (&installation_key, installation_key_buf,
- sizeof installation_key_buf);
- RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root),
- &installation_key, FALSE);
+ RtlInitEmptyUnicodeString (&installation_key, installation_key_buf,
+ sizeof installation_key_buf);
+ RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root),
+ &installation_key, FALSE);
- PWCHAR w = wcsrchr (installation_root, L'\\');
- if (w)
- {
+ PWCHAR w = wcsrchr (installation_root, L'\\');
+ if (w)
+ {
+ *w = L'\0';
+ w = wcsrchr (installation_root, L'\\');
+ }
+ if (!w)
+ api_fatal ("Can't initialize Cygwin installation root dir.\n"
+ "Invalid DLL path");
*w = L'\0';
- w = wcsrchr (installation_root, L'\\');
- }
- if (!w)
- api_fatal ("Can't initialize Cygwin installation root dir.\n"
- "Invalid DLL path");
- *w = L'\0';
- for (int i = 1; i >= 0; --i)
- {
- reg_key r (i, KEY_WRITE, CYGWIN_INFO_INSTALLATIONS_NAME, NULL);
- if (r.set_string (installation_key_buf, installation_root)
- == ERROR_SUCCESS)
- break;
- }
+ for (int i = 1; i >= 0; --i)
+ {
+ reg_key r (i, KEY_WRITE, CYGWIN_INFO_INSTALLATIONS_NAME, NULL);
+ if (r.set_string (installation_key_buf, installation_root)
+ == ERROR_SUCCESS)
+ break;
+ }
- if (cygwin_props.disable_key)
- {
- installation_key.Length = 0;
- installation_key.Buffer[0] = L'\0';
+ if (cygwin_props.disable_key)
+ {
+ installation_key.Length = 0;
+ installation_key.Buffer[0] = L'\0';
+ }
}
}
@@ -301,35 +305,32 @@ open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
/* Second half of user shared initialization: Initialize content. */
void
-user_shared_initialize ()
+user_info::initialize ()
{
- DWORD sversion = (DWORD) InterlockedExchange ((LONG *) &user_shared->version, USER_VERSION_MAGIC);
/* Wait for initialization of the Cygwin per-user shared, if necessary */
+ spinlock sversion (version, CURR_USER_MAGIC);
if (!sversion)
{
+ cb = sizeof (*user_shared);
cygpsid sid (cygheap->user.sid ());
struct passwd *pw = internal_getpwsid (sid);
/* Correct the user name with what's defined in /etc/passwd before
loading the user fstab file. */
if (pw)
cygheap->user.set_name (pw->pw_name);
- user_shared->mountinfo.init (); /* Initialize the mount table. */
- user_shared->cb = sizeof (*user_shared);
- }
- else
- {
- while (!user_shared->cb)
- yield (); // Should be hit only very very rarely
- if (user_shared->version != sversion)
- multiple_cygwin_problem ("user shared memory version", user_shared->version, sversion);
- else if (user_shared->cb != sizeof (*user_shared))
- multiple_cygwin_problem ("user shared memory size", user_shared->cb, sizeof (*user_shared));
+ mountinfo.init (); /* Initialize the mount table. */
}
+ else if (sversion != CURR_USER_MAGIC)
+ sversion.multiple_cygwin_problem ("user shared memory version", version,
+ sversion);
+ else if (user_shared->cb != sizeof (*user_shared))
+ sversion.multiple_cygwin_problem ("user shared memory size", cb,
+ sizeof (*user_shared));
}
/* First half of user shared initialization: Create shared mem region. */
void
-user_shared_create (bool reinit)
+user_info::create (bool reinit)
{
WCHAR name[UNLEN + 1] = L""; /* Large enough for SID */
@@ -352,7 +353,7 @@ user_shared_create (bool reinit)
ProtectHandleINH (cygwin_user_h);
debug_printf ("user shared version %x", user_shared->version);
if (reinit)
- user_shared_initialize ();
+ user_shared->initialize ();
}
void __stdcall
@@ -383,10 +384,21 @@ shared_info::init_obcaseinsensitive ()
debug_printf ("obcaseinsensitive set to %d", obcaseinsensitive);
}
+void inline
+shared_info::create ()
+{
+ cygwin_shared = (shared_info *) open_shared (L"shared",
+ CYGWIN_VERSION_SHARED_DATA,
+ cygwin_shared_h,
+ sizeof (*cygwin_shared),
+ SH_CYGWIN_SHARED);
+ cygwin_shared->initialize ();
+}
+
void
shared_info::initialize ()
{
- DWORD sversion = (DWORD) InterlockedExchange ((LONG *) &version, SHARED_VERSION_MAGIC);
+ spinlock sversion (version, CURR_SHARED_MAGIC);
if (!sversion)
{
cb = sizeof (*this);
@@ -394,16 +406,19 @@ shared_info::initialize ()
init_obcaseinsensitive (); /* Initialize obcaseinsensitive */
tty.init (); /* Initialize tty table */
mt.initialize (); /* Initialize shared tape information */
+ /* Defer debug output printing the installation root and installation key
+ up to this point. Debug output except for system_printf requires
+ the global shared memory to exist. */
+ debug_printf ("Installation root: <%W> key: <%S>",
+ installation_root, &installation_key);
}
- else if (sversion != SHARED_VERSION_MAGIC)
- {
- InterlockedExchange ((LONG *) &version, sversion);
- multiple_cygwin_problem ("system shared memory version", sversion, SHARED_VERSION_MAGIC);
- }
-
- if (cb != SHARED_INFO_CB)
+ else if (sversion != (LONG) CURR_SHARED_MAGIC)
+ sversion.multiple_cygwin_problem ("system shared memory version",
+ sversion, CURR_SHARED_MAGIC);
+ else if (cb != sizeof (*this))
system_printf ("size of shared memory region changed from %u to %u",
- SHARED_INFO_CB, cb);
+ sizeof (*this), cb);
+ heap_init ();
}
void
@@ -418,30 +433,9 @@ memory_init (bool init_cygheap)
cygheap->user.init ();
}
- /* Initialize general shared memory under spinlock control */
- {
- spinlock smi (shared_mem_inited, 10000);
- if (!smi)
- init_installation_root (); /* Initialize installation root dir */
-
- cygwin_shared = (shared_info *) open_shared (L"shared",
- CYGWIN_VERSION_SHARED_DATA,
- cygwin_shared_h,
- sizeof (*cygwin_shared),
- SH_CYGWIN_SHARED);
- heap_init ();
-
- if (!smi)
- {
- cygwin_shared->initialize ();
- /* Defer debug output printing the installation root and installation key
- up to this point. Debug output except for system_printf requires
- the global shared memory to exist. */
- debug_printf ("Installation root: <%W> key: <%S>",
- installation_root, &installation_key);
- }
- }
- user_shared_create (false);
+ init_installation_root (); /* Initialize installation root dir */
+ shared_info::create (); /* Initialize global shared memory */
+ user_info::create (false); /* Initialize per-user shared memory */
}
unsigned
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index 52e6ce3df..f25ea15e2 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -16,33 +16,30 @@ details. */
class user_info
{
+ void initialize ();
public:
- DWORD version;
+ LONG version;
DWORD cb;
bool warned_msdos;
mount_info mountinfo;
+ friend void dll_crt0_1 (void *);
+ static void create (bool);
};
/******** Shared Info ********/
/* Data accessible to all tasks */
-#define SHARED_VERSION (unsigned)(cygwin_version.api_major << 8 | \
- cygwin_version.api_minor)
-#define SHARED_VERSION_MAGIC CYGWIN_VERSION_MAGIC (SHARED_MAGIC, SHARED_VERSION)
-
-#define SHARED_INFO_CB 31136
-#define CURR_SHARED_MAGIC 0x18da899eU
+#define CURR_SHARED_MAGIC 0xcebb78fcU
-#define USER_VERSION 1 // increment when mount table changes and
-#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION)
-#define CURR_USER_MAGIC 0xb2232e71U
+#define USER_VERSION 1
+#define CURR_USER_MAGIC 0x6112afb3U
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
different cygwin versions. */
class shared_info
{
- DWORD version;
+ LONG version;
DWORD cb;
public:
unsigned heap_chunk;
@@ -58,6 +55,7 @@ class shared_info
void init_obcaseinsensitive ();
unsigned heap_chunk_size ();
unsigned heap_slop_size ();
+ static void create ();
};
extern shared_info *cygwin_shared;
@@ -104,7 +102,6 @@ void *__stdcall open_shared (const WCHAR *, int, HANDLE&, DWORD,
shared_locations *, PSECURITY_ATTRIBUTES = &sec_all,
DWORD = FILE_MAP_READ | FILE_MAP_WRITE);
extern void user_shared_create (bool reinit);
-extern void user_shared_initialize ();
extern void init_installation_root ();
extern WCHAR installation_root[PATH_MAX];
extern UNICODE_STRING installation_key;
diff --git a/winsup/cygwin/spinlock.h b/winsup/cygwin/spinlock.h
index abf723acc..b55817245 100644
--- a/winsup/cygwin/spinlock.h
+++ b/winsup/cygwin/spinlock.h
@@ -11,30 +11,70 @@ details. */
#ifndef _SPINLOCK_H
#define _SPINLOCK_H
-#include "hires.h"
+#include "ntdll.h"
+
+#define SPINLOCK_WAIT (15000LL * 10000LL)
class spinlock
{
LONG *locker;
LONG val;
+ LONG setto;
+ void done (LONG what)
+ {
+ if (locker)
+ {
+ InterlockedExchange (locker, what);
+ locker = NULL;
+ }
+ }
+ long long time ()
+ {
+ LARGE_INTEGER t;
+ if (NtQuerySystemTime (&t) == STATUS_SUCCESS)
+ return get_ll (t);
+ return 0LL;
+ }
public:
- spinlock (LONG& locktest, LONGLONG timeout):
- locker (&locktest)
+ spinlock (LONG& locktest, LONG wanted_val = 1, LONGLONG timeout = SPINLOCK_WAIT):
+ locker (&locktest), setto (wanted_val)
{
- if ((val = locktest) == 1)
- return;
- LONGLONG then = gtod.msecs ();
- for (;;)
+ /* Quick test to see if we're already initialized */
+ if ((val = locktest) == wanted_val)
+ locker = NULL;
+ /* Slightly less quick test to see if we are the first cygwin process */
+ else if ((val = InterlockedExchange (locker, -1)) == 0)
+ /* We're armed and dangerous */;
+ else if (val == wanted_val)
+ done (val); /* This was initialized while we weren't looking */
+ else
{
- if ((val = InterlockedExchange (locker, -1)) != -1
- || (gtod.msecs () - then) >= timeout)
- break;
- yield ();
+ long long then = time ();
+ /* Loop waiting for some other process to set locktest to something
+ other than -1, indicating that initialization has finished. Or,
+ wait a default of 15 seconds for that to happen and, if it doesn't
+ just grab the lock ourselves. */
+ while ((val = InterlockedExchange (locker, -1)) == -1
+ && (time () - then) < timeout)
+ yield ();
+ /* Reset the lock back to wanted_value under the assumption that is
+ what caused the above loop to kick out. */
+ if (val == -1)
+ val = 0; /* Timed out. We'll initialize things ourselves. */
+ else
+ done (val); /* Put back whatever was there before, assuming that
+ it is actually wanted_val. */
}
}
- ~spinlock () {InterlockedExchange (locker, 1);}
+ ~spinlock () {done (setto);}
operator LONG () const {return val;}
+ /* FIXME: This should be handled in a more general fashion, probably by
+ establishing a linked list of spinlocks which are freed on process exit. */
+ void multiple_cygwin_problem (const char *w, unsigned m, unsigned v)
+ {
+ done (val);
+ ::multiple_cygwin_problem (w, m, v);
+ }
};
#endif /*_SPINLOCK_H*/
-
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 6f9260fcd..f7e55cce9 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2965,7 +2965,7 @@ seteuid32 (__uid32_t uid)
groups.ischanged = FALSE;
if (!issamesid)
/* Recreate and fill out the user shared region for a new user. */
- user_shared_create (true);
+ user_info::create (true);
return 0;
}