[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]