UNREG: use __builtin___clear_cache where available
[ghc.git] / rts / StaticPtrTable.c
1 /*
2 * (c)2014 Tweag I/O
3 *
4 * The Static Pointer Table implementation.
5 *
6 * https://ghc.haskell.org/trac/ghc/wiki/StaticPointers
7 * https://ghc.haskell.org/trac/ghc/wiki/StaticPointers/ImplementationPlan
8 *
9 */
10
11 #include "StaticPtrTable.h"
12 #include "Rts.h"
13 #include "RtsUtils.h"
14 #include "Hash.h"
15 #include "Stable.h"
16
17 static HashTable * spt = NULL;
18
19 #if defined(THREADED_RTS)
20 static Mutex spt_lock;
21 #endif
22
23 /// Hash function for the SPT.
24 static int hashFingerprint(HashTable *table, StgWord64 key[2]) {
25 // Take half of the key to compute the hash.
26 return hashWord(table, (StgWord)key[1]);
27 }
28
29 /// Comparison function for the SPT.
30 static int compareFingerprint(StgWord64 ptra[2], StgWord64 ptrb[2]) {
31 return ptra[0] == ptrb[0] && ptra[1] == ptrb[1];
32 }
33
34 void hs_spt_insert_stableptr(StgWord64 key[2], StgStablePtr *entry) {
35 // hs_spt_insert is called from constructor functions, so
36 // the SPT needs to be initialized here.
37 if (spt == NULL) {
38 spt = allocHashTable_( (HashFunction *)hashFingerprint
39 , (CompareFunction *)compareFingerprint
40 );
41 #if defined(THREADED_RTS)
42 initMutex(&spt_lock);
43 #endif
44 }
45
46 ACQUIRE_LOCK(&spt_lock);
47 insertHashTable(spt, (StgWord)key, entry);
48 RELEASE_LOCK(&spt_lock);
49 }
50
51 void hs_spt_insert(StgWord64 key[2], void *spe_closure) {
52 // Cannot remove this indirection yet because getStablePtr()
53 // might return NULL, in which case hs_spt_lookup() returns NULL
54 // instead of the actual closure pointer.
55 StgStablePtr * entry = stgMallocBytes( sizeof(StgStablePtr)
56 , "hs_spt_insert: entry"
57 );
58 *entry = getStablePtr(spe_closure);
59 hs_spt_insert_stableptr(key, entry);
60 }
61
62 static void freeSptEntry(void* entry) {
63 freeStablePtr(*(StgStablePtr*)entry);
64 stgFree(entry);
65 }
66
67 void hs_spt_remove(StgWord64 key[2]) {
68 if (spt) {
69 ACQUIRE_LOCK(&spt_lock);
70 StgStablePtr* entry = removeHashTable(spt, (StgWord)key, NULL);
71 RELEASE_LOCK(&spt_lock);
72
73 if (entry)
74 freeSptEntry(entry);
75 }
76 }
77
78 StgPtr hs_spt_lookup(StgWord64 key[2]) {
79 if (spt) {
80 ACQUIRE_LOCK(&spt_lock);
81 const StgStablePtr * entry = lookupHashTable(spt, (StgWord)key);
82 const StgPtr ret = entry ? deRefStablePtr(*entry) : NULL;
83 RELEASE_LOCK(&spt_lock);
84 return ret;
85 } else
86 return NULL;
87 }
88
89 int hs_spt_keys(StgPtr keys[], int szKeys) {
90 if (spt) {
91 ACQUIRE_LOCK(&spt_lock);
92 const int ret = keysHashTable(spt, (StgWord*)keys, szKeys);
93 RELEASE_LOCK(&spt_lock);
94 return ret;
95 } else
96 return 0;
97 }
98
99 int hs_spt_key_count() {
100 return spt ? keyCountHashTable(spt) : 0;
101 }
102
103 void exitStaticPtrTable() {
104 if (spt) {
105 freeHashTable(spt, freeSptEntry);
106 spt = NULL;
107 #if defined(THREADED_RTS)
108 closeMutex(&spt_lock);
109 #endif
110 }
111 }