コード例 #1
0
ファイル: erl_node_tables.c プロジェクト: 3112517927/otp
void erts_init_node_tables(int dd_sec)
{
    erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
    HashFunctions f;
    ErlNode node_tmpl;

    if (dd_sec == ERTS_NODE_TAB_DELAY_GC_INFINITY)
	node_tab_delete_delay = (ErtsMonotonicTime) -1;
    else
	node_tab_delete_delay = ((ErtsMonotonicTime) dd_sec)*1000;

    orig_node_tab_delete_delay = node_tab_delete_delay;

    rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
    rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;

    erts_smp_rwmtx_init_opt(&erts_node_table_rwmtx, &rwmtx_opt, "node_table");
    erts_smp_rwmtx_init_opt(&erts_dist_table_rwmtx, &rwmtx_opt, "dist_table");

    f.hash       = (H_FUN)		dist_table_hash;
    f.cmp        = (HCMP_FUN)		dist_table_cmp;
    f.alloc      = (HALLOC_FUN)		dist_table_alloc;
    f.free       = (HFREE_FUN)		dist_table_free;
    f.meta_alloc = (HMALLOC_FUN) 	erts_alloc;
    f.meta_free  = (HMFREE_FUN) 	erts_free;
    f.meta_print = (HMPRINT_FUN) 	erts_print;
    hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f);

    f.hash  = (H_FUN)      			node_table_hash;
    f.cmp   = (HCMP_FUN)   			node_table_cmp;
    f.alloc = (HALLOC_FUN) 			node_table_alloc;
    f.free  = (HFREE_FUN)  			node_table_free;
    hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f);

    erts_hidden_dist_entries				= NULL;
    erts_visible_dist_entries				= NULL;
    erts_not_connected_dist_entries			= NULL;
    erts_no_of_hidden_dist_entries			= 0;
    erts_no_of_visible_dist_entries			= 0;
    erts_no_of_not_connected_dist_entries		= 0;

    node_tmpl.sysname = am_Noname;
    node_tmpl.creation = 0;
    erts_this_node = hash_put(&erts_node_table, &node_tmpl);
     /* +1 for erts_this_node */
    erts_refc_init(&erts_this_node->refc, 1);

    ASSERT(erts_this_node->dist_entry != NULL);
    erts_this_dist_entry = erts_this_node->dist_entry;
    /* +1 for erts_this_dist_entry */
    /* +1 for erts_this_node->dist_entry */
    erts_refc_init(&erts_this_dist_entry->refc, 2);


    erts_this_node_sysname = erts_this_node_sysname_BUFFER;
    erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
                  "%T", erts_this_node->sysname);

    references_atoms_need_init = 1;
}
コード例 #2
0
ファイル: erl_bif_ddll.c プロジェクト: aronisstav/otp
static int load_driver_entry(DE_Handle **dhp, char *path, char *name)
{
    int res;
    DE_Handle *dh = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sizeof(DE_Handle));

    assert_drv_list_rwlocked();

    dh->handle = NULL;
    dh->procs = NULL;
    erts_atomic32_init_nob(&dh->port_count, 0);
    erts_refc_init(&(dh->refc), (erts_aint_t) 0);
    dh->status = -1;
    dh->reload_full_path = NULL;
    dh->reload_driver_name = NULL;
    dh->reload_flags = 0;
    dh->full_path = NULL;
    dh->flags = 0;

    if ((res = do_load_driver_entry(dh, path, name)) != ERL_DE_NO_ERROR) {
	erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh);
	dh = NULL;
    }
    *dhp = dh;
    return res;
}
コード例 #3
0
ファイル: erl_node_tables.c プロジェクト: 3112517927/otp
static void*
dist_table_alloc(void *dep_tmpl)
{
    Eterm chnl_nr;
    Eterm sysname;
    DistEntry *dep;
    erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
    rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;

    sysname = ((DistEntry *) dep_tmpl)->sysname;
    chnl_nr = make_small((Uint) atom_val(sysname));
    dep = (DistEntry *) erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));

    dist_entries++;

    dep->prev				= NULL;
    erts_refc_init(&dep->refc, -1);
    erts_smp_rwmtx_init_opt_x(&dep->rwmtx, &rwmtx_opt, "dist_entry", chnl_nr);
    dep->sysname			= sysname;
    dep->cid				= NIL;
    dep->connection_id			= 0;
    dep->status				= 0;
    dep->flags				= 0;
    dep->version			= 0;

    erts_smp_mtx_init_x(&dep->lnk_mtx, "dist_entry_links", chnl_nr);
    dep->node_links			= NULL;
    dep->nlinks				= NULL;
    dep->monitors			= NULL;

    erts_smp_mtx_init_x(&dep->qlock, "dist_entry_out_queue", chnl_nr);
    dep->qflgs				= 0;
    dep->qsize				= 0;
    dep->out_queue.first		= NULL;
    dep->out_queue.last			= NULL;
    dep->suspended			= NULL;

    dep->finalized_out_queue.first	= NULL;
    dep->finalized_out_queue.last	= NULL;

    erts_smp_atomic_init_nob(&dep->dist_cmd_scheduled, 0);
    erts_port_task_handle_init(&dep->dist_cmd);
    dep->send				= NULL;
    dep->cache				= NULL;

    /* Link in */

    /* All new dist entries are "not connected".
     * erts_this_dist_entry is also always included among "not connected"
     */
    dep->next = erts_not_connected_dist_entries;
    if(erts_not_connected_dist_entries) {
	ASSERT(erts_not_connected_dist_entries->prev == NULL);
	erts_not_connected_dist_entries->prev = dep;
    }
    erts_not_connected_dist_entries = dep;
    erts_no_of_not_connected_dist_entries++;

    return (void *) dep;
}
コード例 #4
0
ファイル: erl_nif.c プロジェクト: a5an0/otp
ErlNifResourceType*
enif_open_resource_type(ErlNifEnv* env,
			const char* module_str, 
			const char* name_str, 
			ErlNifResourceDtor* dtor,
			ErlNifResourceFlags flags,
			ErlNifResourceFlags* tried)
{
    ErlNifResourceType* type = NULL;
    ErlNifResourceFlags op = flags;
    Eterm module_am, name_am;

    ASSERT(erts_smp_thr_progress_is_blocking());
    ASSERT(module_str == NULL); /* for now... */
    module_am = make_atom(env->mod_nif->mod->module);
    name_am = enif_make_atom(env, name_str);

    type = find_resource_type(module_am, name_am);
    if (type == NULL) {
	if (flags & ERL_NIF_RT_CREATE) {
	    type = erts_alloc(ERTS_ALC_T_NIF,
			      sizeof(struct enif_resource_type_t)); 
	    type->dtor = dtor;
	    type->module = module_am;
	    type->name = name_am;
	    erts_refc_init(&type->refc, 1);
	    type->owner = env->mod_nif;
	    type->prev = &resource_type_list;
	    type->next = resource_type_list.next;
	    type->next->prev = type;
	    type->prev->next = type;
	    op = ERL_NIF_RT_CREATE;
	}
    }
    else {
	if (flags & ERL_NIF_RT_TAKEOVER) {	
	    steal_resource_type(type);
	    op = ERL_NIF_RT_TAKEOVER;
	}
	else {
	    type = NULL;
	}
    }
    if (type != NULL) {
	type->owner = env->mod_nif;
	type->dtor = dtor;
	if (type->dtor != NULL) {
	    erts_refc_inc(&type->owner->rt_dtor_cnt, 1);
	}
	erts_refc_inc(&type->owner->rt_cnt, 1);    
    }
    if (tried != NULL) {
	*tried = op;
    }
    return type;
}
コード例 #5
0
ファイル: erl_nif.c プロジェクト: a5an0/otp
void* enif_alloc_resource(ErlNifResourceType* type, size_t size)
{
    Binary* bin = erts_create_magic_binary(SIZEOF_ErlNifResource(size), &nif_resource_dtor);
    ErlNifResource* resource = ERTS_MAGIC_BIN_DATA(bin);
    resource->type = type;
    erts_refc_inc(&bin->refc, 1);
#ifdef DEBUG
    erts_refc_init(&resource->nif_refc, 1);
#endif
    erts_refc_inc(&resource->type->refc, 2);
    return resource->data;
}
コード例 #6
0
ファイル: erl_node_tables.c プロジェクト: 3112517927/otp
static void*
node_table_alloc(void *venp_tmpl)
{
    ErlNode *enp;

    enp = (ErlNode *) erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));

    node_entries++;

    erts_refc_init(&enp->refc, -1);
    enp->creation = ((ErlNode *) venp_tmpl)->creation;
    enp->sysname = ((ErlNode *) venp_tmpl)->sysname;
    enp->dist_entry = erts_find_or_insert_dist_entry(((ErlNode *) venp_tmpl)->sysname);

    return (void *) enp;
}
コード例 #7
0
ファイル: erl_nif.c プロジェクト: a5an0/otp
int enif_alloc_binary(size_t size, ErlNifBinary* bin)
{
    Binary* refbin;

    refbin = erts_bin_drv_alloc_fnf(size); /* BUGBUG: alloc type? */
    if (refbin == NULL) {
	return 0; /* The NIF must take action */
    }
    refbin->flags = BIN_FLAG_DRV; /* BUGBUG: Flag? */
    erts_refc_init(&refbin->refc, 1);
    refbin->orig_size = (long) size;

    bin->size = size;
    bin->data = (unsigned char*) refbin->orig_bytes;
    bin->bin_term = THE_NON_VALUE;
    bin->ref_bin = refbin;
    return 1;
}
コード例 #8
0
ファイル: erl_io_queue.c プロジェクト: crownedgrouse/otp
static ErtsIOQBinary *alloc_binary(Uint size, char *source, void **iov_base, int driver)
{
    if (driver) {
        ErlDrvBinary *bin = driver_alloc_binary(size);
        if (!bin) return NULL;
        sys_memcpy(bin->orig_bytes, source, size);
        *iov_base = bin->orig_bytes;
        return (ErtsIOQBinary *)bin;
    } else {
        /* This clause can be triggered in enif_ioq_enq_binary is used */
        Binary *bin = erts_bin_nrml_alloc(size);
        if (!bin) return NULL;
        erts_refc_init(&bin->intern.refc, 1);
        sys_memcpy(bin->orig_bytes, source, size);
        *iov_base = bin->orig_bytes;
        return (ErtsIOQBinary *)bin;
    }
}
コード例 #9
0
ファイル: erl_node_tables.c プロジェクト: ask/erlang-otp
static void*
dist_table_alloc(void *dep_tmpl)
{
    DistEntry *dep;

    if(((DistEntry *) dep_tmpl) == erts_this_dist_entry)
	return dep_tmpl;

    dep = (DistEntry *) erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));

    dist_entries++;

    dep->prev       = NULL;
    erts_refc_init(&dep->refc, -1);
    dep->sysname    = ((DistEntry *) dep_tmpl)->sysname;
    dep->cid        = NIL;
    dep->nlinks     = NULL;
    dep->node_links = NULL;
    dep->monitors   = NULL;
    dep->status     = 0;
    dep->flags      = 0;
    dep->cache      = NULL;
    dep->version    = 0;
#ifdef ERTS_SMP
    dep->mtxp       = &dist_entry_mutexes[(atom_val(dep->sysname)
					   % ERTS_NO_OF_DIST_ENTRY_MUTEXES)];
#endif

    /* Link in */

    /* All new dist entries are "not connected" */
    dep->next = erts_not_connected_dist_entries;
    if(erts_not_connected_dist_entries) {
	ASSERT(erts_not_connected_dist_entries->prev == NULL);
	erts_not_connected_dist_entries->prev = dep;
    }
    erts_not_connected_dist_entries = dep;
    erts_no_of_not_connected_dist_entries++;

    return (void *) dep;
}
コード例 #10
0
ファイル: slave_refc.c プロジェクト: margnus1/otp
void
erts_slave_serve_refc(struct master_command_refc *cmd)
{
    switch (cmd->op) {
    case MASTER_REFC_OP_INIT:
	erts_refc_init(cmd->refcp, cmd->arg);
	break;
    case MASTER_REFC_OP_INC:
	erts_refc_inc(cmd->refcp, cmd->min_val);
	break;
    case MASTER_REFC_OP_DEC:
	erts_refc_dec(cmd->refcp, cmd->min_val);
	break;
    case MASTER_REFC_OP_ADD:
	erts_refc_add(cmd->refcp, cmd->arg, cmd->min_val);
	break;
    case MASTER_REFC_OP_DECFREE:
	erts_refc_decfree(cmd->refcp, cmd->min_val, cmd->kind, cmd->objp);
	break;
    default:
	erl_exit(1, "Unexpected op %d in erts_slave_serve_refc", cmd->op);
    }
}
コード例 #11
0
ファイル: erl_bif_ddll.c プロジェクト: aronisstav/otp
static void first_ddll_reference(DE_Handle *dh) 
{
    assert_drv_list_rwlocked();
    erts_refc_init(&(dh->refc),1);
}
コード例 #12
0
ファイル: erl_node_tables.c プロジェクト: ask/erlang-otp
void erts_init_node_tables(void)
{
    HashFunctions f;

    f.hash  = (H_FUN)			dist_table_hash;
    f.cmp   = (HCMP_FUN)		dist_table_cmp;
    f.alloc = (HALLOC_FUN)		dist_table_alloc;
    f.free  = (HFREE_FUN)		dist_table_free;

    erts_this_dist_entry = erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));
    dist_entries = 1;

    hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f);

    erts_hidden_dist_entries			= NULL;
    erts_visible_dist_entries			= NULL;
    erts_not_connected_dist_entries		= NULL;
    erts_no_of_hidden_dist_entries		= 0;
    erts_no_of_visible_dist_entries		= 0;
    erts_no_of_not_connected_dist_entries	= 0;

    erts_this_dist_entry->next			= NULL;
    erts_this_dist_entry->prev			= NULL;
    erts_refc_init(&erts_this_dist_entry->refc, 1); /* erts_this_node */
    erts_this_dist_entry->sysname		= am_Noname;
    erts_this_dist_entry->cid			= NIL;
    erts_this_dist_entry->node_links		= NULL;
    erts_this_dist_entry->nlinks		= NULL;
    erts_this_dist_entry->monitors		= NULL;
    erts_this_dist_entry->status		= 0;
    erts_this_dist_entry->flags			= 0;
    erts_this_dist_entry->cache			= NULL;
    erts_this_dist_entry->version		= 0;

    (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);

    f.hash  = (H_FUN)      			node_table_hash;
    f.cmp   = (HCMP_FUN)   			node_table_cmp;
    f.alloc = (HALLOC_FUN) 			node_table_alloc;
    f.free  = (HFREE_FUN)  			node_table_free;

    hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f);

    erts_this_node = erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));
    node_entries = 1;

    erts_refc_init(&erts_this_node->refc, 1); /* The system itself */
    erts_this_node->sysname			= am_Noname;
    erts_this_node->creation			= 0;
    erts_this_node->dist_entry			= erts_this_dist_entry;

    (void) hash_put(&erts_node_table, (void *) erts_this_node);

#ifdef ERTS_SMP
    {
	int i;
	for (i = 0; i < ERTS_NO_OF_DIST_ENTRY_MUTEXES; i++) {
#ifdef ERTS_ENABLE_LOCK_COUNT
	    erts_smp_mtx_init_x(&dist_entry_mutexes[i], "dist_entry", make_small(i));
#else
	    erts_smp_mtx_init(&dist_entry_mutexes[i], "dist_entry");
#endif /*ERTS_ENABLE_LOCK_COUNT*/
	}
	erts_this_dist_entry->mtxp = &dist_entry_mutexes[0];
	erts_smp_mtx_init(&erts_node_table_mtx, "node_table");
	erts_smp_mtx_init(&erts_dist_table_mtx, "dist_table");
    }
#endif

    references_atoms_need_init = 1;
}
コード例 #13
0
ファイル: erl_nif.c プロジェクト: a5an0/otp
BIF_RETTYPE load_nif_2(BIF_ALIST_2)
{
    static const char bad_lib[] = "bad_lib";
    static const char reload[] = "reload";
    static const char upgrade[] = "upgrade";
    char* lib_name = NULL;
    void* handle = NULL;
    void* init_func;
    ErlNifEntry* entry = NULL;
    ErlNifEnv env;
    int len, i, err;
    Module* mod;
    Eterm mod_atom;
    Eterm f_atom;
    BeamInstr* caller;
    ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT;
    Eterm ret = am_ok;
    int veto;
    struct erl_module_nif* lib = NULL;

    len = list_length(BIF_ARG_1);
    if (len < 0) {
	BIF_ERROR(BIF_P, BADARG);
    }
    lib_name = (char *) erts_alloc(ERTS_ALC_T_TMP, len + 1);

    if (intlist_to_buf(BIF_ARG_1, lib_name, len) != len) {
	erts_free(ERTS_ALC_T_TMP, lib_name);
	BIF_ERROR(BIF_P, BADARG);
    }
    lib_name[len] = '\0';

    /* Block system (is this the right place to do it?) */
    erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_smp_thr_progress_block();

    /* Find calling module */
    ASSERT(BIF_P->current != NULL);
    ASSERT(BIF_P->current[0] == am_erlang
	   && BIF_P->current[1] == am_load_nif 
	   && BIF_P->current[2] == 2);
    caller = find_function_from_pc(BIF_P->cp);
    ASSERT(caller != NULL);
    mod_atom = caller[0];
    ASSERT(is_atom(mod_atom));
    mod=erts_get_module(mod_atom);
    ASSERT(mod != NULL);

    if (!in_area(caller, mod->code, mod->code_length)) {
	ASSERT(in_area(caller, mod->old_code, mod->old_code_length));

	ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
			     "module '%T' not allowed", mod_atom);
    }    
    else if ((err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
	const char slogan[] = "Failed to load NIF library";
	if (strstr(errdesc.str, lib_name) != NULL) {
	    ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str);
	}
	else {
	    ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str);
	}
    }
    else if (erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
	ret  = load_nif_error(BIF_P, bad_lib, "Failed to find library init"
			      " function: '%s'", errdesc.str);
	
    }
    else if ((add_taint(mod_atom),
	      (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) {
	ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful");
    }
    else if (entry->major != ERL_NIF_MAJOR_VERSION
	     || entry->minor > ERL_NIF_MINOR_VERSION) {
	
	ret = load_nif_error(BIF_P, bad_lib, "Library version (%d.%d) not compatible (with %d.%d).",
			     entry->major, entry->minor, ERL_NIF_MAJOR_VERSION, ERL_NIF_MINOR_VERSION);
    }   
    else if (entry->minor >= 1
	     && sys_strcmp(entry->vm_variant, ERL_NIF_VM_VARIANT) != 0) {
	ret = load_nif_error(BIF_P, bad_lib, "Library (%s) not compiled for "
			     "this vm variant (%s).",
			     entry->vm_variant, ERL_NIF_VM_VARIANT);
    }
    else if (!erts_is_atom_str((char*)entry->name, mod_atom)) {
	ret = load_nif_error(BIF_P, bad_lib, "Library module name '%s' does not"
			     " match calling module '%T'", entry->name, mod_atom);
    }
    else {
	/*erts_fprintf(stderr, "Found module %T\r\n", mod_atom);*/
    
	for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) {
	    BeamInstr** code_pp;
	    ErlNifFunc* f = &entry->funcs[i];
	    if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom)
		|| (code_pp = get_func_pp(mod->code, f_atom, f->arity))==NULL) { 
		ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u",
				     mod_atom, f->name, f->arity);
	    }    
	    else if (code_pp[1] - code_pp[0] < (5+3)) {
		ret = load_nif_error(BIF_P,bad_lib,"No explicit call to load_nif"
				     " in module (%T:%s/%u to small)",
				     mod_atom, entry->funcs[i].name, entry->funcs[i].arity);
	    }
	    /*erts_fprintf(stderr, "Found NIF %T:%s/%u\r\n",
			 mod_atom, entry->funcs[i].name, entry->funcs[i].arity);*/
	}
    }

    if (ret != am_ok) {
	goto error;
    }

    /* Call load, reload or upgrade:
     */


    lib = erts_alloc(ERTS_ALC_T_NIF, sizeof(struct erl_module_nif));
    lib->handle = handle;
    lib->entry = entry;
    erts_refc_init(&lib->rt_cnt, 0);
    erts_refc_init(&lib->rt_dtor_cnt, 0);
    lib->mod = mod;
    env.mod_nif = lib;
    if (mod->nif != NULL) { /* Reload */
	int k;
        lib->priv_data = mod->nif->priv_data;

	ASSERT(mod->nif->entry != NULL);
	if (entry->reload == NULL) {
	    ret = load_nif_error(BIF_P,reload,"Reload not supported by this NIF library.");
	    goto error;
	}
	/* Check that no NIF is removed */
	for (k=0; k < mod->nif->entry->num_of_funcs; k++) {
	    ErlNifFunc* old_func = &mod->nif->entry->funcs[k];
	    for (i=0; i < entry->num_of_funcs; i++) {
		if (old_func->arity == entry->funcs[i].arity
		    && sys_strcmp(old_func->name, entry->funcs[i].name) == 0) {			   
		    break;
		}
	    }
	    if (i == entry->num_of_funcs) {
		ret = load_nif_error(BIF_P,reload,"Reloaded library missing "
				     "function %T:%s/%u\r\n", mod_atom,
				     old_func->name, old_func->arity);
		goto error;
	    }
	}       
	erts_pre_nif(&env, BIF_P, lib);
	veto = entry->reload(&env, &lib->priv_data, BIF_ARG_2);
	erts_post_nif(&env);
	if (veto) {
	    ret = load_nif_error(BIF_P, reload, "Library reload-call unsuccessful.");
	}
	else {
	    mod->nif->entry = NULL; /* to prevent 'unload' callback */
	    erts_unload_nif(mod->nif);
	}
    }
    else {
	lib->priv_data = NULL;
	if (mod->old_nif != NULL) { /* Upgrade */
	    void* prev_old_data = mod->old_nif->priv_data;
	    if (entry->upgrade == NULL) {
		ret = load_nif_error(BIF_P, upgrade, "Upgrade not supported by this NIF library.");
		goto error;
	    }
	    erts_pre_nif(&env, BIF_P, lib);
	    veto = entry->upgrade(&env, &lib->priv_data, &mod->old_nif->priv_data, BIF_ARG_2);
	    erts_post_nif(&env);
	    if (veto) {
		mod->old_nif->priv_data = prev_old_data;
		ret = load_nif_error(BIF_P, upgrade, "Library upgrade-call unsuccessful.");
	    }
	    /*else if (mod->old_nif->priv_data != prev_old_data) {
		refresh_cached_nif_data(mod->old_code, mod->old_nif);
	    }*/
	}
	else if (entry->load != NULL) { /* Initial load */
	    erts_pre_nif(&env, BIF_P, lib);
	    veto = entry->load(&env, &lib->priv_data, BIF_ARG_2);
	    erts_post_nif(&env);
	    if (veto) {
		ret = load_nif_error(BIF_P, "load", "Library load-call unsuccessful.");
	    }
	}
    }
    if (ret == am_ok) {
	/*
	** Everything ok, patch the beam code with op_call_nif
	*/
        mod->nif = lib; 
	for (i=0; i < entry->num_of_funcs; i++)
	{
	    BeamInstr* code_ptr;
	    erts_atom_get(entry->funcs[i].name, sys_strlen(entry->funcs[i].name), &f_atom); 
	    code_ptr = *get_func_pp(mod->code, f_atom, entry->funcs[i].arity); 
	    
	    if (code_ptr[1] == 0) {
		code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif);
	    }
	    else { /* Function traced, patch the original instruction word */
		BpData** bps = (BpData**) code_ptr[1];
		BpData*  bp  = (BpData*) bps[erts_bp_sched2ix()];
	        bp->orig_instr = (BeamInstr) BeamOp(op_call_nif);
	    }	    
	    code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr;
	    code_ptr[5+2] = (BeamInstr) lib;
	}
    }
    else {
    error:
	ASSERT(ret != am_ok);
        if (lib != NULL) {
	    erts_free(ERTS_ALC_T_NIF, lib);
	}
	if (handle != NULL) {
	    erts_sys_ddll_close(handle);
	}
	erts_sys_ddll_free_error(&errdesc);
    }

    erts_smp_thr_progress_unblock();
    erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_free(ERTS_ALC_T_TMP, lib_name);
    BIF_RET(ret);
}
コード例 #14
0
ファイル: erl_node_tables.c プロジェクト: JamesGreenhalgh/otp
void erts_init_node_tables(int dd_sec)
{
    erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
    HashFunctions f;

    if (dd_sec == ERTS_NODE_TAB_DELAY_GC_INFINITY)
	node_tab_delete_delay = (ErtsMonotonicTime) -1;
    else
	node_tab_delete_delay = ((ErtsMonotonicTime) dd_sec)*1000;

    orig_node_tab_delete_delay = node_tab_delete_delay;

    rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
    rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;

    f.hash  = (H_FUN)			dist_table_hash;
    f.cmp   = (HCMP_FUN)		dist_table_cmp;
    f.alloc = (HALLOC_FUN)		dist_table_alloc;
    f.free  = (HFREE_FUN)		dist_table_free;

    erts_this_dist_entry = erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry));
    dist_entries = 1;

    hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f);

    erts_hidden_dist_entries				= NULL;
    erts_visible_dist_entries				= NULL;
    erts_not_connected_dist_entries			= NULL;
    erts_no_of_hidden_dist_entries			= 0;
    erts_no_of_visible_dist_entries			= 0;
    erts_no_of_not_connected_dist_entries		= 0;

    erts_this_dist_entry->next				= NULL;
    erts_this_dist_entry->prev				= NULL;
    erts_refc_init(&erts_this_dist_entry->refc, 1); /* erts_this_node */

    erts_smp_rwmtx_init_opt_x(&erts_this_dist_entry->rwmtx,
			      &rwmtx_opt,
			      "dist_entry",
			      make_small(ERST_INTERNAL_CHANNEL_NO));
    erts_this_dist_entry->sysname			= am_Noname;
    erts_this_dist_entry->cid				= NIL;
    erts_this_dist_entry->connection_id			= 0;
    erts_this_dist_entry->status			= 0;
    erts_this_dist_entry->flags				= 0;
    erts_this_dist_entry->version			= 0;

    erts_smp_mtx_init_x(&erts_this_dist_entry->lnk_mtx,
			"dist_entry_links",
			make_small(ERST_INTERNAL_CHANNEL_NO));
    erts_this_dist_entry->node_links			= NULL;
    erts_this_dist_entry->nlinks			= NULL;
    erts_this_dist_entry->monitors			= NULL;

    erts_smp_mtx_init_x(&erts_this_dist_entry->qlock,
			"dist_entry_out_queue",
			make_small(ERST_INTERNAL_CHANNEL_NO));
    erts_this_dist_entry->qflgs				= 0;
    erts_this_dist_entry->qsize				= 0;
    erts_this_dist_entry->out_queue.first		= NULL;
    erts_this_dist_entry->out_queue.last		= NULL;
    erts_this_dist_entry->suspended			= NULL;

    erts_this_dist_entry->finalized_out_queue.first	= NULL;
    erts_this_dist_entry->finalized_out_queue.last	= NULL;
    erts_smp_atomic_init_nob(&erts_this_dist_entry->dist_cmd_scheduled, 0);
    erts_port_task_handle_init(&erts_this_dist_entry->dist_cmd);
    erts_this_dist_entry->send				= NULL;
    erts_this_dist_entry->cache				= NULL;

    (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);

    f.hash  = (H_FUN)      			node_table_hash;
    f.cmp   = (HCMP_FUN)   			node_table_cmp;
    f.alloc = (HALLOC_FUN) 			node_table_alloc;
    f.free  = (HFREE_FUN)  			node_table_free;

    hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f);

    erts_this_node = erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode));
    node_entries = 1;

    erts_refc_init(&erts_this_node->refc, 1); /* The system itself */
    erts_this_node->sysname			= am_Noname;
    erts_this_node->creation			= 0;
    erts_this_node->dist_entry			= erts_this_dist_entry;
    erts_this_node_sysname = erts_this_node_sysname_BUFFER;
    erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
                  "%T", erts_this_node->sysname);

    (void) hash_put(&erts_node_table, (void *) erts_this_node);

    erts_smp_rwmtx_init_opt(&erts_node_table_rwmtx, &rwmtx_opt, "node_table");
    erts_smp_rwmtx_init_opt(&erts_dist_table_rwmtx, &rwmtx_opt, "dist_table");

    references_atoms_need_init = 1;
}