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

📄 erl_fun.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 "erl_fun.h"#include "hash.h"static Hash erts_fun_table;#include "erl_smp.h"static erts_smp_rwmtx_t erts_fun_table_lock;#define erts_fun_read_lock()	erts_smp_rwmtx_rlock(&erts_fun_table_lock)#define erts_fun_read_unlock()	erts_smp_rwmtx_runlock(&erts_fun_table_lock)#define erts_fun_write_lock()	erts_smp_rwmtx_rwlock(&erts_fun_table_lock)#define erts_fun_write_unlock()	erts_smp_rwmtx_rwunlock(&erts_fun_table_lock)#define erts_fun_init_lock()	erts_smp_rwmtx_init(&erts_fun_table_lock, \						    "fun_tab")static HashValue fun_hash(ErlFunEntry* obj);static int fun_cmp(ErlFunEntry* obj1, ErlFunEntry* obj2);static ErlFunEntry* fun_alloc(ErlFunEntry* template);static void fun_free(ErlFunEntry* obj);/* * The address field of every fun that has no loaded code will point * to unloaded_fun[]. The -1 in unloaded_fun[0] will be interpreted * as an illegal arity when attempting to call a fun. */static Eterm unloaded_fun_code[3] = {NIL, -1, 0};static Eterm* unloaded_fun = unloaded_fun_code + 2;voiderts_init_fun_table(void){    HashFunctions f;    erts_fun_init_lock();    f.hash = (H_FUN) fun_hash;    f.cmp  = (HCMP_FUN) fun_cmp;    f.alloc = (HALLOC_FUN) fun_alloc;    f.free = (HFREE_FUN) fun_free;    hash_init(ERTS_ALC_T_FUN_TABLE, &erts_fun_table, "fun_table", 16, f);}voiderts_fun_info(int to, void *to_arg){    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_fun_read_lock();    hash_info(to, to_arg, &erts_fun_table);    if (lock)	erts_fun_read_unlock();}int erts_fun_table_sz(void){    int sz;    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_fun_read_lock();    sz = hash_table_sz(&erts_fun_table);    if (lock)	erts_fun_read_unlock();    return sz;}ErlFunEntry*erts_put_fun_entry(Eterm mod, int uniq, int index){    ErlFunEntry template;    ErlFunEntry* fe;    long refc;    ASSERT(is_atom(mod));    template.old_uniq = uniq;    template.old_index = index;    template.module = mod;    erts_fun_write_lock();    fe = (ErlFunEntry *) hash_put(&erts_fun_table, (void*) &template);    sys_memset(fe->uniq, 0, sizeof(fe->uniq));    fe->index = 0;    refc = erts_refc_inctest(&fe->refc, 0);    if (refc < 2) /* New or pending delete */	erts_refc_inc(&fe->refc, 1);    erts_fun_write_unlock();    return fe;}ErlFunEntry*erts_put_fun_entry2(Eterm mod, int old_uniq, int old_index,		    byte* uniq, int index, int arity){    ErlFunEntry template;    ErlFunEntry* fe;    long refc;    ASSERT(is_atom(mod));    template.old_uniq = old_uniq;    template.old_index = old_index;    template.module = mod;    erts_fun_write_lock();    fe = (ErlFunEntry *) hash_put(&erts_fun_table, (void*) &template);    sys_memcpy(fe->uniq, uniq, sizeof(fe->uniq));    fe->index = index;    fe->arity = arity;    refc = erts_refc_inctest(&fe->refc, 0);    if (refc < 2) /* New or pending delete */	erts_refc_inc(&fe->refc, 1);    erts_fun_write_unlock();    return fe;}struct my_key {    Eterm mod;    byte* uniq;    int index;    ErlFunEntry* fe;};ErlFunEntry*erts_get_fun_entry(Eterm mod, int uniq, int index){    ErlFunEntry template;    ErlFunEntry *ret;    ASSERT(is_atom(mod));    template.old_uniq = uniq;    template.old_index = index;    template.module = mod;    erts_fun_read_lock();    ret = (ErlFunEntry *) hash_get(&erts_fun_table, (void*) &template);    if (ret) {	long refc = erts_refc_inctest(&ret->refc, 1);	if (refc < 2) /* Pending delete */	    erts_refc_inc(&ret->refc, 1);    }    erts_fun_read_unlock();    return ret;}static voiderts_erase_fun_entry_unlocked(ErlFunEntry* fe){    hash_erase(&erts_fun_table, (void *) fe);}voiderts_erase_fun_entry(ErlFunEntry* fe){    erts_fun_write_lock();#ifdef ERTS_SMP    /*     * We have to check refc again since someone might have looked up     * the fun entry and incremented refc after last check.     */    if (erts_refc_dectest(&fe->refc, -1) <= 0)#endif    {	if (fe->address != unloaded_fun)	    erl_exit(1,		     "Internal error: "		     "Invalid reference count found on #Fun<%T.%d.%d>: "		     " About to erase fun still referred by code.\n",		     fe->module, fe->old_index, fe->old_uniq);	erts_erase_fun_entry_unlocked(fe);    }    erts_fun_write_unlock();}#ifndef HYBRID /* FIND ME! */voiderts_cleanup_funs(ErlFunThing* funp){    while (funp) {	ErlFunEntry* fe = funp->fe;	if (erts_refc_dectest(&fe->refc, 0) == 0) {	    erts_erase_fun_entry(fe);	}	funp = funp->next;    }}#endifvoiderts_cleanup_funs_on_purge(Eterm* start, Eterm* end){    int limit;    HashBucket** bucket;    ErlFunEntry* to_delete = NULL;    int i;    erts_fun_write_lock();    limit = erts_fun_table.size;    bucket = erts_fun_table.bucket;    for (i = 0; i < limit; i++) {	HashBucket* b = bucket[i];	while (b) {	    ErlFunEntry* fe = (ErlFunEntry *) b;	    Eterm* addr = fe->address;	    if (start <= addr && addr < end) {		fe->address = unloaded_fun;		if (erts_refc_dectest(&fe->refc, 0) == 0) {		    fe->address = (void *) to_delete;		    to_delete = fe;		}	    }	    b = b->next;	}    }    while (to_delete != NULL) {	ErlFunEntry* next = (ErlFunEntry *) to_delete->address;	erts_erase_fun_entry_unlocked(to_delete);	to_delete = next;    }    erts_fun_write_unlock();}voiderts_dump_fun_entries(int to, void *to_arg){    int limit;    HashBucket** bucket;    int i;    int lock = !ERTS_IS_CRASH_DUMPING;    if (lock)	erts_fun_read_lock();    limit = erts_fun_table.size;    bucket = erts_fun_table.bucket;    for (i = 0; i < limit; i++) {	HashBucket* b = bucket[i];	while (b) {	    ErlFunEntry* fe = (ErlFunEntry *) b;	    erts_print(to, to_arg, "=fun\n");	    erts_print(to, to_arg, "Module: %T\n", fe->module);	    erts_print(to, to_arg, "Uniq: %d\n", fe->old_uniq);	    erts_print(to, to_arg, "Index: %d\n",fe->old_index);	    erts_print(to, to_arg, "Address: %p\n", fe->address);#ifdef HIPE	    erts_print(to, to_arg, "Native_address: %p\n", fe->native_address);#endif	    erts_print(to, to_arg, "Refc: %d\n", erts_refc_read(&fe->refc, 1));	    b = b->next;	}    }    if (lock)	erts_fun_read_unlock();}static HashValuefun_hash(ErlFunEntry* obj){    return (HashValue) (obj->old_uniq ^ obj->old_index ^ atom_val(obj->module));}static intfun_cmp(ErlFunEntry* obj1, ErlFunEntry* obj2){    return !(obj1->module == obj2->module && 	     obj1->old_uniq == obj2->old_uniq &&	     obj1->old_index == obj2->old_index);}static ErlFunEntry*fun_alloc(ErlFunEntry* template){    ErlFunEntry* obj = (ErlFunEntry *) erts_alloc(ERTS_ALC_T_FUN_ENTRY,						  sizeof(ErlFunEntry));    obj->old_uniq = template->old_uniq;    obj->old_index = template->old_index;    obj->module = template->module;    erts_refc_init(&obj->refc, -1);    obj->address = unloaded_fun;#ifdef HIPE    obj->native_address = NULL;#endif    return obj;}static voidfun_free(ErlFunEntry* obj){    erts_free(ERTS_ALC_T_FUN_ENTRY, (void *) obj);}

⌨️ 快捷键说明

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