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