* 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.
This commit is contained in:
		
							parent
							
								
									654e623ce0
								
							
						
					
					
						commit
						cef5dfd75a
					
				|  | @ -1,3 +1,53 @@ | ||||||
|  | 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> | 2010-03-15  Christopher Faylor  <me+cygwin@cgf.cx> | ||||||
| 
 | 
 | ||||||
| 	* sigproc.cc (no_signals_available): Get sense of the test right for | 	* sigproc.cc (no_signals_available): Get sense of the test right for | ||||||
|  |  | ||||||
|  | @ -778,7 +778,7 @@ dll_crt0_1 (void *) | ||||||
|      have overridden malloc.  We only know about that at this stage, |      have overridden malloc.  We only know about that at this stage, | ||||||
|      unfortunately. */ |      unfortunately. */ | ||||||
|   malloc_init (); |   malloc_init (); | ||||||
|   user_shared_initialize (); |   user_shared->initialize (); | ||||||
| 
 | 
 | ||||||
| #ifdef CGF | #ifdef CGF | ||||||
|   int i = 0; |   int i = 0; | ||||||
|  |  | ||||||
|  | @ -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. */ |     The entry is immutable, unless the "override" option is given in /etc/fstab. */ | ||||||
|   char native_root[PATH_MAX]; |   char native_root[PATH_MAX]; | ||||||
|   sys_wcstombs (native_root, PATH_MAX, root); |   sys_wcstombs (native_root, PATH_MAX, root); | ||||||
|   mount_table->add_item (native_root, "/", |   assert (*native_root != '\0'); | ||||||
| 			 MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC); |   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.
 |   /* Create a default cygdrive entry.  Note that this is a user entry.
 | ||||||
|      This allows to override it with mount, unless the sysadmin created |      This allows to override it with mount, unless the sysadmin created | ||||||
|      a cygdrive entry in /etc/fstab. */ |      a cygdrive entry in /etc/fstab. */ | ||||||
|  | @ -353,7 +356,6 @@ mount_info::create_root_entry (const PWCHAR root) | ||||||
| void | void | ||||||
| mount_info::init () | mount_info::init () | ||||||
| { | { | ||||||
|   nmounts = 0; |  | ||||||
|   PWCHAR pathend; |   PWCHAR pathend; | ||||||
|   WCHAR path[PATH_MAX]; |   WCHAR path[PATH_MAX]; | ||||||
| 
 | 
 | ||||||
|  | @ -367,19 +369,20 @@ mount_info::init () | ||||||
|   if (!got_usr_bin || !got_usr_lib) |   if (!got_usr_bin || !got_usr_lib) | ||||||
|     { |     { | ||||||
|       char native[PATH_MAX]; |       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); |       char *p = stpcpy (native, mount[root_idx].native_path); | ||||||
|       if (!got_usr_bin) |       if (!got_usr_bin) | ||||||
|       { |       { | ||||||
| 	stpcpy (p, "\\bin"); | 	stpcpy (p, "\\bin"); | ||||||
| 	mount_table->add_item (native, "/usr/bin", | 	add_item (native, "/usr/bin", | ||||||
| 			       MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC); | 		  MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC); | ||||||
|       } |       } | ||||||
|       if (!got_usr_lib) |       if (!got_usr_lib) | ||||||
|       { |       { | ||||||
| 	stpcpy (p, "\\lib"); | 	stpcpy (p, "\\lib"); | ||||||
| 	mount_table->add_item (native, "/usr/lib", | 	add_item (native, "/usr/lib", | ||||||
| 			       MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC); | 		  MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_AUTOMATIC); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1285,7 +1288,7 @@ mount_info::add_item (const char *native, const char *posix, | ||||||
| 
 | 
 | ||||||
|   if (nativeerr || posixerr) |   if (nativeerr || posixerr) | ||||||
|     { |     { | ||||||
|       set_errno (nativeerr?:posixerr); |       set_errno (nativeerr ?: posixerr); | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,8 @@ | ||||||
|    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for |    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||||
|    details. */ |    details. */ | ||||||
| 
 | 
 | ||||||
|  | #ifndef _NTDLL_H | ||||||
|  | #define _NTDLL_H 1 | ||||||
| #define STATUS_NOT_ALL_ASSIGNED       ((NTSTATUS) 0x00000106) | #define STATUS_NOT_ALL_ASSIGNED       ((NTSTATUS) 0x00000106) | ||||||
| #define STATUS_OBJECT_NAME_EXISTS     ((NTSTATUS) 0x40000000) | #define STATUS_OBJECT_NAME_EXISTS     ((NTSTATUS) 0x40000000) | ||||||
| #define STATUS_BUFFER_OVERFLOW        ((NTSTATUS) 0x80000005) | #define STATUS_BUFFER_OVERFLOW        ((NTSTATUS) 0x80000005) | ||||||
|  | @ -937,6 +939,9 @@ extern "C" | ||||||
| 				ULONG, ULONG *); | 				ULONG, ULONG *); | ||||||
|   NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS, |   NTSTATUS NTAPI NtQuerySystemInformation (SYSTEM_INFORMATION_CLASS, | ||||||
| 					   PVOID, ULONG, PULONG); | 					   PVOID, ULONG, PULONG); | ||||||
|  | 
 | ||||||
|  |   NTSTATUS WINAPI NtQuerySystemTime (PLARGE_INTEGER); | ||||||
|  | 
 | ||||||
|   NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION, |   NTSTATUS NTAPI NtQuerySecurityObject (HANDLE, SECURITY_INFORMATION, | ||||||
| 					PSECURITY_DESCRIPTOR, ULONG, PULONG); | 					PSECURITY_DESCRIPTOR, ULONG, PULONG); | ||||||
|   NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS, |   NTSTATUS NTAPI NtQueryVirtualMemory (HANDLE, PVOID, MEMORY_INFORMATION_CLASS, | ||||||
|  | @ -1094,3 +1099,4 @@ extern "C" | ||||||
|     return NtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation); |     return NtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | #endif /*_NTDLL_H*/ | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ details. */ | ||||||
| #include "cygwin_version.h" | #include "cygwin_version.h" | ||||||
| #include "pwdgrp.h" | #include "pwdgrp.h" | ||||||
| #include "spinlock.h" | #include "spinlock.h" | ||||||
| #include "ntdll.h" |  | ||||||
| #include <alloca.h> | #include <alloca.h> | ||||||
| #include <wchar.h> | #include <wchar.h> | ||||||
| #include <wingdi.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)); | WCHAR installation_root[PATH_MAX] __attribute__((section (".cygwin_dll_common"), shared)); | ||||||
| UNICODE_STRING installation_key __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)); | 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
 | /* Use absolute path of cygwin1.dll to derive the Win32 dir which
 | ||||||
|    is our installation_root.  Note that we can't handle Cygwin installation |    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 |    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. */ |    can be used to change the value in an existing Cygwin DLL binary. */ | ||||||
| 
 | 
 | ||||||
| void | void inline | ||||||
| init_installation_root () | init_installation_root () | ||||||
| { | { | ||||||
|   if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX)) |   if (!spinlock (installation_root_inited)) | ||||||
|     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 (!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"); | 	  if (!wcsncasecmp (p, L"\\\\", 2))	/* UNC */ | ||||||
| 	  GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6); | 	    { | ||||||
| 	  *p = L'C'; | 	      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 |       installation_root[1] = L'?'; | ||||||
|  | 
 | ||||||
|  |       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) | ||||||
| 	{ | 	{ | ||||||
| 	  p = wcpcpy (p, L"\\??\\"); | 	  *w = L'\0'; | ||||||
| 	  GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4); | 	  w = wcsrchr (installation_root, L'\\'); | ||||||
| 	} | 	} | ||||||
|     } |       if (!w) | ||||||
|   installation_root[1] = L'?'; | 	api_fatal ("Can't initialize Cygwin installation root dir.\n" | ||||||
| 
 | 		   "Invalid DLL path"); | ||||||
|   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) |  | ||||||
|     { |  | ||||||
|       *w = L'\0'; |       *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) |       for (int i = 1; i >= 0; --i) | ||||||
|     { | 	{ | ||||||
|       reg_key r (i, KEY_WRITE, CYGWIN_INFO_INSTALLATIONS_NAME, NULL); | 	  reg_key r (i, KEY_WRITE, CYGWIN_INFO_INSTALLATIONS_NAME, NULL); | ||||||
|       if (r.set_string (installation_key_buf, installation_root) | 	  if (r.set_string (installation_key_buf, installation_root) | ||||||
| 	  == ERROR_SUCCESS) | 	      == ERROR_SUCCESS) | ||||||
|       	break; | 	    break; | ||||||
|     } | 	} | ||||||
| 
 | 
 | ||||||
|   if (cygwin_props.disable_key) |       if (cygwin_props.disable_key) | ||||||
|     { | 	{ | ||||||
|       installation_key.Length = 0; | 	  installation_key.Length = 0; | ||||||
|       installation_key.Buffer[0] = L'\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. */ | /* Second half of user shared initialization: Initialize content. */ | ||||||
| void | 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 */ |   /* Wait for initialization of the Cygwin per-user shared, if necessary */ | ||||||
|  |   spinlock sversion (version, CURR_USER_MAGIC); | ||||||
|   if (!sversion) |   if (!sversion) | ||||||
|     { |     { | ||||||
|  |       cb =  sizeof (*user_shared); | ||||||
|       cygpsid sid (cygheap->user.sid ()); |       cygpsid sid (cygheap->user.sid ()); | ||||||
|       struct passwd *pw = internal_getpwsid (sid); |       struct passwd *pw = internal_getpwsid (sid); | ||||||
|       /* Correct the user name with what's defined in /etc/passwd before
 |       /* Correct the user name with what's defined in /etc/passwd before
 | ||||||
| 	 loading the user fstab file. */ | 	 loading the user fstab file. */ | ||||||
|       if (pw) |       if (pw) | ||||||
| 	cygheap->user.set_name (pw->pw_name); | 	cygheap->user.set_name (pw->pw_name); | ||||||
|       user_shared->mountinfo.init ();	/* Initialize the mount table.  */ |       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)); |  | ||||||
|     } |     } | ||||||
|  |   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. */ | /* First half of user shared initialization: Create shared mem region. */ | ||||||
| void | void | ||||||
| user_shared_create (bool reinit) | user_info::create (bool reinit) | ||||||
| { | { | ||||||
|   WCHAR name[UNLEN + 1] = L""; /* Large enough for SID */ |   WCHAR name[UNLEN + 1] = L""; /* Large enough for SID */ | ||||||
| 
 | 
 | ||||||
|  | @ -352,7 +353,7 @@ user_shared_create (bool reinit) | ||||||
|   ProtectHandleINH (cygwin_user_h); |   ProtectHandleINH (cygwin_user_h); | ||||||
|   debug_printf ("user shared version %x", user_shared->version); |   debug_printf ("user shared version %x", user_shared->version); | ||||||
|   if (reinit) |   if (reinit) | ||||||
|     user_shared_initialize (); |     user_shared->initialize (); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void __stdcall | void __stdcall | ||||||
|  | @ -383,10 +384,21 @@ shared_info::init_obcaseinsensitive () | ||||||
|   debug_printf ("obcaseinsensitive set to %d", 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 | void | ||||||
| shared_info::initialize () | shared_info::initialize () | ||||||
| { | { | ||||||
|   DWORD sversion = (DWORD) InterlockedExchange ((LONG *) &version, SHARED_VERSION_MAGIC); |   spinlock sversion (version, CURR_SHARED_MAGIC); | ||||||
|   if (!sversion) |   if (!sversion) | ||||||
|     { |     { | ||||||
|       cb = sizeof (*this); |       cb = sizeof (*this); | ||||||
|  | @ -394,16 +406,19 @@ shared_info::initialize () | ||||||
|       init_obcaseinsensitive ();	/* Initialize obcaseinsensitive */ |       init_obcaseinsensitive ();	/* Initialize obcaseinsensitive */ | ||||||
|       tty.init ();			/* Initialize tty table  */ |       tty.init ();			/* Initialize tty table  */ | ||||||
|       mt.initialize ();			/* Initialize shared tape information */ |       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) |   else if (sversion != (LONG) CURR_SHARED_MAGIC) | ||||||
|     { |     sversion.multiple_cygwin_problem ("system shared memory version", | ||||||
|       InterlockedExchange ((LONG *) &version, sversion); | 				      sversion, CURR_SHARED_MAGIC); | ||||||
|       multiple_cygwin_problem ("system shared memory version", sversion, SHARED_VERSION_MAGIC); |   else if (cb != sizeof (*this)) | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   if (cb != SHARED_INFO_CB) |  | ||||||
|     system_printf ("size of shared memory region changed from %u to %u", |     system_printf ("size of shared memory region changed from %u to %u", | ||||||
| 		   SHARED_INFO_CB, cb); | 		   sizeof (*this), cb); | ||||||
|  |   heap_init (); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
|  | @ -418,30 +433,9 @@ memory_init (bool init_cygheap) | ||||||
|       cygheap->user.init (); |       cygheap->user.init (); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   /* Initialize general shared memory under spinlock control */ |   init_installation_root ();	/* Initialize installation root dir */ | ||||||
|   { |   shared_info::create ();	/* Initialize global shared memory */ | ||||||
|     spinlock smi (shared_mem_inited, 10000); |   user_info::create (false);	/* Initialize per-user shared memory */ | ||||||
|     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); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned | unsigned | ||||||
|  |  | ||||||
|  | @ -16,33 +16,30 @@ details. */ | ||||||
| 
 | 
 | ||||||
| class user_info | class user_info | ||||||
| { | { | ||||||
|  |   void initialize (); | ||||||
| public: | public: | ||||||
|   DWORD version; |   LONG version; | ||||||
|   DWORD cb; |   DWORD cb; | ||||||
|   bool warned_msdos; |   bool warned_msdos; | ||||||
|   mount_info mountinfo; |   mount_info mountinfo; | ||||||
|  |   friend void dll_crt0_1 (void *); | ||||||
|  |   static void create (bool); | ||||||
| }; | }; | ||||||
| /******** Shared Info ********/ | /******** Shared Info ********/ | ||||||
| /* Data accessible to all tasks */ | /* 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 0xcebb78fcU | ||||||
| 
 | 
 | ||||||
| #define CURR_SHARED_MAGIC 0x18da899eU | #define USER_VERSION   1 | ||||||
| 
 | #define CURR_USER_MAGIC 0x6112afb3U | ||||||
| #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 |  | ||||||
| 
 | 
 | ||||||
| /* NOTE: Do not make gratuitous changes to the names or organization of the
 | /* NOTE: Do not make gratuitous changes to the names or organization of the
 | ||||||
|    below class.  The layout is checksummed to determine compatibility between |    below class.  The layout is checksummed to determine compatibility between | ||||||
|    different cygwin versions. */ |    different cygwin versions. */ | ||||||
| class shared_info | class shared_info | ||||||
| { | { | ||||||
|   DWORD version; |   LONG version; | ||||||
|   DWORD cb; |   DWORD cb; | ||||||
|  public: |  public: | ||||||
|   unsigned heap_chunk; |   unsigned heap_chunk; | ||||||
|  | @ -58,6 +55,7 @@ class shared_info | ||||||
|   void init_obcaseinsensitive (); |   void init_obcaseinsensitive (); | ||||||
|   unsigned heap_chunk_size (); |   unsigned heap_chunk_size (); | ||||||
|   unsigned heap_slop_size (); |   unsigned heap_slop_size (); | ||||||
|  |   static void create (); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern shared_info *cygwin_shared; | extern shared_info *cygwin_shared; | ||||||
|  | @ -104,7 +102,6 @@ void *__stdcall open_shared (const WCHAR *, int, HANDLE&, DWORD, | ||||||
| 			     shared_locations *, PSECURITY_ATTRIBUTES = &sec_all, | 			     shared_locations *, PSECURITY_ATTRIBUTES = &sec_all, | ||||||
| 			     DWORD = FILE_MAP_READ | FILE_MAP_WRITE); | 			     DWORD = FILE_MAP_READ | FILE_MAP_WRITE); | ||||||
| extern void user_shared_create (bool reinit); | extern void user_shared_create (bool reinit); | ||||||
| extern void user_shared_initialize (); |  | ||||||
| extern void init_installation_root (); | extern void init_installation_root (); | ||||||
| extern WCHAR installation_root[PATH_MAX]; | extern WCHAR installation_root[PATH_MAX]; | ||||||
| extern UNICODE_STRING installation_key; | extern UNICODE_STRING installation_key; | ||||||
|  |  | ||||||
|  | @ -11,30 +11,70 @@ details. */ | ||||||
| #ifndef _SPINLOCK_H | #ifndef _SPINLOCK_H | ||||||
| #define _SPINLOCK_H | #define _SPINLOCK_H | ||||||
| 
 | 
 | ||||||
| #include "hires.h" | #include "ntdll.h" | ||||||
|  | 
 | ||||||
|  | #define SPINLOCK_WAIT (15000LL * 10000LL) | ||||||
| 
 | 
 | ||||||
| class spinlock | class spinlock | ||||||
| { | { | ||||||
|   LONG *locker; |   LONG *locker; | ||||||
|   LONG val; |   LONG val; | ||||||
| public: |   LONG setto; | ||||||
|   spinlock (LONG& locktest, LONGLONG timeout): |   void done (LONG what) | ||||||
|     locker (&locktest) |  | ||||||
|   { |   { | ||||||
|     if ((val = locktest) == 1) |     if (locker) | ||||||
|       return; |  | ||||||
|     LONGLONG then = gtod.msecs (); |  | ||||||
|     for (;;) |  | ||||||
|       { |       { | ||||||
| 	if ((val = InterlockedExchange (locker, -1)) != -1 | 	InterlockedExchange (locker, what); | ||||||
| 	    || (gtod.msecs () - then) >= timeout) | 	locker = NULL; | ||||||
| 	  break; |  | ||||||
| 	yield (); |  | ||||||
|       } |       } | ||||||
|   } |   } | ||||||
|   ~spinlock () {InterlockedExchange (locker, 1);} |   long long time () | ||||||
|  |   { | ||||||
|  |     LARGE_INTEGER t; | ||||||
|  |     if (NtQuerySystemTime (&t) == STATUS_SUCCESS) | ||||||
|  |       return get_ll (t); | ||||||
|  |     return 0LL; | ||||||
|  |   } | ||||||
|  | public: | ||||||
|  |   spinlock (LONG& locktest, LONG wanted_val = 1, LONGLONG timeout = SPINLOCK_WAIT): | ||||||
|  |     locker (&locktest), setto (wanted_val) | ||||||
|  |   { | ||||||
|  |     /* 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 | ||||||
|  |       { | ||||||
|  | 	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 () {done (setto);} | ||||||
|   operator LONG () const {return val;} |   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*/ | #endif /*_SPINLOCK_H*/ | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -2965,7 +2965,7 @@ seteuid32 (__uid32_t uid) | ||||||
|   groups.ischanged = FALSE; |   groups.ischanged = FALSE; | ||||||
|   if (!issamesid) |   if (!issamesid) | ||||||
|     /* Recreate and fill out the user shared region for a new user. */ |     /* Recreate and fill out the user shared region for a new user. */ | ||||||
|     user_shared_create (true); |     user_info::create (true); | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue