ruby-changes:31155
From: ko1 <ko1@a...>
Date: Thu, 10 Oct 2013 13:56:38 +0900 (JST)
Subject: [ruby-changes:31155] ko1:r43234 (trunk): * vm_trace.c (postponed_job): use preallocated buffer.
ko1 2013-10-10 13:56:32 +0900 (Thu, 10 Oct 2013) New Revision: 43234 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43234 Log: * vm_trace.c (postponed_job): use preallocated buffer. Pre-allocate MAX_POSTPONED_JOB (1024) sized buffer and use it. If rb_postponed_job_register() cause overflow, simply it fails and returns 0. And maybe rb_postponed_job_register() is signal safe. * vm_core.h: change data structure. Modified files: trunk/ChangeLog trunk/vm_core.h trunk/vm_trace.c Index: ChangeLog =================================================================== --- ChangeLog (revision 43233) +++ ChangeLog (revision 43234) @@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Oct 10 13:52:37 2013 Koichi Sasada <ko1@a...> + + * vm_trace.c (postponed_job): use preallocated buffer. + Pre-allocate MAX_POSTPONED_JOB (1024) sized buffer + and use it. + If rb_postponed_job_register() cause overflow, simply it + fails and returns 0. + And maybe rb_postponed_job_register() is signal safe. + + * vm_core.h: change data structure. + Thu Oct 10 11:11:33 2013 Nobuyoshi Nakada <nobu@r...> * vm.c (Init_VM): hide also the singleton class of frozen-core, not Index: vm_core.h =================================================================== --- vm_core.h (revision 43233) +++ vm_core.h (revision 43234) @@ -389,7 +389,9 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L389 /* hook */ rb_hook_list_t event_hooks; - struct rb_postponed_job_struct *postponed_job; + /* postponed_job */ + struct rb_postponed_job_struct *postponed_job_buffer; + int postponed_job_index; int src_encoding_index; Index: vm_trace.c =================================================================== --- vm_trace.c (revision 43233) +++ vm_trace.c (revision 43234) @@ -1280,6 +1280,8 @@ tracepoint_inspect(VALUE self) https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1280 } } +static void Init_postponed_job(void); + /* This function is called from inits.c */ void Init_vm_trace(void) @@ -1370,33 +1372,54 @@ Init_vm_trace(void) https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1372 rb_define_method(rb_cTracePoint, "self", tracepoint_attr_self, 0); rb_define_method(rb_cTracePoint, "return_value", tracepoint_attr_return_value, 0); rb_define_method(rb_cTracePoint, "raised_exception", tracepoint_attr_raised_exception, 0); + + /* initialized for postponed job */ + + Init_postponed_job(); } typedef struct rb_postponed_job_struct { - unsigned long flags; /* reserve */ - rb_thread_t *th; /* created thread, reserve */ + unsigned long flags; /* reserved */ + struct rb_thread_struct *th; /* created thread, reserved */ rb_postponed_job_func_t func; void *data; - struct rb_postponed_job_struct *next; } rb_postponed_job_t; +#define MAX_POSTPONED_JOB 1024 + +static void +Init_postponed_job(void) +{ + rb_vm_t *vm = GET_VM(); + vm->postponed_job_buffer = ALLOC_N(rb_postponed_job_t, MAX_POSTPONED_JOB); + vm->postponed_job_index = 0; +} + +/* return 0 if job buffer is full */ int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data) { rb_thread_t *th = GET_THREAD(); rb_vm_t *vm = th->vm; - rb_postponed_job_t *pjob = (rb_postponed_job_t *)ruby_xmalloc(sizeof(rb_postponed_job_t)); - if (pjob == NULL) return 0; /* failed */ + rb_postponed_job_t *pjob; + + while (1) { + int index = vm->postponed_job_index; + if (index >= MAX_POSTPONED_JOB) return 0; /* failed */ + + if (ATOMIC_CAS(vm->postponed_job_index, index, index+1) == index) { + pjob = &vm->postponed_job_buffer[index]; + break; + } + } pjob->flags = flags; pjob->th = th; pjob->func = func; pjob->data = data; - pjob->next = vm->postponed_job; - vm->postponed_job = pjob; - RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(th); + return 1; } @@ -1404,13 +1427,15 @@ int https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1427 rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data) { rb_vm_t *vm = GET_VM(); - rb_postponed_job_t *pjob = vm->postponed_job; + rb_postponed_job_t *pjob; + int i; - while (pjob) { + /* TODO: this check is not signal safe, but I believe this is not critical prbolem */ + for (i=0; i<vm->postponed_job_index; i++) { + pjob = &vm->postponed_job_buffer[i]; if (pjob->func == func) { return 2; } - pjob = pjob->next; } return rb_postponed_job_register(flags, func, data); @@ -1419,13 +1444,19 @@ rb_postponed_job_register_one(unsigned i https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1444 void rb_postponed_job_flush(rb_vm_t *vm) { - rb_postponed_job_t *pjob = vm->postponed_job, *next_pjob; - vm->postponed_job = 0; + rb_postponed_job_t *pjob; - while (pjob) { - next_pjob = pjob->next; - pjob->func(pjob->data); - ruby_xfree(pjob); - pjob = next_pjob; + while (1) { + int index = vm->postponed_job_index; + + if (index <= 0) { + return; /* finished */ + } + + if (ATOMIC_CAS(vm->postponed_job_index, index, index-1) == index) { + pjob = &vm->postponed_job_buffer[index-1]; + /* do postponed job */ + pjob->func(pjob->data); + } } } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/