From cef5dfd75aca85d5fd3996d387cfee5a28b467c7 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 15 Mar 2010 21:29:15 +0000 Subject: * 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. --- winsup/cygwin/shared.cc | 178 +++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 92 deletions(-) (limited to 'winsup/cygwin/shared.cc') 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 #include #include @@ -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 -- cgit v1.2.3