Beispiel #1
0
Datei: gc.c Projekt: wlbksy/julia
static void gc_mark(void)
{
    // mark all roots

    // active tasks
    gc_push_root(jl_root_task);
    gc_push_root(jl_current_task);

    // modules
    gc_push_root(jl_main_module);
    gc_push_root(jl_current_module);

    // invisible builtin values
    if (jl_an_empty_cell) gc_push_root(jl_an_empty_cell);
    gc_push_root(jl_exception_in_transit);
    gc_push_root(jl_task_arg_in_transit);
    gc_push_root(jl_unprotect_stack_func);
    gc_push_root(jl_bottom_func);
    gc_push_root(jl_typetype_type);
    gc_push_root(jl_tupletype_type);

    // constants
    gc_push_root(jl_null);
    gc_push_root(jl_true);
    gc_push_root(jl_false);

    // libuv loops
    gc_mark_uv_state(jl_global_event_loop());

    jl_mark_box_caches();

    size_t i;

    // stuff randomly preserved
    for(i=0; i < preserved_values.len; i++) {
        gc_push_root((jl_value_t*)preserved_values.items[i]);
    }

    // objects currently being finalized
    for(i=0; i < to_finalize.len; i++) {
        gc_push_root(to_finalize.items[i]);
    }

    gc_mark_all();

    // find unmarked objects that need to be finalized.
    // this must happen last.
    for(i=0; i < finalizer_table.size; i+=2) {
        if (finalizer_table.table[i+1] != HT_NOTFOUND) {
            jl_value_t *v = finalizer_table.table[i];
            if (!gc_marked(v)) {
                gc_push_root(v);
                schedule_finalization(v);
            }
            gc_push_root(finalizer_table.table[i+1]);
        }
    }

    gc_mark_all();
}
Beispiel #2
0
DLLEXPORT void jl_close_uv(uv_handle_t *handle)
{
    if (!handle || uv_is_closing(handle))
       return;
    if (handle->type==UV_TTY)
        uv_tty_set_mode((uv_tty_t*)handle,0);

    if ( (handle->type == UV_NAMED_PIPE || handle->type == UV_TCP) && uv_is_writable( (uv_stream_t *) handle)) { 
        // Make sure that the stream has not already been marked closed in Julia.
        // A double shutdown would cause the process to hang on exit.
        JULIA_CB(isopen, handle->data, 0);
        if (!jl_is_int32(ret)) {
            jl_error("jl_close_uv: _uv_hook_isopen must return an int32.");
        }
        if (!jl_unbox_int32(ret)){
            return;
        }

        uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t));
        int err = uv_shutdown(req, (uv_stream_t*)handle, &shutdownCallback);
        if (err != 0) {
            printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop())));
            uv_close(handle, &closeHandle);
        }
    }
    else {
        uv_close(handle,&closeHandle);
    }
}
Beispiel #3
0
int true_main(int argc, char *argv[])
{
    if (jl_base_module != NULL) {
        jl_array_t *args = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("ARGS"));
        assert(jl_array_len(args) == 0);
        jl_array_grow_end(args, argc);
        int i;
        for (i=0; i < argc; i++) {
            jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]);
            s->type = (jl_value_t*)jl_utf8_string_type;
            jl_arrayset(args, s, i);
        }
    }
    
    // run program if specified, otherwise enter REPL
    if (program) {
        int ret = exec_program();
        uv_tty_reset_mode();
        return ret;
    }

    jl_function_t *start_client =
        (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start"));

    //uv_read_start(jl_stdin_tty,jl_alloc_read_buffer,&read_buffer);

    if (start_client) {
        jl_apply(start_client, NULL, 0);
        //rl_cleanup_after_signal();
        return 0;
    }

    // client event loop not available; use fallback blocking version
    //install_read_event_handler(&echoBack);
    int iserr = 0;

 again:
    ;
    JL_TRY {
        if (iserr) {
            //jl_show(jl_exception_in_transit);# What if the error was in show?
            jl_printf(JL_STDERR, "\n\n");
            iserr = 0;
        }
        uv_run(jl_global_event_loop(),UV_RUN_DEFAULT);
    }
    JL_CATCH {
        iserr = 1;
        JL_PUTS("error during run:\n",JL_STDERR);
        jl_show(jl_stderr_obj(),jl_exception_in_transit);
        JL_PUTS("\n",JL_STDOUT);
        goto again;
    }
    uv_tty_reset_mode();
    return iserr;
}
Beispiel #4
0
int true_main(int argc, char *argv[])
{
    if (jl_base_module != NULL) {
        jl_array_t *args = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("ARGS"));
        if (args == NULL) {
            args = jl_alloc_cell_1d(0);
            jl_set_const(jl_base_module, jl_symbol("ARGS"), (jl_value_t*)args);
        }
        assert(jl_array_len(args) == 0);
        jl_array_grow_end(args, argc);
        int i;
        for (i=0; i < argc; i++) {
            jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]);
            s->type = (jl_value_t*)jl_utf8_string_type;
            jl_arrayset(args, s, i);
        }
    }

    // run program if specified, otherwise enter REPL
    if (program) {
        int ret = exec_program();
        uv_tty_reset_mode();
        return ret;
    }

    jl_function_t *start_client =
        (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start"));

    if (start_client) {
        jl_apply(start_client, NULL, 0);
        return 0;
    }

    int iserr = 0;

 again:
    ;
    JL_TRY {
        if (iserr) {
            //jl_show(jl_exception_in_transit);# What if the error was in show?
            jl_printf(JL_STDERR, "\n\n");
            iserr = 0;
        }
        uv_run(jl_global_event_loop(),UV_RUN_DEFAULT);
    }
    JL_CATCH {
        iserr = 1;
        JL_PUTS("error during run:\n",JL_STDERR);
        jl_show(jl_stderr_obj(),jl_exception_in_transit);
        JL_PUTS("\n",JL_STDOUT);
        goto again;
    }
    uv_tty_reset_mode();
    return iserr;
}
Beispiel #5
0
DLLEXPORT void uv_atexit_hook()
{
    uv_loop_t* loop = jl_global_event_loop();
    struct uv_shutdown_queue queue = {NULL, NULL};
    uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
    struct uv_shutdown_queue_item *item = queue.first;
    while (item) {
        uv_handle_t *handle = item->h;
        switch(handle->type) {
            case UV_TTY:
            case UV_UDP:
//#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE
// but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general
                uv_close(handle,NULL);
                break;
//#endif
            case UV_TCP:
            case UV_NAMED_PIPE:
                if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable
                    uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t));
                    int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb);
                    if (err != 0) { printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop())));}
                }
                else {
                    uv_close(handle,NULL);
                }
                break;
            case UV_POLL:
            case UV_TIMER:
            case UV_PREPARE:
            case UV_CHECK:
            case UV_IDLE:
            case UV_ASYNC:
            case UV_SIGNAL:
            case UV_PROCESS:
            case UV_FS_EVENT:
            case UV_FS_POLL:
                uv_close(handle,NULL); //do we want to use jl_close_uv?
                break;
            case UV_HANDLE:
            case UV_STREAM:
            case UV_UNKNOWN_HANDLE:
            case UV_HANDLE_TYPE_MAX:
            case UV_RAW_FD:
            case UV_RAW_HANDLE:
            default:
                assert(0);
        }
        item = item->next;
    }
    uv_run(loop); //let libuv spin until everything has finished closing
}
Beispiel #6
0
JL_DLLEXPORT void jl_wakeup_thread(int16_t tid)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    /* ensure thread tid is awake if necessary */
    if (ptls->tid != tid && !_threadedregion && tid != -1) {
        uv_mutex_lock(&sleep_lock);
        uv_cond_broadcast(&sleep_alarm); // TODO: make this uv_cond_signal / just wake up correct thread
        uv_mutex_unlock(&sleep_lock);
    }
    if (_threadedregion && jl_uv_mutex.owner != jl_thread_self())
        jl_wake_libuv();
    else
        uv_stop(jl_global_event_loop());
}
Beispiel #7
0
    if (jl_base_module) {
        jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
        if (f!=NULL && jl_is_function(f)) {
            JL_TRY {
                jl_apply((jl_function_t*)f, NULL, 0);
            }
            JL_CATCH {
                jl_printf(JL_STDERR, "\natexit hook threw an error: ");
                jl_static_show(JL_STDERR, jl_exception_in_transit);
            }
        }
    }

    jl_gc_run_all_finalizers();

    uv_loop_t *loop = jl_global_event_loop();

    if (loop == NULL) {
        return;
    }

    struct uv_shutdown_queue queue = {NULL, NULL};
    uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
    // close stdout and stderr last, since we like being
    // able to show stuff (incl. printf's)
    if (JL_STDOUT != (void*) STDOUT_FILENO &&
        ((uv_handle_t*)JL_STDOUT)->type < UV_HANDLE_TYPE_MAX)
        jl_uv_exitcleanup_add((uv_handle_t*)JL_STDOUT, &queue);
    if (JL_STDERR != (void*) STDERR_FILENO &&
        ((uv_handle_t*)JL_STDERR)->type < UV_HANDLE_TYPE_MAX)
        jl_uv_exitcleanup_add((uv_handle_t*)JL_STDERR, &queue);
Beispiel #8
0
DLLEXPORT void uv_atexit_hook()
{
#if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS)
    jl_print_gc_stats(JL_STDERR);
#endif
    if (jl_base_module) {
        jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
        if (f!=NULL && jl_is_function(f)) {
            jl_apply((jl_function_t*)f, NULL, 0);
        }
    }
    uv_loop_t* loop = jl_global_event_loop();
    struct uv_shutdown_queue queue = {NULL, NULL};
    uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
    // close stdout and stderr last, since we like being
    // able to show stuff (incl. printf's)
    jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue);
    jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue);
    struct uv_shutdown_queue_item *item = queue.first;
    while (item) {
        uv_handle_t *handle = item->h;
        if (uv_is_closing(handle)) {
            item = item->next;
            continue;
        }
        switch(handle->type) {
        case UV_TTY:
        case UV_UDP:
//#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE
// but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general
            jl_close_uv(handle);
            break;
//#endif
        case UV_TCP:
        case UV_NAMED_PIPE:
            if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable
                uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t));
                int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb);
                if (err != 0) {
                    printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop())));
                    jl_close_uv(handle);
                }
            }
            else {
                jl_close_uv(handle);
            }
            break;
        case UV_POLL:
        case UV_TIMER:
        case UV_PREPARE:
        case UV_CHECK:
        case UV_IDLE:
        case UV_ASYNC:
        case UV_SIGNAL:
        case UV_PROCESS:
        case UV_FS_EVENT:
        case UV_FS_POLL:
            jl_close_uv(handle);
            break;
        case UV_HANDLE:
        case UV_STREAM:
        case UV_UNKNOWN_HANDLE:
        case UV_HANDLE_TYPE_MAX:
        case UV_RAW_FD:
        case UV_RAW_HANDLE:
        default:
            assert(0);
        }
        item = item->next;
    }
    uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing
}
Beispiel #9
0
static NOINLINE int true_main(int argc, char *argv[])
{
    if (jl_core_module != NULL) {
        jl_array_t *args = (jl_array_t*)jl_get_global(jl_core_module, jl_symbol("ARGS"));
        if (args == NULL) {
            args = jl_alloc_cell_1d(0);
            JL_GC_PUSH1(&args);
            jl_set_const(jl_core_module, jl_symbol("ARGS"), (jl_value_t*)args);
            JL_GC_POP();
        }
        assert(jl_array_len(args) == 0);
        jl_array_grow_end(args, argc);
        int i;
        for (i=0; i < argc; i++) {
            jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]);
            jl_set_typeof(s,jl_utf8_string_type);
            jl_arrayset(args, s, i);
        }
    }

    jl_function_t *start_client = jl_base_module ?
        (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")) : NULL;

    if (start_client) {
        jl_apply(&start_client, 1);
        return 0;
    }

    // run program if specified, otherwise enter REPL
    if (argc > 0) {
        if (strcmp(argv[0], "-")) {
            return exec_program(argv[0]);
        }
    }

    ios_puts("WARNING: Base._start not defined, falling back to economy mode repl.\n", ios_stdout);
    if (!jl_errorexception_type)
        ios_puts("WARNING: jl_errorexception_type not defined; any errors will be fatal.\n", ios_stdout);

    while (!ios_eof(ios_stdin)) {
        char *volatile line = NULL;
        JL_TRY {
            ios_puts("\njulia> ", ios_stdout);
            ios_flush(ios_stdout);
            line = ios_readline(ios_stdin);
            jl_value_t *val = (jl_value_t*)jl_eval_string(line);
            if (jl_exception_occurred()) {
                jl_printf(JL_STDERR, "error during run:\n");
                jl_static_show(JL_STDERR, jl_exception_in_transit);
                jl_exception_clear();
            }
            else if (val) {
                jl_static_show(JL_STDOUT, val);
            }
            jl_printf(JL_STDOUT, "\n");
            free(line);
            line = NULL;
            uv_run(jl_global_event_loop(),UV_RUN_NOWAIT);
        }
        JL_CATCH {
            if (line) {
                free(line);
                line = NULL;
            }
            jl_printf(JL_STDERR, "\nparser error:\n");
            jl_static_show(JL_STDERR, jl_exception_in_transit);
            jl_printf(JL_STDERR, "\n");
            jlbacktrace();
        }
    }
    return 0;
}
Beispiel #10
0
DLLEXPORT void uv_atexit_hook()
{
#if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS)
    jl_print_gc_stats(JL_STDERR);
#endif
    if (jl_base_module) {
        jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
        if (f!=NULL && jl_is_function(f)) {
            jl_apply((jl_function_t*)f, NULL, 0);
        }
    }
    uv_loop_t* loop = jl_global_event_loop();
    struct uv_shutdown_queue queue = {NULL, NULL};
    uv_walk(loop, jl_uv_exitcleanup_walk, &queue);
    // close stdout and stderr last, since we like being
    // able to show stuff (incl. printf's)
    jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue);
    jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue);
    struct uv_shutdown_queue_item *item = queue.first;
    while (item) {
        uv_handle_t *handle = item->h;
        if (uv_is_closing(handle)) {
            item = item->next;
            continue;
        }
        switch(handle->type) {
        case UV_TTY:
        case UV_UDP:
//#ifndef _OS_WINDOWS_ // unix only supports shutdown on TCP and NAMED_PIPE
// but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general
            jl_close_uv(handle);
            break;
//#endif
        case UV_TCP:
        case UV_NAMED_PIPE:
            // These will be shut down in jl_close_uv.
            jl_close_uv(handle);
            break;
        //Don't close these directly, but rather let the GC take care of it
        case UV_POLL:
            uv_poll_stop((uv_poll_t*)handle);
            handle->data = NULL;
            uv_unref(handle);
            break;
        case UV_TIMER:
            uv_timer_stop((uv_timer_t*)handle);
            handle->data = NULL;
            uv_unref(handle);
            break;
        case UV_IDLE:
            uv_idle_stop((uv_idle_t*)handle);
        case UV_ASYNC:
            handle->data = NULL;
            uv_unref(handle);
            break;
        case UV_FS_EVENT:
            handle->data = NULL;
            uv_unref(handle);
            break;
        case UV_FS_POLL:
            uv_fs_poll_stop((uv_fs_poll_t*)handle);
            handle->data = NULL;
            uv_unref(handle);
            break;
        case UV_PREPARE:
        case UV_CHECK:
        case UV_SIGNAL:
        case UV_PROCESS:
            jl_close_uv(handle);
            break;
        case UV_HANDLE:
        case UV_STREAM:
        case UV_UNKNOWN_HANDLE:
        case UV_HANDLE_TYPE_MAX:
        case UV_RAW_FD:
        case UV_RAW_HANDLE:
        default:
            assert(0);
        }
        item = item->next;
    }
    uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing
}
Beispiel #11
0
JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *getsticky)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    // spin briefly before blocking when the workqueue is empty
    size_t spin_count = 0;
    jl_task_t *task;

    while (1) {
        jl_gc_safepoint();
        task = get_next_task(getsticky);
        if (task)
            return task;

        if (!_threadedregion) {
            spin_count = 0;
            if (ptls->tid == 0) {
                if (jl_run_once(jl_global_event_loop()) == 0) {
                    task = get_next_task(getsticky);
                    if (task)
                        return task;
#ifdef _OS_WINDOWS_
                    Sleep(INFINITE);
#else
                    pause();
#endif
                }
            }
            else {
                int sleepnow = 0;
                uv_mutex_lock(&sleep_lock);
                if (!_threadedregion) {
                    sleepnow = 1;
                }
                else {
                    uv_mutex_unlock(&sleep_lock);
                }
                if (sleepnow) {
                    int8_t gc_state = jl_gc_safe_enter(ptls);
                    uv_cond_wait(&sleep_alarm, &sleep_lock);
                    uv_mutex_unlock(&sleep_lock);
                    jl_gc_safe_leave(ptls, gc_state);
                }
            }
        }
        else {
            if (++spin_count > 1000 && jl_atomic_load(&jl_uv_n_waiters) == 0 && jl_mutex_trylock(&jl_uv_mutex)) {
                task = get_next_task(getsticky);
                if (task) {
                    JL_UV_UNLOCK();
                    return task;
                }
                uv_loop_t *loop = jl_global_event_loop();
                loop->stop_flag = 0;
                uv_run(loop, UV_RUN_ONCE);
                JL_UV_UNLOCK();
            }
            else {
                jl_cpu_pause();
            }
        }
    }
}