rts: Add api to pin a thread to a numa node but without fixing a capability
[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 #ifdef 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(StgWord64 key[2],void *spe_closure) {
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 #ifdef THREADED_RTS
42 initMutex(&spt_lock);
43 #endif
44 }
45
46 // Cannot remove this indirection yet because getStablePtr()
47 // might return NULL, in which case hs_spt_lookup() returns NULL
48 // instead of the actual closure pointer.
49 StgStablePtr * entry = stgMallocBytes( sizeof(StgStablePtr)
50 , "hs_spt_insert: entry"
51 );
52 *entry = getStablePtr(spe_closure);
53 ACQUIRE_LOCK(&spt_lock);
54 insertHashTable(spt, (StgWord)key, entry);
55 RELEASE_LOCK(&spt_lock);
56 }
57
58 static void freeSptEntry(void* entry) {
59 freeStablePtr(*(StgStablePtr*)entry);
60 stgFree(entry);
61 }
62
63 void hs_spt_remove(StgWord64 key[2]) {
64 if (spt) {
65 ACQUIRE_LOCK(&spt_lock);
66 StgStablePtr* entry = removeHashTable(spt, (StgWord)key, NULL);
67 RELEASE_LOCK(&spt_lock);
68
69 if (entry)
70 freeSptEntry(entry);
71 }
72 }
73
74 StgPtr hs_spt_lookup(StgWord64 key[2]) {
75 if (spt) {
76 ACQUIRE_LOCK(&spt_lock);
77 const StgStablePtr * entry = lookupHashTable(spt, (StgWord)key);
78 const StgPtr ret = entry ? deRefStablePtr(*entry) : NULL;
79 RELEASE_LOCK(&spt_lock);
80 return ret;
81 } else
82 return NULL;
83 }
84
85 int hs_spt_keys(StgPtr keys[], int szKeys) {
86 if (spt) {
87 ACQUIRE_LOCK(&spt_lock);
88 const int ret = keysHashTable(spt, (StgWord*)keys, szKeys);
89 RELEASE_LOCK(&spt_lock);
90 return ret;
91 } else
92 return 0;
93 }
94
95 int hs_spt_key_count() {
96 return spt ? keyCountHashTable(spt) : 0;
97 }
98
99 void exitStaticPtrTable() {
100 if (spt) {
101 freeHashTable(spt, freeSptEntry);
102 spt = NULL;
103 #ifdef THREADED_RTS
104 closeMutex(&spt_lock);
105 #endif
106 }
107 }