Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/6model/reprs/ReentrantMutex.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* This representation's function pointer table. */
4
static const MVMREPROps ReentrantMutex_this_repr;
5
6
/* Populates the object body with a mutex. */
7
5.48k
static void initialize_mutex(MVMThreadContext *tc, MVMReentrantMutexBody *rm) {
8
5.48k
    int init_stat;
9
5.48k
    rm->mutex = MVM_malloc(sizeof(uv_mutex_t));
10
5.48k
    if ((init_stat = uv_mutex_init(rm->mutex)) < 0)
11
0
        MVM_exception_throw_adhoc(tc, "Failed to initialize mutex: %s",
12
0
            uv_strerror(init_stat));
13
5.48k
}
14
15
/* Creates a new type object of this representation, and associates it with
16
 * the given HOW. */
17
130
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
18
130
    MVMSTable *st  = MVM_gc_allocate_stable(tc, &ReentrantMutex_this_repr, HOW);
19
130
20
130
    MVMROOT(tc, st, {
21
130
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
22
130
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
23
130
        st->size = sizeof(MVMReentrantMutex);
24
130
    });
25
130
26
130
    return st->WHAT;
27
130
}
28
29
/* Initializes a new instance. */
30
5.48k
static void initialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data) {
31
5.48k
    initialize_mutex(tc, (MVMReentrantMutexBody *)data);
32
5.48k
}
33
34
/* Copies the body of one object to another. */
35
0
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
36
0
    MVM_exception_throw_adhoc(tc, "Cannot copy object with representation ReentrantMutex");
37
0
}
38
39
/* Called by the VM in order to free memory associated with this object. */
40
0
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
41
0
    /* The ThreadContext has already been destroyed by the GC. */
42
0
    MVMReentrantMutex *rm = (MVMReentrantMutex *)obj;
43
0
    if (rm->body.lock_count)
44
0
        MVM_panic(1, "Tried to garbage-collect a locked mutex");
45
0
    uv_mutex_destroy(rm->body.mutex);
46
0
    MVM_free(rm->body.mutex);
47
0
}
48
49
50
static const MVMStorageSpec storage_spec = {
51
    MVM_STORAGE_SPEC_REFERENCE, /* inlineable */
52
    0,                          /* bits */
53
    0,                          /* align */
54
    MVM_STORAGE_SPEC_BP_NONE,   /* boxed_primitive */
55
    0,                          /* can_box */
56
    0,                          /* is_unsigned */
57
};
58
59
/* Gets the storage specification for this representation. */
60
0
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
61
0
    return &storage_spec;
62
0
}
63
64
/* Compose the representation. */
65
0
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) {
66
0
    /* Nothing to do for this REPR. */
67
0
}
68
69
/* Set the size of the STable. */
70
130
static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
71
130
    st->size = sizeof(MVMReentrantMutex);
72
130
}
73
74
/* Serializing a mutex doesn't save anything; we will re-create it upon
75
 * deserialization. Makes data structures that just happen to have a lock in
76
 * them serializable. */
77
0
static void serialize(MVMThreadContext *tc, MVMSTable *st, void *data, MVMSerializationWriter *writer) {
78
0
}
79
0
static void deserialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMSerializationReader *reader) {
80
0
    initialize_mutex(tc, (MVMReentrantMutexBody *)data);
81
0
}
82
83
/* Initializes the representation. */
84
130
const MVMREPROps * MVMReentrantMutex_initialize(MVMThreadContext *tc) {
85
130
    return &ReentrantMutex_this_repr;
86
130
}
87
88
static const MVMREPROps ReentrantMutex_this_repr = {
89
    type_object_for,
90
    MVM_gc_allocate_object,
91
    initialize,
92
    copy_to,
93
    MVM_REPR_DEFAULT_ATTR_FUNCS,
94
    MVM_REPR_DEFAULT_BOX_FUNCS,
95
    MVM_REPR_DEFAULT_POS_FUNCS,
96
    MVM_REPR_DEFAULT_ASS_FUNCS,
97
    MVM_REPR_DEFAULT_ELEMS,
98
    get_storage_spec,
99
    NULL, /* change_type */
100
    serialize,
101
    deserialize,
102
    NULL, /* serialize_repr_data */
103
    NULL, /* deserialize_repr_data */
104
    deserialize_stable_size,
105
    NULL, /* gc_mark */
106
    gc_free,
107
    NULL, /* gc_cleanup */
108
    NULL, /* gc_mark_repr_data */
109
    NULL, /* gc_free_repr_data */
110
    compose,
111
    NULL, /* spesh */
112
    "ReentrantMutex", /* name */
113
    MVM_REPR_ID_ReentrantMutex,
114
    NULL, /* unmanaged_size */
115
    NULL, /* describe_refs */
116
};
117
118
/* Locks the mutex. */
119
1.59M
void MVM_reentrantmutex_lock(MVMThreadContext *tc, MVMReentrantMutex *rm) {
120
1.59M
    if (MVM_load(&rm->body.holder_id) == tc->thread_id) {
121
1.33M
        /* We already hold the lock; bump the count. */
122
1.33M
        MVM_incr(&rm->body.lock_count);
123
1.33M
    }
124
259k
    else {
125
259k
        /* Not holding the lock; obtain it. */
126
259k
        MVMROOT(tc, rm, {
127
259k
            MVM_gc_mark_thread_blocked(tc);
128
259k
            uv_mutex_lock(rm->body.mutex);
129
259k
            MVM_gc_mark_thread_unblocked(tc);
130
259k
        });
131
259k
        MVM_store(&rm->body.holder_id, tc->thread_id);
132
259k
        MVM_store(&rm->body.lock_count, 1);
133
259k
        tc->num_locks++;
134
259k
    }
135
1.59M
}
136
137
/* Unlocks the mutex. */
138
1.59M
void MVM_reentrantmutex_unlock(MVMThreadContext *tc, MVMReentrantMutex *rm) {
139
1.59M
    /* Ensure we hold the lock. */
140
1.59M
    if (MVM_load(&rm->body.holder_id) == tc->thread_id) {
141
1.59M
        if (MVM_decr(&rm->body.lock_count) == 1) {
142
259k
            /* Decremented the last recursion count; really unlock. */
143
259k
            MVM_store(&rm->body.holder_id, 0);
144
259k
            uv_mutex_unlock(rm->body.mutex);
145
259k
            tc->num_locks--;
146
259k
        }
147
1.59M
    }
148
0
    else {
149
0
        MVM_exception_throw_adhoc(tc, "Attempt to unlock mutex by thread not holding it");
150
0
    }
151
1.59M
}