1 /*
2 * Copyright (c) 2021 Calvin Rose
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22
23 #ifndef JANET_AMALG
24 #include "features.h"
25 #include <janet.h>
26 #include "gc.h"
27 #include "state.h"
28 #ifdef JANET_EV
29 #ifdef JANET_WINDOWS
30 #include <windows.h>
31 #endif
32 #endif
33 #endif
34
35 /* Create new userdata */
janet_abstract_begin(const JanetAbstractType * atype,size_t size)36 void *janet_abstract_begin(const JanetAbstractType *atype, size_t size) {
37 JanetAbstractHead *header = janet_gcalloc(JANET_MEMORY_NONE,
38 sizeof(JanetAbstractHead) + size);
39 header->size = size;
40 header->type = atype;
41 return (void *) & (header->data);
42 }
43
janet_abstract_end(void * x)44 void *janet_abstract_end(void *x) {
45 janet_gc_settype((void *)(janet_abstract_head(x)), JANET_MEMORY_ABSTRACT);
46 return x;
47 }
48
janet_abstract(const JanetAbstractType * atype,size_t size)49 void *janet_abstract(const JanetAbstractType *atype, size_t size) {
50 return janet_abstract_end(janet_abstract_begin(atype, size));
51 }
52
53 #ifdef JANET_EV
54
55 /*
56 * Threaded abstracts
57 */
58
janet_abstract_begin_threaded(const JanetAbstractType * atype,size_t size)59 void *janet_abstract_begin_threaded(const JanetAbstractType *atype, size_t size) {
60 JanetAbstractHead *header = janet_malloc(sizeof(JanetAbstractHead) + size);
61 if (NULL == header) {
62 JANET_OUT_OF_MEMORY;
63 }
64 janet_vm.next_collection += size + sizeof(JanetAbstractHead);
65 header->gc.flags = JANET_MEMORY_THREADED_ABSTRACT;
66 header->gc.data.next = NULL; /* Clear memory for address sanitizers */
67 header->gc.data.refcount = 1;
68 header->size = size;
69 header->type = atype;
70 void *abstract = (void *) & (header->data);
71 janet_table_put(&janet_vm.threaded_abstracts, janet_wrap_abstract(abstract), janet_wrap_false());
72 return abstract;
73 }
74
janet_abstract_end_threaded(void * x)75 void *janet_abstract_end_threaded(void *x) {
76 janet_gc_settype((void *)(janet_abstract_head(x)), JANET_MEMORY_THREADED_ABSTRACT);
77 return x;
78 }
79
janet_abstract_threaded(const JanetAbstractType * atype,size_t size)80 void *janet_abstract_threaded(const JanetAbstractType *atype, size_t size) {
81 return janet_abstract_end_threaded(janet_abstract_begin_threaded(atype, size));
82 }
83
84 /* Refcounting primitives and sync primitives */
85
86 #ifdef JANET_WINDOWS
87
janet_incref(JanetAbstractHead * ab)88 static int32_t janet_incref(JanetAbstractHead *ab) {
89 return InterlockedIncrement(&ab->gc.data.refcount);
90 }
91
janet_decref(JanetAbstractHead * ab)92 static int32_t janet_decref(JanetAbstractHead *ab) {
93 return InterlockedDecrement(&ab->gc.data.refcount);
94 }
95
janet_os_mutex_init(JanetOSMutex * mutex)96 void janet_os_mutex_init(JanetOSMutex *mutex) {
97 InitializeCriticalSection((CRITICAL_SECTION *) mutex);
98 }
99
janet_os_mutex_deinit(JanetOSMutex * mutex)100 void janet_os_mutex_deinit(JanetOSMutex *mutex) {
101 DeleteCriticalSection((CRITICAL_SECTION *) mutex);
102 }
103
janet_os_mutex_lock(JanetOSMutex * mutex)104 void janet_os_mutex_lock(JanetOSMutex *mutex) {
105 EnterCriticalSection((CRITICAL_SECTION *) mutex);
106 }
107
janet_os_mutex_unlock(JanetOSMutex * mutex)108 void janet_os_mutex_unlock(JanetOSMutex *mutex) {
109 LeaveCriticalSection((CRITICAL_SECTION *) mutex);
110 }
111
112 #else
113
janet_incref(JanetAbstractHead * ab)114 static int32_t janet_incref(JanetAbstractHead *ab) {
115 return __atomic_add_fetch(&ab->gc.data.refcount, 1, __ATOMIC_RELAXED);
116 }
117
janet_decref(JanetAbstractHead * ab)118 static int32_t janet_decref(JanetAbstractHead *ab) {
119 return __atomic_add_fetch(&ab->gc.data.refcount, -1, __ATOMIC_RELAXED);
120 }
121
janet_os_mutex_init(JanetOSMutex * mutex)122 void janet_os_mutex_init(JanetOSMutex *mutex) {
123 pthread_mutex_init(mutex, NULL);
124 }
125
janet_os_mutex_deinit(JanetOSMutex * mutex)126 void janet_os_mutex_deinit(JanetOSMutex *mutex) {
127 pthread_mutex_destroy(mutex);
128 }
129
janet_os_mutex_lock(JanetOSMutex * mutex)130 void janet_os_mutex_lock(JanetOSMutex *mutex) {
131 pthread_mutex_lock(mutex);
132 }
133
janet_os_mutex_unlock(JanetOSMutex * mutex)134 void janet_os_mutex_unlock(JanetOSMutex *mutex) {
135 pthread_mutex_unlock(mutex);
136 }
137
138 #endif
139
janet_abstract_incref(void * abst)140 int32_t janet_abstract_incref(void *abst) {
141 return janet_incref(janet_abstract_head(abst));
142 }
143
janet_abstract_decref(void * abst)144 int32_t janet_abstract_decref(void *abst) {
145 return janet_decref(janet_abstract_head(abst));
146 }
147
148 #endif
149