Cygwin: cwd: use SRWLOCK instead of muto

To reduce thread contention, use reader/writer locks as required.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2022-08-23 11:58:38 +02:00
parent ee54cabad9
commit 0819679a7a
4 changed files with 27 additions and 24 deletions

View File

@ -303,25 +303,30 @@ private:
public: public:
UNICODE_STRING win32; UNICODE_STRING win32;
static muto cwd_lock; static SRWLOCK NO_COPY cwd_lock;
static void acquire_read () { AcquireSRWLockShared (&cwd_lock); }
static void release_read () { ReleaseSRWLockShared (&cwd_lock); }
static void acquire_write () { AcquireSRWLockExclusive (&cwd_lock); }
static void release_write () { ReleaseSRWLockExclusive (&cwd_lock); }
const char *get_posix () const { return posix; }; const char *get_posix () const { return posix; };
void reset_posix (wchar_t *w_cwd); void reset_posix (wchar_t *w_cwd);
char *get (char *buf, int need_posix = 1, int with_chroot = 0, char *get (char *buf, int need_posix = 1, int with_chroot = 0,
unsigned ulen = NT_MAX_PATH); unsigned ulen = NT_MAX_PATH);
PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH) PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH)
{ {
cwd_lock.acquire (); acquire_read ();
buf[0] = L'\0'; buf[0] = L'\0';
wcsncat (buf, win32.Buffer, buflen - 1); wcsncat (buf, win32.Buffer, buflen - 1);
cwd_lock.release (); release_read ();
return buf; return buf;
} }
HANDLE get_handle () { return dir; } HANDLE get_handle () { return dir; }
DWORD get_drive (char * dst) DWORD get_drive (char * dst)
{ {
cwd_lock.acquire (); acquire_read ();
DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length); DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length);
cwd_lock.release (); release_read ();
return ret; return ret;
} }
int get_error () const { return error; } int get_error () const { return error; }

View File

@ -1583,7 +1583,7 @@ internal_setlocale ()
_sys_mbstowcs (cygheap->locale.mbtowc, w_path, 32768, path); _sys_mbstowcs (cygheap->locale.mbtowc, w_path, 32768, path);
} }
w_cwd = tp.w_get (); w_cwd = tp.w_get ();
cwdstuff::cwd_lock.acquire (); cwdstuff::acquire_write ();
_sys_mbstowcs (cygheap->locale.mbtowc, w_cwd, 32768, _sys_mbstowcs (cygheap->locale.mbtowc, w_cwd, 32768,
cygheap->cwd.get_posix ()); cygheap->cwd.get_posix ());
/* Set charset for internal conversion functions. */ /* Set charset for internal conversion functions. */
@ -1592,7 +1592,7 @@ internal_setlocale ()
cygheap->locale.mbtowc = __utf8_mbtowc; cygheap->locale.mbtowc = __utf8_mbtowc;
/* Restore CWD and PATH in new charset. */ /* Restore CWD and PATH in new charset. */
cygheap->cwd.reset_posix (w_cwd); cygheap->cwd.reset_posix (w_cwd);
cwdstuff::cwd_lock.release (); cwdstuff::release_write ();
if (w_path) if (w_path)
{ {
char *c_path = tp.c_get (); char *c_path = tp.c_get ();

View File

@ -103,7 +103,7 @@ struct symlink_info
bool set_error (int); bool set_error (int);
}; };
muto NO_COPY cwdstuff::cwd_lock; SRWLOCK NO_COPY cwdstuff::cwd_lock;
static const GUID GUID_shortcut static const GUID GUID_shortcut
= { 0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}}; = { 0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
@ -4737,12 +4737,10 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count)
} }
} }
/* Initialize cygcwd 'muto' for serializing access to cwd info. */ /* Initialize cwdstuff */
void void
cwdstuff::init () cwdstuff::init ()
{ {
cwd_lock.init ("cwd_lock");
/* Cygwin processes inherit the cwd from their parent. If the win32 path /* Cygwin processes inherit the cwd from their parent. If the win32 path
buffer is not NULL, the cwd struct is already set up, and we only buffer is not NULL, the cwd struct is already set up, and we only
have to override the Win32 CWD with ours. */ have to override the Win32 CWD with ours. */
@ -4800,8 +4798,6 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
Win32 CWD to a "weird" directory in which all relative filesystem-related Win32 CWD to a "weird" directory in which all relative filesystem-related
calls fail. */ calls fail. */
cwd_lock.acquire ();
if (nat_cwd) if (nat_cwd)
{ {
upath = *nat_cwd->get_nt_native_path (); upath = *nat_cwd->get_nt_native_path ();
@ -4825,6 +4821,8 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
} }
} }
acquire_write ();
/* Memorize old DismountCount before opening the dir. This value is /* Memorize old DismountCount before opening the dir. This value is
stored in the FAST_CWD structure. It would be simpler to fetch the stored in the FAST_CWD structure. It would be simpler to fetch the
old DismountCount in override_win32_cwd, but Windows also fetches old DismountCount in override_win32_cwd, but Windows also fetches
@ -4888,7 +4886,7 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
/* Called from chdir? Just fail. */ /* Called from chdir? Just fail. */
if (nat_cwd) if (nat_cwd)
{ {
cwd_lock.release (); release_write ();
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
return -1; return -1;
} }
@ -4905,7 +4903,7 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
peb.ProcessParameters->CurrentDirectoryHandle, peb.ProcessParameters->CurrentDirectoryHandle,
GetCurrentProcess (), &h, 0, TRUE, 0)) GetCurrentProcess (), &h, 0, TRUE, 0))
{ {
cwd_lock.release (); release_write ();
if (peb.ProcessParameters->CurrentDirectoryHandle) if (peb.ProcessParameters->CurrentDirectoryHandle)
debug_printf ("...and DuplicateHandle failed with %E."); debug_printf ("...and DuplicateHandle failed with %E.");
dir = NULL; dir = NULL;
@ -5027,7 +5025,7 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1);
stpcpy (posix, posix_cwd); stpcpy (posix, posix_cwd);
cwd_lock.release (); release_write ();
return 0; return 0;
} }
@ -5079,7 +5077,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
goto out; goto out;
} }
cwd_lock.acquire (); acquire_read ();
char *tocopy; char *tocopy;
if (!need_posix) if (!need_posix)
@ -5106,7 +5104,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
strcpy (buf, "/"); strcpy (buf, "/");
} }
cwd_lock.release (); release_read ();
out: out:
syscall_printf ("(%s) = cwdstuff::get (%p, %u, %d, %d), errno %d", syscall_printf ("(%s) = cwdstuff::get (%p, %u, %d, %d), errno %d",

View File

@ -4437,9 +4437,9 @@ gen_full_path_at (char *path_ret, int dirfd, const char *pathname,
if (dirfd == AT_FDCWD) if (dirfd == AT_FDCWD)
{ {
cwdstuff::cwd_lock.acquire (); cwdstuff::acquire_read ();
p = stpcpy (path_ret, cygheap->cwd.get_posix ()); p = stpcpy (path_ret, cygheap->cwd.get_posix ());
cwdstuff::cwd_lock.release (); cwdstuff::release_read ();
} }
else else
{ {
@ -4581,9 +4581,9 @@ fchownat (int dirfd, const char *pathname, uid_t uid, gid_t gid, int flags)
/* pathname is an empty string. Operate on dirfd. */ /* pathname is an empty string. Operate on dirfd. */
if (dirfd == AT_FDCWD) if (dirfd == AT_FDCWD)
{ {
cwdstuff::cwd_lock.acquire (); cwdstuff::acquire_read ();
strcpy (path, cygheap->cwd.get_posix ()); strcpy (path, cygheap->cwd.get_posix ());
cwdstuff::cwd_lock.release (); cwdstuff::release_read ();
} }
else else
{ {
@ -4626,9 +4626,9 @@ fstatat (int dirfd, const char *__restrict pathname, struct stat *__restrict st,
/* pathname is an empty string. Operate on dirfd. */ /* pathname is an empty string. Operate on dirfd. */
if (dirfd == AT_FDCWD) if (dirfd == AT_FDCWD)
{ {
cwdstuff::cwd_lock.acquire (); cwdstuff::acquire_read ();
strcpy (path, cygheap->cwd.get_posix ()); strcpy (path, cygheap->cwd.get_posix ());
cwdstuff::cwd_lock.release (); cwdstuff::release_read ();
} }
else else
return fstat (dirfd, st); return fstat (dirfd, st);