pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:4573:    * If there's anything left in the complete list then it's internal    * cyclic stuff. In that case we put those things into the work list,    * move the indirectly incomplete list back to complete and repeat    * MC_PASS_LOOKAHEAD. Otherwise we're done.    */      /* #define MEMORY_COUNT_DEBUG */      #define MC_WQ_START_SIZE 1024    + static IMUTEX_T mc_mutex; +    PMOD_EXPORT int mc_pass;   PMOD_EXPORT size_t mc_counted_bytes;      static int mc_lookahead, mc_block_pike_cycle_depth;   static TYPE_FIELD mc_block_lookahead;   static TYPE_FIELD mc_block_lookahead_default = BIT_PROGRAM|BIT_STRING|BIT_TYPE;   /* Strings are blocked because they don't contain refs. Types are    * blocked because they are acyclic and don't contain refs to anything    * but strings and other types. */   
pike.git/src/gc.c:4684:   #define BLOCK_ALLOC_NEXT hash_next   #undef PTR_HASH_ALLOC_DATA   #define PTR_HASH_ALLOC_DATA thing   #undef INIT_BLOCK   #define INIT_BLOCK(f)   #undef EXIT_BLOCK   #define EXIT_BLOCK(f)      PTR_HASH_ALLOC_FILL_PAGES (mc_marker, 2)    + static void start_mc(void) + { +  LOCK_IMUTEX(&mc_mutex); +  init_mc_marker_hash(); + } +  + static void stop_mc(void) + { +  exit_mc_marker_hash(); +  UNLOCK_IMUTEX(&mc_mutex); + } +    static struct mc_marker *my_make_mc_marker (void *thing,    visit_thing_fn *visit_fn,    void *extra)   {    struct mc_marker *m = make_mc_marker (thing);    assert (thing);    assert (visit_fn);    m->thing = thing;    m->visit_fn = visit_fn;    m->extra = extra;
pike.git/src/gc.c:5615:       else {    if (TYPEOF(Pike_sp[-args]) != T_INT)    SIMPLE_ARG_TYPE_ERROR ("count_memory", 1, "int|mapping(string:int)");    mc_lookahead =    Pike_sp[-args].u.integer > (unsigned INT16) -1 ? (unsigned INT16) -1 :    Pike_sp[-args].u.integer < 0 ? -1 :    Pike_sp[-args].u.integer;    }    -  init_mc_marker_hash(); +  start_mc();       if (TYPEOF(pike_cycle_depth_str) == PIKE_T_FREE) {    SET_SVAL_TYPE(pike_cycle_depth_str, T_STRING);    MAKE_CONST_STRING (pike_cycle_depth_str.u.string, "pike_cycle_depth");    }       assert (mc_work_queue == NULL);    mc_work_queue = malloc (MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));    if (!mc_work_queue) { -  exit_mc_marker_hash(); +  stop_mc();    SIMPLE_OUT_OF_MEMORY_ERROR ("Pike.count_memory",    MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));    }    mc_wq_size = MC_WQ_START_SIZE;    mc_work_queue--; /* Compensate for 1-based indexing. */    mc_wq_used = 1;       assert (!mc_pass);    assert (visit_enter == NULL);    assert (visit_ref == NULL);
pike.git/src/gc.c:5650:       {    int i;    for (i = -args + 1; i < 0; i++) {    struct svalue *s = Pike_sp + i;       if (TYPEOF(*s) == T_INT)    continue;       else if (!REFCOUNTED_TYPE(TYPEOF(*s))) { -  exit_mc_marker_hash(); +     free (mc_work_queue + 1);    mc_work_queue = NULL; -  +  stop_mc();    SIMPLE_ARG_TYPE_ERROR (    "count_memory", i + args + 1,    "array|multiset|mapping|object|program|string|type|int");    }       else {    if (TYPEOF(*s) == T_FUNCTION) {    struct svalue s2;    if (!(s2.u.program = program_from_function (s))) { -  exit_mc_marker_hash(); +     free (mc_work_queue + 1);    mc_work_queue = NULL; -  +  stop_mc();    SIMPLE_ARG_TYPE_ERROR (    "count_memory", i + args + 1,    "array|multiset|mapping|object|program|string|type|int");    }    add_ref (s2.u.program);    SET_SVAL_TYPE(s2, T_PROGRAM);    free_svalue (s);    move_svalue (s, &s2);    }   
pike.git/src/gc.c:5686:    /* The user passed the same thing several times. Ignore it. */    }       else {    struct mc_marker *m =    my_make_mc_marker (s->u.ptr, visit_fn_from_type[TYPEOF(*s)], NULL);    m->flags |= MC_FLAG_INTERNAL;    if (!mc_block_pike_cycle_depth && TYPEOF(*s) == T_OBJECT) {    int cycle_depth = mc_cycle_depth_from_obj (s->u.object);    if (TYPEOF(throw_value) != PIKE_T_FREE) { -  exit_mc_marker_hash(); +     free (mc_work_queue + 1);    mc_work_queue = NULL; -  +  stop_mc();    throw_severity = THROW_ERROR;    pike_throw();    }    m->la_count = cycle_depth >= 0 ? cycle_depth : mc_lookahead;    }    else    m->la_count = mc_lookahead;    mc_wq_enqueue (m);    MC_DEBUG_MSG (m, "enqueued starting point");    }
pike.git/src/gc.c:5815:    MC_DEBUG_MSG (NULL, "leave - added to incomplete list");    }    else {    DL_ADD_LAST (mc_complete, mc_ref_from);    MC_DEBUG_MSG (NULL, "leave - added to complete list");    }    }    }       if (TYPEOF(throw_value) != PIKE_T_FREE) { -  exit_mc_marker_hash(); +     free (mc_work_queue + 1);    mc_work_queue = NULL; -  +  stop_mc();    throw_severity = THROW_ERROR;    pike_throw();    }    }   #if defined (PIKE_DEBUG) || defined (MEMORY_COUNT_DEBUG)    mc_ref_from = (void *) (ptrdiff_t) -1;   #endif       /* If no things that might be indirectly incomplete have been    * enqueued then there's no need to do another mark external pass. */
pike.git/src/gc.c:6062:    DL_MAKE_EMPTY (mc_incomplete);    DL_MAKE_EMPTY (mc_indirect);   #ifdef DO_PIKE_CLEANUP    {    size_t e;    for (e = 0; e < mc_marker_hash_table_size; e++)    while (mc_marker_hash_table[e])    remove_mc_marker (mc_marker_hash_table[e]->thing);    }   #endif -  exit_mc_marker_hash(); +        assert (mc_wq_used == 1);    free (mc_work_queue + 1);    mc_work_queue = NULL; -  +  stop_mc();       pop_n_elems (args);    push_ulongest (return_count ? count_internal : mc_counted_bytes);   }      static struct mapping *identify_loop_reverse = NULL;      void identify_loop_visit_enter(void *thing, int type, void *UNUSED(extra))   {    if (type < T_VOID) {
pike.git/src/gc.c:6171:    "array|multiset|mapping|object|program|string|type");    }    if (TYPEOF(*s) == T_FUNCTION) {    if (SUBTYPEOF(*s) == FUNCTION_BUILTIN) {    SIMPLE_ARG_TYPE_ERROR("identify_loops", 1,    "array|multiset|mapping|object|program|string|type");    }    SET_SVAL_TYPE(*s, T_OBJECT);    }    -  init_mc_marker_hash(); +  start_mc();       if (TYPEOF(pike_cycle_depth_str) == PIKE_T_FREE) {    SET_SVAL_TYPE(pike_cycle_depth_str, T_STRING);    MAKE_CONST_STRING (pike_cycle_depth_str.u.string, "pike_cycle_depth");    }       assert (mc_work_queue == NULL);    mc_work_queue = malloc (MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));    if (!mc_work_queue) { -  exit_mc_marker_hash(); +  stop_mc();    SIMPLE_OUT_OF_MEMORY_ERROR ("Pike.count_memory",    MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));    }    mc_work_queue--;    mc_wq_size = MC_WQ_START_SIZE;    mc_wq_used = 1;    mc_lookahead = -1;       assert (!mc_pass);    assert (visit_enter == NULL);
pike.git/src/gc.c:6222:    if (mc_ref_from->flags & MC_FLAG_INT_VISITED) continue;       mc_ref_from->flags |= MC_FLAG_INT_VISITED;    mc_ref_from->visit_fn(mc_ref_from->thing, VISIT_COMPLEX_ONLY, NULL);    }      #if defined (PIKE_DEBUG) || defined (MEMORY_COUNT_DEBUG)    mc_ref_from = (void *) (ptrdiff_t) -1;   #endif    -  exit_mc_marker_hash(); -  free (mc_work_queue + 1); +  /* NB: 1-based indexing in mc_work_queue. */ +  mc_work_queue++; +  free(mc_work_queue);    mc_work_queue = NULL;       visit_enter = NULL;    visit_ref = NULL;    visit_leave = NULL;      #ifdef PIKE_DEBUG    if (s != Pike_sp-1) {    Pike_fatal("Stack error in identify_loops.\n");    }
pike.git/src/gc.c:6250:    */    push_svalue(k);    if (k->u.refs == s->u.refs) {    /* Found! */    break;    }    }       free_mapping(identify_loop_reverse);    +  stop_mc(); +     if (!k) {    push_undefined();    } else {    /* NB: We push s an extra time last above, to simplify the    * reversing below.    */    f_aggregate(Pike_sp - (s + 1));    f_reverse(1);    }   } -  +  + void init_mc(void) + { +  init_interleave_mutex(&mc_mutex); + } +  + void exit_mc(void) + { +  exit_interleave_mutex(&mc_mutex); + }