Aaron Patterson <aaron / tenderlovemaking.com> wrote: > On Wed, Mar 24, 2010 at 07:43:56PM +0900, NARUSE, Yui wrote: > > (2010/03/22 17:05), Eric Wong wrote: > > >This assumes st.c is only called inside GVL, and GVL == GIL which is > > >true these days in 1.9.1 and trunk. > > > > st.c is used not only from GC, but by other extensions. > > > > I don't know whether st.h is public API or not. > > But if a library uses st_table in multi thread way, > > it will break when st_table become thread unsafe. > > FWIW, Nokogiri uses st.h. st.h seems public, at least there are several extensions that use it, too (json, rcov, ruby-prof) but very few of them release GVL, so they should all be safe. Combining thread-safety good malloc performance is a lot of work, I would just defer to the malloc implementation (like tcmalloc) if thread-safety is a concern. I not sure if this patch series is suitable for ruby itself, which is why I'm putting them here first for discussion (and not Redmine). diff --git a/st.c b/st.c index 54ebee9..c9a5bba 100644 --- a/st.c +++ b/st.c @@ -7,6 +7,7 @@ #include "st.h" #else #include "ruby/ruby.h" +#include "vm_core.h" #endif #include <stdio.h> @@ -38,6 +39,22 @@ struct st_table_entry { * */ +/* + * assume USE_VALUE_CACHE means we care about thread-safety + */ +#if USE_VALUE_CACHE +/* thread-safety, defer to slower malloc() implementation */ +#define DEFINE_ALLOC_POOL(name,type,size) \ +static inline type *alloc_##name(void) \ +{ \ + return ruby_xmalloc(sizeof(type)); \ +} \ +static inline void release_##name(void *ptr) \ +{ \ + ruby_xfree(ptr); \ +} +#else +/* not thread-safe, but faster if st.h users don't release GVL */ #if __GNUC__ >= 3 #define UNLIKELY(x) (__builtin_expect((x), 0)) #else /* __GNUC__ >= 3 */ @@ -83,6 +100,7 @@ static void release_##name(void *ptr) \ tmp->as.next = name##_head ? name##_head : NULL; \ name##_head = tmp; \ } +#endif DEFINE_ALLOC_POOL(entry, struct st_table_entry, 0x2000); DEFINE_ALLOC_POOL(table, struct st_table, 0x2000); -- Eric Wong