ruby-changes:48808
From: normal <ko1@a...>
Date: Tue, 28 Nov 2017 12:28:40 +0900 (JST)
Subject: [ruby-changes:48808] normal:r60925 (trunk): file: release GVL for access(2) syscalls
normal 2017-11-28 12:28:35 +0900 (Tue, 28 Nov 2017) New Revision: 60925 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60925 Log: file: release GVL for access(2) syscalls Like stat(2), the access(2) syscall may take an indeterminate amount of time on slow/remote filesystems. This lets the following methods release the GVL to avoid choking the entire VM while one thread is stuck on a slow or non-responsive filesystem: - File.readable? - File.readable_real? - File.writable? - File.writable_real? - File.executable? - File.executable_real? * file.c (nogvl_eaccess): new function (nogvl_access): ditto (rb_access): new wrapper function (rb_eaccess): release GVL (rb_file_readable_real_p): use rb_access (rb_file_writable_real_p): ditto (rb_file_executable_real_p): ditto Modified files: trunk/file.c Index: file.c =================================================================== --- file.c (revision 60924) +++ file.c (revision 60925) @@ -1414,12 +1414,53 @@ eaccess(const char *path, int mode) https://github.com/ruby/ruby/blob/trunk/file.c#L1414 } #endif +struct access_arg { + const char *path; + int mode; +}; + +static void * +nogvl_eaccess(void *ptr) +{ + struct access_arg *aa = ptr; + + return (void *)(VALUE)eaccess(aa->path, aa->mode); +} + static int rb_eaccess(VALUE fname, int mode) { + struct access_arg aa; + FilePathValue(fname); fname = rb_str_encode_ospath(fname); - return eaccess(StringValueCStr(fname), mode); + aa.path = StringValueCStr(fname); + aa.mode = mode; + + return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa, + RUBY_UBF_IO, 0); +} + +static void * +nogvl_access(void *ptr) +{ + struct access_arg *aa = ptr; + + return (void *)(VALUE)access(aa->path, aa->mode); +} + +static int +rb_access(VALUE fname, int mode) +{ + struct access_arg aa; + + FilePathValue(fname); + fname = rb_str_encode_ospath(fname); + aa.path = StringValueCStr(fname); + aa.mode = mode; + + return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa, + RUBY_UBF_IO, 0); } /* @@ -1680,9 +1721,7 @@ rb_file_readable_p(VALUE obj, VALUE fnam https://github.com/ruby/ruby/blob/trunk/file.c#L1721 static VALUE rb_file_readable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse; + if (rb_access(fname, R_OK) < 0) return Qfalse; return Qtrue; } @@ -1750,9 +1789,7 @@ rb_file_writable_p(VALUE obj, VALUE fnam https://github.com/ruby/ruby/blob/trunk/file.c#L1789 static VALUE rb_file_writable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse; + if (rb_access(fname, W_OK) < 0) return Qfalse; return Qtrue; } @@ -1812,9 +1849,7 @@ rb_file_executable_p(VALUE obj, VALUE fn https://github.com/ruby/ruby/blob/trunk/file.c#L1849 static VALUE rb_file_executable_real_p(VALUE obj, VALUE fname) { - FilePathValue(fname); - fname = rb_str_encode_ospath(fname); - if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse; + if (rb_access(fname, X_OK) < 0) return Qfalse; return Qtrue; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/