ruby-changes:48481
From: normal <ko1@a...>
Date: Wed, 1 Nov 2017 09:17:22 +0900 (JST)
Subject: [ruby-changes:48481] normal:r60595 (trunk): dir: Dir.mkdir and Dir.rmdir release GVL
normal 2017-11-01 09:17:11 +0900 (Wed, 01 Nov 2017) New Revision: 60595 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60595 Log: dir: Dir.mkdir and Dir.rmdir release GVL This avoids blocking the entire VM when operating on slow or unreliable filesystems. Instead, only the thread performing the mkdir or rmdir operation is blocked and other threads are free to proceed. * dir.c (nogvl_mkdir): new function (nogvl_rmdir): ditto (dir_s_mkdir): release GVL (dir_s_rmdir): ditto Modified files: trunk/dir.c Index: dir.c =================================================================== --- dir.c (revision 60594) +++ dir.c (revision 60595) @@ -1199,6 +1199,19 @@ dir_s_chroot(VALUE dir, VALUE path) https://github.com/ruby/ruby/blob/trunk/dir.c#L1199 #define dir_s_chroot rb_f_notimplement #endif +struct mkdir_arg { + const char *path; + mode_t mode; +}; + +static void * +nogvl_mkdir(void *ptr) +{ + struct mkdir_arg *m = ptr; + + return (void *)(VALUE)mkdir(m->path, m->mode); +} + /* * call-seq: * Dir.mkdir( string [, integer] ) -> 0 @@ -1217,23 +1230,34 @@ dir_s_chroot(VALUE dir, VALUE path) https://github.com/ruby/ruby/blob/trunk/dir.c#L1230 static VALUE dir_s_mkdir(int argc, VALUE *argv, VALUE obj) { + struct mkdir_arg m; VALUE path, vmode; - mode_t mode; + int r; if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) { - mode = NUM2MODET(vmode); + m.mode = NUM2MODET(vmode); } else { - mode = 0777; + m.mode = 0777; } path = check_dirname(path); - if (mkdir(RSTRING_PTR(path), mode) == -1) + m.path = RSTRING_PTR(path); + r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0); + if (r < 0) rb_sys_fail_path(path); return INT2FIX(0); } +static void * +nogvl_rmdir(void *ptr) +{ + const char *path = ptr; + + return (void *)(VALUE)rmdir(path); +} + /* * call-seq: * Dir.delete( string ) -> 0 @@ -1246,8 +1270,13 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/dir.c#L1270 static VALUE dir_s_rmdir(VALUE obj, VALUE dir) { + const char *p; + int r; + dir = check_dirname(dir); - if (rmdir(RSTRING_PTR(dir)) < 0) + p = RSTRING_PTR(dir); + r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, p, RUBY_UBF_IO, 0); + if (r < 0) rb_sys_fail_path(dir); return INT2FIX(0); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/