ruby-changes:47996
From: normal <ko1@a...>
Date: Wed, 4 Oct 2017 08:47:56 +0900 (JST)
Subject: [ruby-changes:47996] normal:r60110 (trunk): file.c: release GVL around lstat(2)
normal 2017-10-04 08:47:53 +0900 (Wed, 04 Oct 2017) New Revision: 60110 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60110 Log: 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] Modified files: trunk/file.c Index: file.c =================================================================== --- file.c (revision 60109) +++ file.c (revision 60110) @@ -1181,6 +1181,27 @@ rb_io_stat(VALUE obj) https://github.com/ruby/ruby/blob/trunk/file.c#L1181 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 https://github.com/ruby/ruby/blob/trunk/file.c#L1224 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) https://github.com/ruby/ruby/blob/trunk/file.c#L1258 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 https://github.com/ruby/ruby/blob/trunk/file.c#L1470 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 https://github.com/ruby/ruby/blob/trunk/file.c#L2102 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 https://github.com/ruby/ruby/blob/trunk/file.c#L3649 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 *re https://github.com/ruby/ruby/blob/trunk/file.c#L3917 #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; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/