pike.git / src / program.c

version» Context lines:

pike.git/src/program.c:40:   #include "bitvector.h"      #include <errno.h>   #include <fcntl.h>      #define sp Pike_sp      #undef ATTRIBUTE   #define ATTRIBUTE(X)    + #ifdef PIKE_THREADS + static COND_T Pike_compiler_cond; + static THREAD_T Pike_compiler_thread; + static int lock_depth = 0; +  + PMOD_EXPORT void lock_pike_compiler(void) + { +  while (lock_depth && (Pike_compiler_thread != th_self())) { +  co_wait_interpreter(&Pike_compiler_cond); +  } +  lock_depth++; +  Pike_compiler_thread = th_self(); + } +  + PMOD_EXPORT void unlock_pike_compiler(void) + { + #ifdef PIKE_DEBUG +  if (lock_depth < 1) { +  Pike_fatal("Pike compiler running unlocked!\n"); +  } + #endif +  lock_depth--; +  co_broadcast(&Pike_compiler_cond); + } + #else + PMOD_EXPORT void lock_pike_compiler(void) + { + } + PMOD_EXPORT void unlock_pike_compiler(void) + { + } + #endif +    static void low_enter_compiler(struct object *ce, int inherit);   static void exit_program_struct(struct program *);   static size_t add_xstorage(size_t size,    size_t alignment,    ptrdiff_t modulo_orig);      static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);      ATTRIBUTE((malloc))   struct program * alloc_program() {
pike.git/src/program.c:78:   void free_all_program_blocks() {    ba_destroy(&program_allocator);   }      /* #define COMPILER_DEBUG */   /* #define PROGRAM_BUILD_DEBUG */      #ifdef COMPILER_DEBUG   #define CDFPRINTF(X) fprintf X   #ifndef PIKE_THREADS - /* The CDFPRINTF lines wants to print threads_disabled, so fake on of those */ - static const int threads_disabled = 1; + /* The CDFPRINTF lines wants to print lock_depth, so fake one of those */ + static const int lock_depth = 1;   #endif   #else /* !COMPILER_DEBUG */   #define CDFPRINTF(X)   #endif /* COMPILER_DEBUG */      /*    * These two values should probably be fine-tuned, but doing so    * more or less requires running a predictable 'typical' application    * and testing different hashsizes and tresholds. I tried to do it    * mathematically by measuring the extremes (no cache hits, 100%
pike.git/src/program.c:2838:    struct pike_string *name,    int flags,    int *idp)   {    struct compilation *c = THIS_COMPILATION;    int id=0;    struct svalue tmp;       CHECK_COMPILER();    -  /* We don't want to change thread, but we don't want to -  * wait for the other threads to complete either. +  /* We aren't thread safe, but we are reentrant. +  * +  * Lock out any other threads from the compiler until we are finished.    */ -  low_init_threads_disable(); +  lock_pike_compiler();       c->compilation_depth++;       SET_SVAL_TYPE(tmp, T_PROGRAM);    if(!p)    {    p=low_allocate_program();    if(name)    {    tmp.u.program=p;
pike.git/src/program.c:2886:    if (pass == 1) {    if(c->compilation_depth >= 1) {    add_ref(p->parent = Pike_compiler->new_program);    debug_malloc_touch (p);    }    }    p->flags &=~ PROGRAM_VIRGIN;    if(idp) *idp=id;       CDFPRINTF((stderr, "th(%ld) %p low_start_new_program() %s " -  "pass=%d: threads_disabled:%d, compilation_depth:%d\n", +  "pass=%d: lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), p, name ? name->str : "-",    Pike_compiler->compiler_pass, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));       init_type_stack();      #define PUSH   #include "compilation.h"       ba_init(&Pike_compiler->node_allocator, sizeof(struct node_s), 512);       Pike_compiler->parent_identifier=id;    Pike_compiler->compiler_pass = pass;
pike.git/src/program.c:3119:    const char *p = DEFINETOSTR(PIKE_SRC_ROOT), *f = file;    while (*p && *p == *f) p++, f++;    while (*f == '/' || *f == '\\') f++;       c->lex.current_file = make_shared_string(f);    c->lex.current_line = line;    }       CDFPRINTF((stderr,    "th(%ld) start_new_program(%ld, %s): " -  "threads_disabled:%d, compilation_depth:%d\n", +  "lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), (long)line, file, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));       low_start_new_program(0,1,0,0,0);    store_linenumber(line,c->lex.current_file);    debug_malloc_name(Pike_compiler->new_program, file, line);       free_string(c->lex.current_file);    c->lex.current_file = dmalloc_touch(struct pike_string *, save_file);    c->lex.current_line = save_line;   }   
pike.git/src/program.c:4145:   #endif /* SHARED_NODES */      #define POP   #include "compilation.h"       exit_type_stack();          CDFPRINTF((stderr,    "th(%ld) %p end_first_pass(%d): " -  "threads_disabled:%d, compilation_depth:%d\n", +  "lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), prog, finish, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));       c->compilation_depth--;    -  exit_threads_disable(NULL); +  unlock_pike_compiler();      #if 0   #ifdef PIKE_USE_MACHINE_CODE    if (prog &&    (((unsigned long long *)prog->program)[-1] != 0xdeadfeedf00dfaddLL)) {    Pike_fatal("Bad mexec magic!\n");    }   #endif /* PIKE_USE_MACHINE_CODE */   #endif /* 0 */    return prog;
pike.git/src/program.c:8979:    if(c->target && !(c->target->flags & PROGRAM_VIRGIN)) {    yyerror("Placeholder program is not virgin!");    return 0;    }       low_start_new_program(c->target,1,0,0,0);    c->supporter.prog = Pike_compiler->new_program;       CDFPRINTF((stderr,    "th(%ld) %p run_pass1() start: " -  "threads_disabled:%d, compilation_depth:%d\n", +  "lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), Pike_compiler->new_program, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));       run_init2(c);       if(c->placeholder)    {    if(c->placeholder->prog != null_program)    {    yyerror("Placeholder argument is not a null_program clone!");    c->placeholder=0;    debug_malloc_touch(c->placeholder);
pike.git/src/program.c:9068:       run_init(c);    low_start_new_program(c->p,2,0,0,0);    free_program(c->p);    c->p=0;       run_init2(c);       CDFPRINTF((stderr,    "th(%ld) %p run_pass2() start: " -  "threads_disabled:%d, compilation_depth:%d\n", +  "lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), Pike_compiler->new_program, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));       verify_supporters();       do_yyparse(); /* Parse da program */       CDFPRINTF((stderr, "th(%ld) %p run_pass2() done for %s\n",    (long)th_self(), Pike_compiler->new_program,    c->lex.current_file->str));       verify_supporters();
pike.git/src/program.c:9093:       run_exit(c);   }      static void run_cleanup(struct compilation *c, int delayed)   {    debug_malloc_touch(c);    debug_malloc_touch(c->placeholder);   #if 0 /* FIXME */   #ifdef PIKE_THREADS -  if (threads_disabled != c->saved_threads_disabled) { -  Pike_fatal("compile(): threads_disabled:%d saved_threads_disabled:%d\n", -  threads_disabled, c->saved_threads_disabled); +  if (lock_depth != c->saved_lock_depth) { +  Pike_fatal("compile(): lock_depth:%d saved_lock_depth:%d\n", +  lock_depth, c->saved_lock_depth);    }   #endif   #endif /* PIKE_DEBUG */    -  exit_threads_disable(NULL); +  unlock_pike_compiler();       CDFPRINTF((stderr,    "th(%ld) %p run_cleanup(): " -  "threads_disabled:%d, compilation_depth:%d\n", +  "lock_depth:%d, compilation_depth:%d\n",    (long)th_self(), c->target, -  threads_disabled, c->compilation_depth)); +  lock_depth, c->compilation_depth));    if (!c->p)    {    /* fprintf(stderr, "Destructing placeholder.\n"); */    if(c->placeholder) {    debug_malloc_touch(c->placeholder);    zap_placeholder(c);    }       if(delayed && c->target)    {
pike.git/src/program.c:9557:    ref_push_program(c->p);    return;    }      #ifdef PIKE_DEBUG    SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");   #endif       c->flags |= COMPILER_BUSY;    -  low_init_threads_disable(); +  lock_pike_compiler();   #ifdef PIKE_THREADS -  c->saved_threads_disabled = threads_disabled; +  c->saved_lock_depth = lock_depth;   #endif       init_supporter(& c->supporter,    (supporter_callback *) call_delayed_pass2,    (void *)c);       delay=run_pass1(c);    dependants_ok = call_dependants(& c->supporter, !!c->p );   #ifdef PIKE_DEBUG    /* FIXME */
pike.git/src/program.c:10517:    }else{    ref_push_mapping(get_builtin_constants());    }    free_svalue(& c->default_module);    move_svalue (&c->default_module, --Pike_sp);      #ifdef PIKE_DEBUG    SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");   #endif    -  low_init_threads_disable(); +  lock_pike_compiler();   #ifdef PIKE_THREADS -  c->saved_threads_disabled = threads_disabled; +  c->saved_lock_depth = lock_depth;   #endif       init_supporter(& c->supporter,    (supporter_callback *) call_delayed_pass2,    (void *)c);       delay=run_pass1(c);    dependants_ok = call_dependants(& c->supporter, !!c->p );   #ifdef PIKE_DEBUG    /* FIXME */
pike.git/src/program.c:10833:    mapping_insert(lfun_ids, &key, &id);       SET_SVAL(val, T_TYPE, 0, type, make_pike_type(raw_lfun_types[i]));    mapping_insert(lfun_types, &key, &val);    free_type(val.u.type);    }       lfun_getter_type_string = make_pike_type(tFuncV(tNone, tVoid, tMix));    lfun_setter_type_string = make_pike_type(tFuncV(tZero, tVoid, tVoid));    + #ifdef PIKE_THREADS +  co_init(&Pike_compiler_cond); + #endif +     compile_compiler();       enter_compiler(NULL, 0);       start_new_program();    debug_malloc_touch(Pike_compiler->fake_object);    debug_malloc_touch(Pike_compiler->fake_object->storage);    ADD_STORAGE(struct pike_trampoline);    ADD_FUNCTION("`()",apply_trampoline,tFunction,0);    ADD_FUNCTION("`!",not_trampoline,tFunc(tVoid,tInt),0);
pike.git/src/program.c:10960:    compilation_environment = 0;    }    if (compilation_env_program) {    free_program(compilation_env_program);    compilation_env_program = 0;    }    if (reporter_program) {    free_program(reporter_program);    reporter_program = 0;    } + #ifdef PIKE_THREADS +  co_destroy(&Pike_compiler_cond); + #endif   }         PMOD_EXPORT void visit_program (struct program *p, int action)   {    switch (action) {   #ifdef PIKE_DEBUG    default:    Pike_fatal ("Unknown visit action %d.\n", action);    case VISIT_NORMAL: