ext/etc/etc.c in etc-1.2.0 vs ext/etc/etc.c in etc-1.3.0

- old
+ new

@@ -50,36 +50,35 @@ #ifndef _WIN32 char *getenv(); #endif char *getlogin(); -#define RUBY_ETC_VERSION "1.2.0" +#define RUBY_ETC_VERSION "1.3.0" #ifdef HAVE_RB_DEPRECATE_CONSTANT void rb_deprecate_constant(VALUE mod, const char *name); #else # define rb_deprecate_constant(mod,name) ((void)(mod),(void)(name)) #endif #include "constdefs.h" -#ifdef HAVE_RB_EXT_RACTOR_SAFE -#include "ruby/thread_native.h" +#ifdef HAVE_RUBY_ATOMIC_H +# include "ruby/atomic.h" #else -/* Implement rb_native_mutex_x using an int */ -typedef int rb_nativethread_lock_t; -static int rb_native_mutex_trylock(int *mutex) { - if (*mutex) { - return 1; - } - *mutex = 1; - return 0; +typedef int rb_atomic_t; +# define RUBY_ATOMIC_CAS(var, oldval, newval) \ + ((var) == (oldval) ? ((var) = (newval), (oldval)) : (var)) +# define RUBY_ATOMIC_EXCHANGE(var, newval) \ + atomic_exchange(&var, newval) +static inline rb_atomic_t +atomic_exchange(volatile rb_atomic_t *var, rb_atomic_t newval) +{ + rb_atomic_t oldval = *var; + *var = newval; + return oldval; } -static void rb_native_mutex_unlock(int *mutex) { - *mutex = 0; -} -#define rb_native_mutex_initialize rb_native_mutex_unlock #endif /* call-seq: * getlogin -> String * @@ -256,16 +255,18 @@ return Qnil; #endif } #ifdef HAVE_GETPWENT -static rb_nativethread_lock_t passwd_blocking; +static rb_atomic_t passwd_blocking; static VALUE passwd_ensure(VALUE _) { endpwent(); - rb_native_mutex_unlock(&passwd_blocking); + if (RUBY_ATOMIC_EXCHANGE(passwd_blocking, 0) != 1) { + rb_raise(rb_eRuntimeError, "unexpected passwd_blocking"); + } return Qnil; } static VALUE passwd_iterate(VALUE _) @@ -280,11 +281,11 @@ } static void each_passwd(void) { - if (rb_native_mutex_trylock(&passwd_blocking)) { + if (RUBY_ATOMIC_CAS(passwd_blocking, 0, 1)) { rb_raise(rb_eRuntimeError, "parallel passwd iteration"); } rb_ensure(passwd_iterate, 0, passwd_ensure, 0); } #endif @@ -498,16 +499,18 @@ return Qnil; #endif } #ifdef HAVE_GETGRENT -static rb_nativethread_lock_t group_blocking; +static rb_atomic_t group_blocking; static VALUE group_ensure(VALUE _) { endgrent(); - rb_native_mutex_unlock(&group_blocking); + if (RUBY_ATOMIC_EXCHANGE(group_blocking, 0) != 1) { + rb_raise(rb_eRuntimeError, "unexpected group_blocking"); + } return Qnil; } static VALUE @@ -523,11 +526,11 @@ } static void each_group(void) { - if (rb_native_mutex_trylock(&group_blocking)) { + if (RUBY_ATOMIC_CAS(group_blocking, 0, 1)) { rb_raise(rb_eRuntimeError, "parallel group iteration"); } rb_ensure(group_iterate, 0, group_ensure, 0); } #endif @@ -952,15 +955,17 @@ #if defined(HAVE_SCHED_GETAFFINITY) && defined(CPU_ALLOC) static int etc_nprocessors_affin(void) { - cpu_set_t *cpuset; + cpu_set_t *cpuset, cpuset_buff[1024 / sizeof(cpu_set_t)]; size_t size; int ret; int n; + CPU_ZERO_S(sizeof(cpuset_buff), cpuset_buff); + /* * XXX: * man page says CPU_ALLOC takes number of cpus. But it is not accurate * explanation. sched_getaffinity() returns EINVAL if cpuset bitmap is * smaller than kernel internal bitmap. @@ -975,29 +980,28 @@ * So, we use hardcode number for a workaround. Current linux kernel * (Linux 3.17) support 8192 cpus at maximum. Then 16384 must be enough. */ for (n=64; n <= 16384; n *= 2) { size = CPU_ALLOC_SIZE(n); - if (size >= 1024) { + if (size >= sizeof(cpuset_buff)) { cpuset = xcalloc(1, size); if (!cpuset) return -1; } else { - cpuset = alloca(size); - CPU_ZERO_S(size, cpuset); + cpuset = cpuset_buff; } ret = sched_getaffinity(0, size, cpuset); if (ret == 0) { /* On success, count number of cpus. */ ret = CPU_COUNT_S(size, cpuset); } - if (size >= 1024) { + if (size >= sizeof(cpuset_buff)) { xfree(cpuset); } - if (ret > 0) { + if (ret > 0 || errno != EINVAL) { return ret; } } return ret; @@ -1197,14 +1201,10 @@ #endif rb_define_const(rb_cStruct, "Passwd", sPasswd); /* deprecated name */ rb_deprecate_constant(rb_cStruct, "Passwd"); rb_extend_object(sPasswd, rb_mEnumerable); rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0); -#ifdef HAVE_GETPWENT - rb_native_mutex_initialize(&passwd_blocking); -#endif #ifdef HAVE_GETGRENT - rb_native_mutex_initialize(&group_blocking); sGroup = rb_struct_define_under(mEtc, "Group", "name", #ifdef HAVE_STRUCT_GROUP_GR_PASSWD "passwd", #endif "gid", "mem", NULL);