⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 export.c

📁 OTP是开放电信平台的简称
💻 C
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "sys.h"#include "erl_vm.h"#include "global.h"#include "export.h"#include "hash.h"#define EXPORT_SIZE   500#define EXPORT_LIMIT  (64*1024)#define EXPORT_HASH(m,f,a) ((m)*(f)+(a))static IndexTable export_table;	/* Not locked. */static Hash secondary_export_table; /* Locked. */#include "erl_smp.h"static erts_smp_rwmtx_t export_table_lock; /* Locks the secondary export table. */#define export_read_lock()	erts_smp_rwmtx_rlock(&export_table_lock)#define export_read_unlock()	erts_smp_rwmtx_runlock(&export_table_lock)#define export_write_lock()	erts_smp_rwmtx_rwlock(&export_table_lock)#define export_write_unlock()	erts_smp_rwmtx_rwunlock(&export_table_lock)#define export_init_lock()	erts_smp_rwmtx_init(&export_table_lock, \						    "export_tab")extern Eterm* em_call_error_handler;extern Uint* em_call_traced_function;voidexport_info(int to, void *to_arg){#ifdef ERTS_SMP    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	export_read_lock();#endif    index_info(to, to_arg, &export_table);    hash_info(to, to_arg, &secondary_export_table);#ifdef ERTS_SMP    if (lock)	export_read_unlock();#endif}static HashValueexport_hash(Export* x){    return EXPORT_HASH(x->code[0], x->code[1], x->code[2]);}static intexport_cmp(Export* tmpl, Export* obj){    return !(tmpl->code[0] == obj->code[0] &&	     tmpl->code[1] == obj->code[1] &&	     tmpl->code[2] == obj->code[2]);}static Export*export_alloc(Export* tmpl){    Export* obj = (Export*) erts_alloc(ERTS_ALC_T_EXPORT, sizeof(Export));        obj->fake_op_func_info_for_hipe[0] = 0;    obj->fake_op_func_info_for_hipe[1] = 0;    obj->code[0] = tmpl->code[0];    obj->code[1] = tmpl->code[1];    obj->code[2] = tmpl->code[2];    obj->slot.index = -1;    obj->address = obj->code+3;    obj->code[3] = (Eterm) em_call_error_handler;    obj->code[4] = 0;    obj->match_prog_set = NULL;    return obj;}static void export_free(Export* obj){    erts_free(ERTS_ALC_T_EXPORT,  (void*) obj);}voidinit_export_table(void){    HashFunctions f;    export_init_lock();    f.hash = (H_FUN) export_hash;    f.cmp  = (HCMP_FUN) export_cmp;    f.alloc = (HALLOC_FUN) export_alloc;    f.free = (HFREE_FUN) export_free;    erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_table, "export_list",		    EXPORT_SIZE, EXPORT_LIMIT, f);    hash_init(ERTS_ALC_T_EXPORT_TABLE, &secondary_export_table,	      "secondary_export_table", 50, f);}/* * Return a pointer to the export entry for the given function, * or NULL otherwise.  Notes: * * 1) BIFs have export entries and can be called through *    a wrapper in the export entry. * 2) Functions referenced by a loaded module, but not yet loaded *    also have export entries.  The export entry contains *    a wrapper which invokes the error handler if a function is *    called through such an export entry. * 3) This function is suitable for the implementation of erlang:apply/3. */Export*erts_find_export_entry(Eterm m, Eterm f, unsigned int a){    HashValue hval = EXPORT_HASH(m, f, a);    int ix;    HashBucket* b;    ix = hval % export_table.htable.size;    b = export_table.htable.bucket[ix];    /*     * Note: We have inlined the code from hash.c for speed.     */	    while (b != (HashBucket*) 0) {	Export* ep = (Export *) b;	if (ep->code[0] == m && ep->code[1] == f && ep->code[2] == a) {	    break;	}	b = b->next;    }    return (Export*)b;}/* * Find the export entry for a loaded function. * Returns a NULL pointer if the given function is not loaded, or * a pointer to the export entry. * * Note: This function never returns export entries for BIFs * or functions which are not yet loaded.  This makes it suitable * for use by the erlang:function_exported/3 BIF or whenever you * cannot depend on the error_handler. */Export*erts_find_function(Eterm m, Eterm f, unsigned int a){    Export e;    Export* ep;    e.code[0] = m;    e.code[1] = f;    e.code[2] = a;    ep = hash_get(&export_table.htable, (void*) &e);    if (ep != NULL && ep->address == ep->code+3 &&	ep->code[3] != (Uint) em_call_traced_function) {	ep = NULL;    }    return ep;}/* * Returns a pointer to an existing export entry for a MFA, * or creates a new one and returns the pointer. * * This function provides unlocked write access to the main export * table. It should only be used during start up or when * all other threads are blocked. */Export*erts_export_put(Eterm mod, Eterm func, unsigned int arity){    Export e;    int ix;    ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));    ASSERT(is_atom(mod));    ASSERT(is_atom(func));    e.code[0] = mod;    e.code[1] = func;    e.code[2] = arity;    ix = index_put(&export_table, (void*) &e);    return (Export*) erts_index_lookup(&export_table, ix);}/* * Find the existing export entry for M:F/A. Failing that, create a stub * export entry (making a call through it will cause the error_handler to * be called). * * Stub export entries will be placed in the secondary export table. * erts_export_consolidate() will move all stub export entries into the * main export table (will be done the next time code is loaded). */Export*erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity){    Export e;    Export* ep;        ASSERT(is_atom(mod));    ASSERT(is_atom(func));        e.code[0] = mod;    e.code[1] = func;    e.code[2] = arity;    ep = erts_find_export_entry(mod, func, arity);    if (ep == 0) {	/*	 * The code is not loaded (yet). Put the export in the secondary	 * export table, to avoid having to lock the main export table.	 */	export_write_lock();	ep = (Export *) hash_put(&secondary_export_table, (void*) &e);	export_write_unlock();    }    return ep;}/* * To be called before loading code (with other threads blocked). * This function will move all export entries from the secondary * export table into the primary. */voiderts_export_consolidate(void){#ifdef DEBUG    HashInfo hi;#endif    ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_is_system_blocked(0));    export_write_lock();    erts_index_merge(&secondary_export_table, &export_table);    erts_hash_merge(&secondary_export_table, &export_table.htable);    export_write_unlock();#ifdef DEBUG    hash_get_info(&hi, &export_table.htable);    ASSERT(export_table.entries == hi.objs);#endif}Export *export_list(int i){    return (Export*) erts_index_lookup(&export_table, i);}int export_list_size(void){    return export_table.entries;}int export_table_sz(void){    return index_table_sz(&export_table);}Export *export_get(Export *e){    return hash_get(&export_table.htable, e);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -