Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/core/threadcontext.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
#include "platform/time.h"
3
4
/* Initializes a new thread context. Note that this doesn't set up a
5
 * thread itself, it just creates the data structure that exists in
6
 * MoarVM per thread. */
7
130
MVMThreadContext * MVM_tc_create(MVMThreadContext *parent, MVMInstance *instance) {
8
130
    MVMThreadContext *tc = MVM_calloc(1, sizeof(MVMThreadContext));
9
130
10
130
    /* Associate with VM instance. */
11
130
    tc->instance = instance;
12
130
13
130
    /* Use default loop for main thread; create a new one for others. */
14
130
    if (instance->main_thread) {
15
0
        int r;
16
0
17
0
        tc->loop = MVM_calloc(1, sizeof(uv_loop_t));
18
0
        r = uv_loop_init(tc->loop);
19
0
        if (r < 0) {
20
0
            MVM_free(tc->loop);
21
0
            MVM_free(tc);
22
0
            MVM_exception_throw_adhoc(parent, "Could not create a new Thread: %s", uv_strerror(r));
23
0
        }
24
130
    } else {
25
130
        tc->loop = uv_default_loop();
26
130
    }
27
130
28
130
    /* Set up GC nursery. We only allocate tospace initially, and allocate
29
130
     * fromspace the first time this thread GCs, provided it ever does. */
30
130
    tc->nursery_tospace     = MVM_calloc(1, MVM_NURSERY_SIZE);
31
130
    tc->nursery_alloc       = tc->nursery_tospace;
32
130
    tc->nursery_alloc_limit = (char *)tc->nursery_alloc + MVM_NURSERY_SIZE;
33
130
34
130
    /* Set up temporary root handling. */
35
130
    tc->num_temproots   = 0;
36
130
    tc->alloc_temproots = MVM_TEMP_ROOT_BASE_ALLOC;
37
130
    tc->temproots       = MVM_malloc(sizeof(MVMCollectable **) * tc->alloc_temproots);
38
130
39
130
    /* Set up intergenerational root handling. */
40
130
    tc->num_gen2roots   = 0;
41
130
    tc->alloc_gen2roots = 64;
42
130
    tc->gen2roots       = MVM_malloc(sizeof(MVMCollectable *) * tc->alloc_gen2roots);
43
130
44
130
    /* Set up the second generation allocator. */
45
130
    tc->gen2 = MVM_gc_gen2_create(instance);
46
130
47
130
    /* Allocate an initial call stack region for the thread. */
48
130
    MVM_callstack_region_init(tc);
49
130
50
130
    /* Initialize random number generator state. */
51
130
    MVM_proc_seed(tc, (MVM_platform_now() / 10000) * MVM_proc_getpid(tc));
52
130
53
130
    /* Initialize frame sequence numbers */
54
130
    tc->next_frame_nr = 0;
55
130
    tc->current_frame_nr = 0;
56
130
57
130
    /* Initialize last_payload, so we can be sure it's never NULL and don't
58
130
     * need to check. */
59
130
    tc->last_payload = instance->VMNull;
60
130
61
130
    return tc;
62
130
}
63
64
/* Destroys a given thread context. This will also free the nursery.
65
 * This means that it must no longer be in use, at all; this can be
66
 * ensured by a GC run at thread exit that forces evacuation of all
67
 * objects from this nursery to the second generation. Only after
68
 * that is true should this be called. */
69
0
void MVM_tc_destroy(MVMThreadContext *tc) {
70
0
    /* We run once again (non-blocking) to eventually close filehandles. */
71
0
    uv_run(tc->loop, UV_RUN_NOWAIT);
72
0
73
0
    /* Free the nursery and finalization queue. */
74
0
    MVM_free(tc->nursery_fromspace);
75
0
    MVM_free(tc->nursery_tospace);
76
0
    MVM_free(tc->finalizing);
77
0
78
0
    /* Destroy the second generation allocator. */
79
0
    MVM_gc_gen2_destroy(tc->instance, tc->gen2);
80
0
81
0
    /* Destroy all callstack regions. */
82
0
    MVM_callstack_region_destroy_all(tc);
83
0
84
0
    /* Free the thread-specific storage */
85
0
    MVM_free(tc->gc_work);
86
0
    MVM_free(tc->temproots);
87
0
    MVM_free(tc->gen2roots);
88
0
    MVM_free(tc->finalize);
89
0
90
0
    /* Free any memory allocated for NFAs and multi-dim indices. */
91
0
    MVM_free(tc->nfa_done);
92
0
    MVM_free(tc->nfa_curst);
93
0
    MVM_free(tc->nfa_nextst);
94
0
    MVM_free(tc->nfa_fates);
95
0
    MVM_free(tc->nfa_longlit);
96
0
    MVM_free(tc->multi_dim_indices);
97
0
98
0
    /* Free per-thread lexotic cache. */
99
0
    MVM_free(tc->lexotic_cache);
100
0
101
0
    /* Destroy the libuv event loop */
102
0
    uv_loop_delete(tc->loop);
103
0
104
0
    /* Free the thread context itself. */
105
0
    memset(tc, 0, sizeof(MVMThreadContext));
106
0
    MVM_free(tc);
107
0
}
108
109
/* Setting and clearing mutex to release on exception throw. */
110
16.3k
void MVM_tc_set_ex_release_mutex(MVMThreadContext *tc, uv_mutex_t *mutex) {
111
16.3k
    if (tc->ex_release_mutex)
112
0
        MVM_exception_throw_adhoc(tc, "Internal error: multiple ex_release_mutex");
113
16.3k
    tc->ex_release_mutex = mutex;
114
16.3k
}
115
103
void MVM_tc_release_ex_release_mutex(MVMThreadContext *tc) {
116
103
    if (tc->ex_release_mutex)
117
2
        uv_mutex_unlock(tc->ex_release_mutex);
118
103
    tc->ex_release_mutex = NULL;
119
103
}
120
16.3k
void MVM_tc_clear_ex_release_mutex(MVMThreadContext *tc) {
121
16.3k
    tc->ex_release_mutex = NULL;
122
16.3k
}