From 1483f85cbc01aae71e6102f32f4fe150114db6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Fri, 2 Dec 2011 15:14:12 +0100 Subject: [PATCH] Backend: The storage for call_outs is now a proper object. --- src/backend.cmod | 266 +++++++++++++++++++++++++---------------------- 1 file changed, 143 insertions(+), 123 deletions(-) diff --git a/src/backend.cmod b/src/backend.cmod index c6e21962cb..88a7a63a3f 100644 --- a/src/backend.cmod +++ b/src/backend.cmod @@ -36,6 +36,7 @@ #include "mapping.h" #include "svalue.h" #include "gc.h" +#include "module_support.h" /* * Things to do @@ -131,33 +132,12 @@ static int compat_box_dispatcher (struct fd_callback_box *box, int event); /* CALL OUT STUFF */ -struct call_out_s -{ - INT32 pos; - size_t fun_hval; - struct timeval tv; - struct call_out_s *next_fun; - struct call_out_s **prev_fun; - struct call_out_s *next_arr; - struct call_out_s **prev_arr; - struct object *caller; - struct array *args; -}; - -/* MUST be after any include of "block_alloc_h.h"! */ -#include "block_alloc.h" - -#undef BLOCK_ALLOC_NEXT -#define BLOCK_ALLOC_NEXT next_fun - #ifdef PIKE_DEBUG #define MESS_UP_BLOCK(X) do {\ - (X)->next_arr=(struct call_out_s *)(ptrdiff_t)-1; \ - (X)->next_fun=(struct call_out_s *)(ptrdiff_t)-1; \ - (X)->prev_arr=(struct call_out_s **)(ptrdiff_t)-1; \ - (X)->prev_fun=(struct call_out_s **)(ptrdiff_t)-1; \ - (X)->caller=(struct object *)(ptrdiff_t)-1; \ - (X)->args=(struct array *)(ptrdiff_t)-1; \ + (X)->next_arr=(struct Backend_CallOut_struct *)(ptrdiff_t)-1; \ + (X)->next_fun=(struct Backend_CallOut_struct *)(ptrdiff_t)-1; \ + (X)->prev_arr=(struct Backend_CallOut_struct **)(ptrdiff_t)-1; \ + (X)->prev_fun=(struct Backend_CallOut_struct **)(ptrdiff_t)-1; \ (X)->pos=-1; \ } while(0) #else @@ -172,17 +152,11 @@ struct call_out_s if(X->next_fun) X->next_fun->prev_fun=X->prev_fun; \ MESS_UP_BLOCK(X); \ } while(0) -BLOCK_ALLOC_FILL_PAGES(call_out_s, 2) - -#define alloc_call_out() debug_malloc_pass(alloc_call_out_s()) -#define really_free_call_out(X) really_free_call_out_s(debug_malloc_pass(X)) - -typedef struct call_out_s call_out; struct hash_ent { - call_out *arr; - call_out *fun; + struct Backend_CallOut_struct *arr; + struct Backend_CallOut_struct *fun; }; @@ -345,9 +319,9 @@ PIKECLASS Backend /* * CALL OUT variables */ - CVAR int num_pending_calls; /* no of busy pointers in heap */ - CVAR call_out **call_heap; /* pointer to heap */ - CVAR int call_heap_size; /* no of pointers in heap */ + CVAR int num_pending_calls; /* no of busy pointers in heap */ + CVAR struct Backend_CallOut_struct **call_heap; /* pointer to heap */ + CVAR int call_heap_size; /* no of pointers in heap */ CVAR unsigned int hash_size; CVAR unsigned int hash_order; @@ -449,6 +423,23 @@ PIKECLASS Backend * Call outs. */ + PIKECLASS CallOut + program_flags PROGRAM_USES_PARENT; + flags ID_PROTECTED|ID_PRIVATE|ID_USED; + { + CVAR INT32 pos; + CVAR size_t fun_hval; + CVAR struct timeval tv; + CVAR struct Backend_CallOut_struct *next_fun; + CVAR struct Backend_CallOut_struct **prev_fun; + CVAR struct Backend_CallOut_struct *next_arr; + CVAR struct Backend_CallOut_struct **prev_arr; + PIKEVAR array args + flags ID_STATIC; + CVAR struct object *this; + + DECLARE_STORAGE; + #undef CAR #undef CDR @@ -456,10 +447,10 @@ PIKECLASS Backend #define CDR(X) (((X)<<1)+2) #define PARENT(X) (((X)-1)>>1) #define CALL_(X) (me->call_heap[(X)]) -#define CALL(X) ((struct call_out_s *)debug_malloc_pass(CALL_(X))) +#define CALL(X) ((struct Backend_CallOut_struct *)debug_malloc_pass(CALL_(X))) #define MOVECALL(X,Y) do { INT32 p_=(X); (CALL_(p_)=CALL(Y))->pos=p_; }while(0) #define CMP(X,Y) my_timercmp(& CALL(X)->tv, <, & CALL(Y)->tv) -#define SWAP(X,Y) do{ call_out *_tmp=CALL(X); (CALL_(X)=CALL(Y))->pos=(X); (CALL_(Y)=_tmp)->pos=(Y); } while(0) +#define SWAP(X,Y) do{ struct Backend_CallOut_struct *_tmp=CALL(X); (CALL_(X)=CALL(Y))->pos=(X); (CALL_(Y)=_tmp)->pos=(Y); } while(0) #ifdef PIKE_DEBUG #define PROTECT_CALL_OUTS() \ @@ -531,7 +522,7 @@ PIKECLASS Backend for(e=0;e<(int)me->hash_size;e++) { - call_out *c,**prev; + struct Backend_CallOut_struct *c,**prev; for(prev=& me->call_hash[e].arr;(c=*prev);prev=& c->next_arr) { if(c->prev_arr != prev) @@ -612,31 +603,64 @@ PIKECLASS Backend if(!adjust_up(me,pos)) adjust_down(me,pos); } - /* start a new call out, return 1 for success */ - static struct array *new_call_out(struct Backend_struct *me, - int num_arg) + INIT + { + THIS->pos = -1; + THIS->this = Pike_fp->current_object; + } + + EXIT { - call_out *new; - struct array *args; + struct Backend_CallOut_struct *this = THIS; + + if (this->pos >= 0) { + /* Still active in the heap. DO_PIKE_CLEANUP? */ + struct Backend_struct *me = parent_storage(1); + int e = this->pos; + + me->num_pending_calls--; + if (e != me->num_pending_calls) { + MOVECALL(e, me->num_pending_calls); + adjust(me, e); + } + CALL_(me->num_pending_calls) = NULL; + this->pos = -1; + free_object(this->this); + this->this = NULL; + } + EXIT_BLOCK(this); + } + + /* Start a new call out */ + PIKEFUN void create(int|float seconds, mixed fun, mixed ... extra_args) + flags ID_PROTECTED; + { + struct array *callable; size_t fun_hval; size_t hval; - + struct Backend_struct *me = parent_storage(1); + struct Backend_CallOut_struct *new = THIS; + + push_array(callable = aggregate_array(args - 1)); + args = 2; + /* NOTE: hash_svalue() can run Pike code! */ - fun_hval = hash_svalue(Pike_sp + 1 - num_arg); + fun_hval = hash_svalue(ITEM(callable)); PROTECT_CALL_OUTS(); if(me->num_pending_calls == me->call_heap_size) { /* here we need to allocate space for more pointers */ - call_out **new_heap; + struct Backend_CallOut_struct **new_heap; if(!me->call_heap) { me->call_heap_size = 128; me->call_heap = - (call_out **)xalloc(sizeof(call_out *)*me->call_heap_size); - if(!me->call_heap) return 0; - MEMSET(me->call_heap, 0, sizeof(call_out *)*me->call_heap_size); + (struct Backend_CallOut_struct **)xalloc(sizeof(struct Backend_CallOut_struct *) * + me->call_heap_size); + MEMSET(me->call_heap, 0, sizeof(struct Backend_CallOut_struct *) * + me->call_heap_size); me->num_pending_calls = 0; me->hash_size = hashprimes[me->hash_order]; @@ -647,13 +671,13 @@ PIKECLASS Backend struct hash_ent *new_hash; int e; - new_heap = (call_out **) + new_heap = (struct Backend_CallOut_struct **) realloc((char *)me->call_heap, - sizeof(call_out *)*me->call_heap_size*2); + sizeof(struct Backend_CallOut_struct *)*me->call_heap_size*2); if(!new_heap) Pike_error("Not enough memory for another call_out\n"); MEMSET(new_heap + me->call_heap_size, 0, - sizeof(call_out *)*me->call_heap_size); + sizeof(struct Backend_CallOut_struct *)*me->call_heap_size); me->call_heap_size *= 2; me->call_heap = new_heap; @@ -668,7 +692,7 @@ PIKECLASS Backend /* Re-hash */ for(e=0;e<me->num_pending_calls;e++) { - call_out *c = CALL(e); + struct Backend_CallOut_struct *c = CALL(e); hval = PTR_TO_INT(c->args); #define LINK(X,c) \ @@ -687,17 +711,15 @@ PIKECLASS Backend } } - /* time to allocate a new call_out struct */ - push_array(args = aggregate_array(num_arg-1)); - #ifdef PIKE_DEBUG if (CALL(me->num_pending_calls)) { Pike_fatal("Lost call out in heap.\n"); } #endif /* PIKE_DEBUG */ - CALL_(me->num_pending_calls) = new = alloc_call_out(); - new->pos = me->num_pending_calls; + CALL_(me->num_pending_calls) = new; + new->pos = me->num_pending_calls++; + add_ref(Pike_fp->current_object); { hval = PTR_TO_INT(args); @@ -706,16 +728,16 @@ PIKECLASS Backend LINK(fun,new); } - switch(TYPEOF(Pike_sp[-2])) + switch(TYPEOF(*seconds)) { case T_INT: - new->tv.tv_sec = Pike_sp[-2].u.integer; + new->tv.tv_sec = seconds->u.integer; new->tv.tv_usec = 0; break; case T_FLOAT: { - FLOAT_TYPE tmp = Pike_sp[-2].u.float_number; + FLOAT_TYPE tmp = seconds->u.float_number; new->tv.tv_sec = DO_NOT_WARN((long)floor(tmp)); new->tv.tv_usec = DO_NOT_WARN((long)(1000000.0 * (tmp - floor(tmp)))); break; @@ -747,19 +769,10 @@ PIKECLASS Backend tmp.tv_sec, tmp.tv_usec)); } - if(Pike_fp && Pike_fp->current_object) - { - add_ref(new->caller = Pike_fp->current_object); - } else { - new->caller = 0; - } - - new->args = args; + new->args = callable; Pike_sp -= 2; dmalloc_touch_svalue(Pike_sp); - - me->num_pending_calls++; adjust_up(me, me->num_pending_calls-1); backend_verify_call_outs(me); @@ -768,8 +781,11 @@ PIKECLASS Backend #endif UNPROTECT_CALL_OUTS(); - return args; } + } + +#undef THIS +#define THIS THIS_BACKEND static void backend_count_memory_in_call_outs(struct Backend_struct *me) { @@ -777,8 +793,8 @@ PIKECLASS Backend push_int(me->num_pending_calls); push_text("call_out_bytes"); - push_int64(me->call_heap_size * sizeof(call_out **)+ - me->num_pending_calls * sizeof(call_out)); + push_int64(me->call_heap_size * sizeof(struct Backend_CallOut_struct **)+ + me->num_pending_calls * sizeof(struct Backend_CallOut_struct)); } @@ -820,8 +836,6 @@ PIKECLASS Backend for(e=0;e<me->num_pending_calls;e++) { gc_mark(CALL(e)->args,0,"call out args"); - if(CALL(e)->caller) - gc_mark(CALL(e)->caller,0,"call out caller"); } } #endif @@ -848,7 +862,9 @@ PIKECLASS Backend PIKEFUN array call_out(mixed f, int|float t, mixed ... rest) { struct svalue tmp; - struct array *v; + struct object *co; + struct Backend_CallOut_struct *c; + if(args<2) SIMPLE_TOO_FEW_ARGS_ERROR("call_out", 2); @@ -859,9 +875,20 @@ PIKECLASS Backend tmp = Pike_sp[-args]; Pike_sp[-args] = Pike_sp[1-args]; Pike_sp[1-args] = tmp; - - v = new_call_out(THIS, args); - ref_push_array(v); + + apply_current(Backend_CallOut_program_fun_num, args); + args = 1; + + get_all_args("low_call_out", args, "%o", &co); + + c = (struct Backend_CallOut_struct *) + get_storage(co, Backend_CallOut_program); + + if (!c) Pike_error("low_call_out(): Unexpected object from CallOut.\n"); + + ref_push_array(c->args); + + stack_pop_n_elems_keep_top(args); } /* Assumes current_time is correct on entry. */ @@ -881,7 +908,7 @@ PIKECLASS Backend { struct timeval now; /* unlink call out */ - call_out c,*cc; + struct Backend_CallOut_struct *cc; PROTECT_CALL_OUTS(); cc=CALL(0); @@ -892,13 +919,13 @@ PIKECLASS Backend } CALL_(me->num_pending_calls) = NULL; UNPROTECT_CALL_OUTS(); - c=*cc; - really_free_call_out(cc); - - if(c.caller) free_object(c.caller); - - args=c.args->size; - push_array_items(c.args); + cc->pos = -1; + + args = cc->args->size; + push_array_items(cc->args); + cc->args = NULL; + free_object(cc->this); + check_destructed(Pike_sp - args); if(TYPEOF(Pike_sp[-args]) != T_INT) { @@ -952,7 +979,7 @@ PIKECLASS Backend struct svalue *fun) { size_t hval, fun_hval; - call_out *c; + struct Backend_CallOut_struct *c; struct svalue *save_sp; if(!me->num_pending_calls) return -1; @@ -1103,18 +1130,17 @@ PIKECLASS Backend backend_verify_call_outs(me); if(e!=-1) { + struct Backend_CallOut_struct *c = CALL(e); struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); IF_CO (fprintf (stderr, "BACKEND[%d]: Removing call out at %ld.%ld " "(current_time is %ld.%ld)\n", me->id, - CALL(e)->tv.tv_sec, CALL(e)->tv.tv_usec, + c->tv.tv_sec, c->tv.tv_usec, now.tv_sec, now.tv_usec)); pop_n_elems(args); - push_int(CALL(e)->tv.tv_sec - now.tv_sec); - free_array(CALL(e)->args); - if(CALL(e)->caller) - free_object(CALL(e)->caller); - really_free_call_out(CALL(e)); + push_int(c->tv.tv_sec - now.tv_sec); + me->num_pending_calls--; if(e!=me->num_pending_calls) { @@ -1122,6 +1148,9 @@ PIKECLASS Backend adjust(me,e); } CALL_(me->num_pending_calls) = NULL; + c->pos = -1; + + free_object(c->this); }else{ pop_n_elems(args); /* NB: This is a very exotic value! */ @@ -1153,15 +1182,14 @@ PIKECLASS Backend struct array *v; v=allocate_array_no_init(CALL(e)->args->size+2, 0); ITEM(v)[0].u.integer=CALL(e)->tv.tv_sec - now.tv_sec; - - if(CALL(e)->caller) - { - SET_SVAL(ITEM(v)[1], T_OBJECT, 0, object, CALL(e)->caller); - add_ref(CALL(e)->caller); - v->type_field = BIT_INT|BIT_OBJECT; - }else{ - v->type_field = BIT_INT; - } + + /* FIXME: ITEM(v)[1] used to be the current object + * from when the call_out was created, but + * that is always the backend since the + * backend.cmod rewrite. + * Now we just leave it zero. + */ + v->type_field = BIT_INT; v->type_field |= assign_svalues_no_free(ITEM(v)+2, @@ -1186,8 +1214,8 @@ PIKECLASS Backend *! @array *! @elem int time_left *! Time remaining in seconds until the call_out is to be performed. - *! @elem object caller - *! The object that scheduled the call_out. + *! @elem int(0..0) zero + *! Used to be the object that scheduled the call_out. *! @elem function fun *! Function to be called. *! @elem mixed ... args @@ -1757,12 +1785,9 @@ PIKECLASS Backend int e; for (e = 0; e < me->num_pending_calls; e++) { - if (CALL(e)->caller) - debug_gc_check (CALL(e)->caller, - " as caller for call out in backend object"); - if (CALL(e)->args) - debug_gc_check (CALL(e)->args, - " as args for call out in backend object"); + if (CALL(e)->this) + debug_gc_check (CALL(e)->this, + " as call out in backend object"); } {FOR_EACH_ACTIVE_FD_BOX (me, box) { @@ -1786,10 +1811,8 @@ PIKECLASS Backend int e; for (e = 0; e < me->num_pending_calls; e++) { - if (CALL(e)->caller) - gc_recurse_object (CALL(e)->caller); - if (CALL(e)->args) - gc_recurse_array (CALL(e)->args); + if (CALL(e)->this) + gc_recurse_short_svalue ((union anything *) &CALL(e)->this, T_OBJECT); } {FOR_EACH_ACTIVE_FD_BOX (me, box) { @@ -2199,9 +2222,9 @@ PIKECLASS Backend backend_verify_call_outs(me); for(e=0;e<me->num_pending_calls;e++) { - free_array(CALL(e)->args); - if(CALL(e)->caller) free_object(CALL(e)->caller); - really_free_call_out(CALL(e)); + CALL(e)->pos = -1; + if (CALL(e)->this) + free_object(CALL(e)->this); } me->num_pending_calls=0; if(me->call_heap) free((char*)me->call_heap); @@ -5017,8 +5040,6 @@ static struct callback *mem_callback; void init_backend(void) { - IF_CO(fprintf(stderr, "BACKEND: Init call_out...\n")); - init_call_out_s_blocks(); IF_PD(fprintf(stderr, "BACKEND: Init compat callback boxes...\n")); init_compat_cb_box_blocks(); IF_PD(fprintf(stderr, "BACKEND: INIT...\n")); @@ -5076,7 +5097,6 @@ static void backend_cleanup() num_pdb_backends = 0; } #endif /* OPEN_POLL_DEVICE */ - free_all_call_out_s_blocks(); free_all_compat_cb_box_blocks(); if(fd_map) { -- GitLab