29
29
#define EXPORT_SIZE 500
30
30
#define EXPORT_LIMIT (64*1024)
31
#define EXPORT_RATE 100
33
32
#define EXPORT_HASH(m,f,a) ((m)*(f)+(a))
34
IndexTable export_table;
34
static IndexTable export_table; /* Not locked. */
35
static Hash secondary_export_table; /* Locked. */
39
static erts_smp_rwmtx_t export_table_lock; /* Locks the secondary export table. */
41
#define export_read_lock() erts_smp_rwmtx_rlock(&export_table_lock)
42
#define export_read_unlock() erts_smp_rwmtx_runlock(&export_table_lock)
43
#define export_write_lock() erts_smp_rwmtx_rwlock(&export_table_lock)
44
#define export_write_unlock() erts_smp_rwmtx_rwunlock(&export_table_lock)
45
#define export_init_lock() erts_smp_rwmtx_init(&export_table_lock, \
36
48
extern Eterm* em_call_error_handler;
37
49
extern Uint* em_call_traced_function;
52
export_info(int to, void *to_arg)
42
index_info(to, &export_table);
55
int lock = !ERTS_IS_CRASH_DUMPING;
59
index_info(to, to_arg, &export_table);
60
hash_info(to, to_arg, &secondary_export_table);
92
115
f.hash = (H_FUN) export_hash;
93
116
f.cmp = (HCMP_FUN) export_cmp;
94
117
f.alloc = (HALLOC_FUN) export_alloc;
95
118
f.free = (HFREE_FUN) export_free;
97
index_init(ERTS_ALC_T_EXPORT_TABLE, &export_table, "export_list",
98
EXPORT_SIZE, EXPORT_LIMIT, EXPORT_RATE, f);
120
erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_table, "export_list",
121
EXPORT_SIZE, EXPORT_LIMIT, f);
122
hash_init(ERTS_ALC_T_EXPORT_TABLE, &secondary_export_table,
123
"secondary_export_table", 50, f);
115
140
erts_find_export_entry(Eterm m, Eterm f, unsigned int a)
117
142
HashValue hval = EXPORT_HASH(m, f, a);
118
int ix = hval % export_table.htable.size;
119
HashBucket* b = export_table.htable.bucket[ix];
146
ix = hval % export_table.htable.size;
147
b = export_table.htable.bucket[ix];
122
150
* Note: We have inlined the code from hash.c for speed.
157
if ((ep = hash_get(&export_table.htable, (void*) &e)) == NULL) {
160
if (ep->address == ep->code+3 && ep->code[3] != (Uint) em_call_traced_function) {
185
ep = hash_get(&export_table.htable, (void*) &e);
186
if (ep != NULL && ep->address == ep->code+3 &&
187
ep->code[3] != (Uint) em_call_traced_function) {
168
194
* Returns a pointer to an existing export entry for a MFA,
169
195
* or creates a new one and returns the pointer.
197
* This function provides unlocked write access to the main export
198
* table. It should only be used during start up or when
199
* all other threads are blocked.
173
203
erts_export_put(Eterm mod, Eterm func, unsigned int arity)
177
ASSERT(is_atom(mod));
178
ASSERT(is_atom(func));
180
e.fake_op_func_info_for_hipe[0] = 0;
181
e.fake_op_func_info_for_hipe[1] = 0;
185
e.address = e.code+3;
187
e.match_prog_set = NULL;
188
return export_list(index_put(&export_table, (void*) &e));
208
ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
209
ASSERT(is_atom(mod));
210
ASSERT(is_atom(func));
214
ix = index_put(&export_table, (void*) &e);
215
return (Export*) erts_index_lookup(&export_table, ix);
219
* Find the existing export entry for M:F/A. Failing that, create a stub
220
* export entry (making a call through it will cause the error_handler to
223
* Stub export entries will be placed in the secondary export table.
224
* erts_export_consolidate() will move all stub export entries into the
225
* main export table (will be done the next time code is loaded).
229
erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity)
234
ASSERT(is_atom(mod));
235
ASSERT(is_atom(func));
240
ep = erts_find_export_entry(mod, func, arity);
243
* The code is not loaded (yet). Put the export in the secondary
244
* export table, to avoid having to lock the main export table.
247
ep = (Export *) hash_put(&secondary_export_table, (void*) &e);
248
export_write_unlock();
254
* To be called before loading code (with other threads blocked).
255
* This function will move all export entries from the secondary
256
* export table into the primary.
259
erts_export_consolidate(void)
265
ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));
268
erts_index_merge(&secondary_export_table, &export_table);
269
erts_hash_merge(&secondary_export_table, &export_table.htable);
270
export_write_unlock();
272
hash_get_info(&hi, &export_table.htable);
273
ASSERT(export_table.entries == hi.objs);
277
Export *export_list(int i)
279
return (Export*) erts_index_lookup(&export_table, i);
282
int export_list_size(void)
284
return export_table.entries;
287
int export_table_sz(void)
289
return index_table_sz(&export_table);
292
Export *export_get(Export *e)
294
return hash_get(&export_table.htable, e);