diff options
author | Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com> | 2017-03-01 10:19:37 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2019-02-03 12:07:35 +0100 |
commit | 99fcc209dbb83c683a8e2c17e77bf427b70920c8 (patch) | |
tree | a902bff8cc7e05a34a56b82af79ed06814fa4994 | |
parent | 98899c68a23fdc8f1e8f657272d870be4bbaea6e (diff) | |
download | newlib-99fcc209dbb83c683a8e2c17e77bf427b70920c8.zip newlib-99fcc209dbb83c683a8e2c17e77bf427b70920c8.tar.gz newlib-99fcc209dbb83c683a8e2c17e77bf427b70920c8.tar.bz2 |
forkables: simplify disabling via shm
* Rename cygwin_shared->prefer_forkable_hardlinks to
forkable_hardlink_support, with values
0 for Unknown, 1 for Supported, -1 for Unsupported.
Upon first dll loaded ever, dll_list::forkable_ntnamesize checks the
/var/run/cygfork directory to both exist and reside on NTFS, setting
cygwin_shared->forkable_hardlink_support accordingly.
* Replace enum forkables_needs by bool forkables_created: Set
to True by request_forkables after creating forkable hardlinks.
-rw-r--r-- | winsup/cygwin/dll_init.h | 21 | ||||
-rw-r--r-- | winsup/cygwin/forkable.cc | 185 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/shared.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/shared_info.h | 4 |
5 files changed, 65 insertions, 148 deletions
diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h index 45f71cb..5c4cc0b 100644 --- a/winsup/cygwin/dll_init.h +++ b/winsup/cygwin/dll_init.h @@ -87,17 +87,9 @@ struct dll class dll_list { /* forkables */ - enum - { - forkables_unknown, - forkables_impossible, - forkables_disabled, - forkables_needless, - forkables_needed, - forkables_created, - } - forkables_needs; + bool forkables_supported (); DWORD forkables_dirx_size; + bool forkables_created; PWCHAR forkables_dirx_ntname; PWCHAR forkables_mutex_name; HANDLE forkables_mutex; @@ -160,10 +152,11 @@ public: void cleanup_forkables (); bool setup_forkables (bool with_forkables) { - if (forkables_needs == forkables_impossible) - return true; /* short cut to not retry fork */ - /* Once used, always use forkables in current process chain. */ - if (forkables_needs != forkables_unknown) + if (!forkables_supported ()) + return true; /* no need to retry fork */ + if (forkables_created) + /* Once created, use forkables in current + process chain on first fork try already. */ with_forkables = true; if (with_forkables) request_forkables (); diff --git a/winsup/cygwin/forkable.cc b/winsup/cygwin/forkable.cc index c569b0f..05b2285 100644 --- a/winsup/cygwin/forkable.cc +++ b/winsup/cygwin/forkable.cc @@ -501,17 +501,56 @@ dll::create_forkable () return false; } +bool +dll_list::forkables_supported () +{ + return cygwin_shared->forkable_hardlink_support >= 0; +} + /* return the number of characters necessary to store one forkable name */ size_t dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modname) { /* per process, this is the first forkables-method ever called */ - if (forkables_needs == forkables_unknown && - !cygwin_shared->prefer_forkable_hardlinks) - forkables_needs = forkables_impossible; /* short cut */ + if (cygwin_shared->forkable_hardlink_support == 0) /* Unknown */ + { + /* check existence of forkables dir */ + PWCHAR pbuf = nt_max_path_buf (); + for (namepart const *part = forkable_nameparts; part->text; ++part) + { + if (part->textfunc) + pbuf += part->textfunc (pbuf, -1); + else + pbuf += __small_swprintf (pbuf, L"%W", part->text); + if (part->mutex_from_dir) + break; /* up to first mutex-naming dir */ + } + pbuf = nt_max_path_buf (); - if (forkables_needs == forkables_impossible) - return 0; + UNICODE_STRING fn; + RtlInitUnicodeString (&fn, pbuf); + + HANDLE dh = INVALID_HANDLE_VALUE; + fs_info fsi; + if (fsi.update (&fn, NULL) && +/* FIXME: !fsi.is_readonly () && */ + fsi.is_ntfs ()) + dh = ntopenfile (pbuf, NULL, FILE_DIRECTORY_FILE); + if (dh != INVALID_HANDLE_VALUE) + { + cygwin_shared->forkable_hardlink_support = 1; /* Yes */ + NtClose (dh); + debug_printf ("enabled"); + } + else + { + cygwin_shared->forkable_hardlink_support = -1; /* No */ + debug_printf ("disabled, missing or not on NTFS %W", fn.Buffer); + } + } + + if (!forkables_supported ()) + return 0; if (!forkables_dirx_size) { @@ -560,9 +599,6 @@ dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modnam void dll_list::prepare_forkables_nomination () { - if (!forkables_dirx_ntname) - return; - dll *d = &dlls.start; while ((d = d->next)) stat_real_file_once (d); /* uses nt_max_path_buf () */ @@ -627,106 +663,19 @@ dll_list::prepare_forkables_nomination () void dll_list::update_forkables_needs () { - dll *d; - - if (forkables_needs == forkables_unknown) - { - /* check if filesystem of forkables dir is NTFS */ - PWCHAR pbuf = nt_max_path_buf (); - for (namepart const *part = forkable_nameparts; part->text; ++part) - { - if (part->mutex_from_dir) - break; /* leading non-mutex-naming dirs, must exist anyway */ - if (part->textfunc) - pbuf += part->textfunc (pbuf, -1); - else - pbuf += __small_swprintf (pbuf, L"%W", part->text); - } - - UNICODE_STRING fn; - RtlInitUnicodeString (&fn, nt_max_path_buf ()); - - fs_info fsi; - if (fsi.update (&fn, NULL) && -/* FIXME: !fsi.is_readonly () && */ - fsi.is_ntfs ()) - forkables_needs = forkables_disabled; /* check directory itself */ - else - { - debug_printf ("impossible, not on NTFS %W", fn.Buffer); - forkables_needs = forkables_impossible; - cygwin_shared->prefer_forkable_hardlinks = 0; - } - } - - if (forkables_needs == forkables_impossible) - return; /* we have not created any hardlink, nothing to clean up */ - - if (forkables_needs == forkables_disabled || - forkables_needs == forkables_needless || - forkables_needs == forkables_created) - { - /* (re-)check existence of forkables dir */ - PWCHAR pbuf = nt_max_path_buf (); - for (namepart const *part = forkable_nameparts; part->text; ++part) - { - if (part->textfunc) - pbuf += part->textfunc (pbuf, -1); - else - pbuf += __small_swprintf (pbuf, L"%W", part->text); - if (part->mutex_from_dir) - break; /* up to first mutex-naming dir */ - } - pbuf = nt_max_path_buf (); - - HANDLE dh = ntopenfile (pbuf, NULL, FILE_DIRECTORY_FILE); - if (dh != INVALID_HANDLE_VALUE) - { - NtClose (dh); - if (forkables_needs == forkables_disabled) - forkables_needs = forkables_needless; - } - else if (forkables_needs != forkables_disabled) - { - debug_printf ("disabled, disappearing %W", pbuf); - close_mutex (); - denominate_forkables (); - forkables_needs = forkables_disabled; - } - else - debug_printf ("disabled, missing %W", pbuf); - } - - if (forkables_needs == forkables_disabled) - return; - - if (forkables_needs == forkables_created) + if (forkables_created) { /* already have created hardlinks in this process, ... */ - forkables_needs = forkables_needless; - d = &start; + dll *d = &start; while ((d = d->next) != NULL) if (d->forkable_ntname && !*d->forkable_ntname) { /* ... but another dll was loaded since last fork */ debug_printf ("needed, since last fork loaded %W", d->ntname); - forkables_needs = forkables_needed; + forkables_created = false; break; } } - - if (forkables_needs > forkables_needless) - return; /* no need to check anything else */ - - if (forkables_needs != forkables_needless) - { - /* paranoia */ - system_printf ("WARNING: invalid forkables_needs value %d", - forkables_needs); - return; - } - - forkables_needs = forkables_needed; } /* Create the nominated forkable hardlinks and directories as necessary, @@ -958,7 +907,7 @@ dll_list::close_mutex () void dll_list::cleanup_forkables () { - if (!forkables_dirx_ntname) + if (!forkables_supported ()) return; bool locked = close_mutex (); @@ -1034,58 +983,32 @@ dll_list::set_forkables_inheritance (bool inherit) void dll_list::request_forkables () { - if (!forkables_dirx_ntname) + if (!forkables_supported ()) return; - /* Even on forkables_impossible, keep the number of open handles - stable across the fork, and close them when releasing only. */ prepare_forkables_nomination (); update_forkables_needs (); set_forkables_inheritance (true); - if (forkables_needs == forkables_disabled) - { - /* we do not support (re-)enabling on the fly */ - forkables_needs = forkables_impossible; - cygwin_shared->prefer_forkable_hardlinks = 0; - } - - if (forkables_needs <= forkables_needless) - return; + if (forkables_created) + return; /* nothing new to create */ dll *d = &start; while ((d = d->next)) d->nominate_forkable (forkables_dirx_ntname); - bool updated = update_forkables (); - - if (!updated) - forkables_needs = forkables_needless; - else - forkables_needs = forkables_created; + if (update_forkables ()) + forkables_created = true; } void dll_list::release_forkables () { - if (!forkables_dirx_ntname) + if (!forkables_supported ()) return; set_forkables_inheritance (false); - - if (forkables_needs == forkables_impossible) - { - cleanup_forkables (); - - dll *d = &start; - while ((d = d->next)) - d->forkable_ntname = NULL; - - cfree (forkables_dirx_ntname); - forkables_dirx_ntname = NULL; - forkables_mutex_name = NULL; - } } diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index f7ed351..8926d49 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -518,7 +518,7 @@ details. */ regions. It is incremented when incompatible changes are made to the shared memory region *or* to any named shared mutexes, semaphores, etc. */ -#define CYGWIN_VERSION_SHARED_DATA 6 +#define CYGWIN_VERSION_SHARED_DATA 5 /* An identifier used in the names used to create shared objects. The full names include the CYGWIN_VERSION_SHARED_DATA version as well as this diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index e87f2f9..c939e0d 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -334,6 +334,7 @@ shared_info::initialize () NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low */ InterlockedExchange (&pid_src, /* random value to make start pid */ luid.LowPart % 2048);/* less predictably */ + forkable_hardlink_support = 0; /* 0: Unknown, 1: Yes, -1: No */ /* 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. */ diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index 8f0954f..307306c 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -33,7 +33,7 @@ public: /* Data accessible to all tasks */ -#define CURR_SHARED_MAGIC 0x3a6025edU +#define CURR_SHARED_MAGIC 0xc590e67eU #define USER_VERSION 1 @@ -51,7 +51,7 @@ class shared_info mtinfo mt; loadavginfo loadavg; LONG pid_src; - char prefer_forkable_hardlinks; /* single byte access always is atomic */ + char forkable_hardlink_support; /* single byte access always is atomic */ void initialize (); void init_obcaseinsensitive (); |