diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-03 23:47:53 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-10-03 23:47:53 +0000 |
commit | fbb343273666bed162b3190bcfce36c24e89fc6d (patch) | |
tree | f25fb6309683d6e587600d449de54d891f8af3a3 /file.c | |
parent | 15edf2b3eefb44039f72f8b7721a143ac369ca77 (diff) | |
download | ruby-fbb343273666bed162b3190bcfce36c24e89fc6d.tar.gz |
file.c: release GVL around lstat(2)
Like stat(2), lstat(2) can be expensive on slow filesystems and
should not block other threads. There should be a minor, but
not significant slowdowns in single-threaded performance similar
to benchmarks around the more-portable stat(2):
[ruby-core:83012] [Bug #13941]
* file.c (no_gvl_lstat): new function for rb_thread_call_without_gvl
(lstat_without_gvl): new wrapper to replace lstat(2) calls
(rb_file_s_lstat): s/lstat/&_without_gvl/
(rb_file_lstat): ditto
(rb_file_symlink_p): ditto
(rb_file_s_ftype): ditto
(rb_file_expand_path_internal): ditto
(realpath_rec): ditto
[ruby-core:83075] [Feature #13963]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60110 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 33 |
1 files changed, 27 insertions, 6 deletions
@@ -1181,6 +1181,27 @@ rb_io_stat(VALUE obj) return rb_stat_new(&st); } +#ifdef HAVE_LSTAT +static void * +no_gvl_lstat(void *ptr) +{ + no_gvl_stat_data *arg = ptr; + return (void *)(VALUE)lstat(arg->file.path, arg->st); +} + +static int +lstat_without_gvl(const char *path, struct stat *st) +{ + no_gvl_stat_data data; + + data.file.path = path; + data.st = st; + + return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_lstat, &data, + RUBY_UBF_IO, NULL); +} +#endif /* HAVE_LSTAT */ + /* * call-seq: * File.lstat(file_name) -> stat @@ -1203,7 +1224,7 @@ rb_file_s_lstat(VALUE klass, VALUE fname) FilePathValue(fname); fname = rb_str_encode_ospath(fname); - if (lstat(StringValueCStr(fname), &st) == -1) { + if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) { rb_sys_fail_path(fname); } return rb_stat_new(&st); @@ -1237,7 +1258,7 @@ rb_file_lstat(VALUE obj) GetOpenFile(obj, fptr); if (NIL_P(fptr->pathv)) return Qnil; path = rb_str_encode_ospath(fptr->pathv); - if (lstat(RSTRING_PTR(path), &st) == -1) { + if (lstat_without_gvl(RSTRING_PTR(path), &st) == -1) { rb_sys_fail_path(fptr->pathv); } return rb_stat_new(&st); @@ -1449,7 +1470,7 @@ rb_file_symlink_p(VALUE obj, VALUE fname) FilePathValue(fname); fname = rb_str_encode_ospath(fname); - if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse; + if (lstat_without_gvl(StringValueCStr(fname), &st) < 0) return Qfalse; if (S_ISLNK(st.st_mode)) return Qtrue; #endif @@ -2081,7 +2102,7 @@ rb_file_s_ftype(VALUE klass, VALUE fname) FilePathValue(fname); fname = rb_str_encode_ospath(fname); - if (lstat(StringValueCStr(fname), &st) == -1) { + if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) { rb_sys_fail_path(fname); } @@ -3628,7 +3649,7 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na struct stat st; p = (char *)s; len = strlen(p); - if (lstat(buf, &st) == 0 && S_ISLNK(st.st_mode)) { + if (lstat_without_gvl(buf, &st) == 0 && S_ISLNK(st.st_mode)) { is_symlink = 1; if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) { lnk_added = 1; @@ -3896,7 +3917,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, #ifdef __native_client__ ret = stat(RSTRING_PTR(testpath), &sbuf); #else - ret = lstat(RSTRING_PTR(testpath), &sbuf); + ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf); #endif if (ret == -1) { int e = errno; |