Пример #1
0
static void try_delete_node(void *venp)
{
    ErlNode *enp = (ErlNode *) venp;
    erts_aint_t refc;

    erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx);
    /*
     * Another thread might have looked up this node after we
     * decided to delete it (refc became zero). If so, the other
     * thread incremented refc twice. Once for the new reference
     * and once for this thread.
     *
     * If refc reach -1, noone has used the entry since we
     * set up the timer. Delete the entry.
     *
     * If refc reach 0, the entry is currently not in use
     * but has been used since we set up the timer. Set up a
     * new timer.
     *
     * If refc > 0, the entry is in use. Keep the entry.
     */
    refc = erts_refc_dectest(&enp->refc, -1);
    if (refc == -1)
	(void) hash_erase(&erts_node_table, (void *) enp);
    erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx);

    if (refc == 0)
	erts_schedule_delete_node(enp);
}
Пример #2
0
void
erts_set_this_node(Eterm sysname, Uint creation)
{
    erts_smp_mtx_lock(&erts_node_table_mtx);
    erts_smp_mtx_lock(&erts_dist_table_mtx);

    (void) hash_erase(&erts_dist_table, (void *) erts_this_dist_entry);
    erts_this_dist_entry->sysname = sysname;
    erts_this_dist_entry->creation = creation;
    (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);

    (void) hash_erase(&erts_node_table, (void *) erts_this_node);
    erts_this_node->sysname = sysname;
    erts_this_node->creation = creation;
    (void) hash_put(&erts_node_table, (void *) erts_this_node);

    erts_smp_mtx_unlock(&erts_dist_table_mtx);
    erts_smp_mtx_unlock(&erts_node_table_mtx);

}
Пример #3
0
void
erts_set_this_node(Eterm sysname, Uint creation)
{
    erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx);
    erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx);

    (void) hash_erase(&erts_dist_table, (void *) erts_this_dist_entry);
    erts_this_dist_entry->sysname = sysname;
    erts_this_dist_entry->creation = creation;
    (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry);

    (void) hash_erase(&erts_node_table, (void *) erts_this_node);
    erts_this_node->sysname = sysname;
    erts_this_node->creation = creation;
    erts_this_node_sysname = erts_this_node_sysname_BUFFER;
    erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER),
                  "%T", sysname);
    (void) hash_put(&erts_node_table, (void *) erts_this_node);

    erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx);
    erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx);

}
Пример #4
0
void erts_delete_node(ErlNode *enp)
{
    ASSERT(enp != erts_this_node);
    if(enp != erts_this_node) {
	erts_smp_mtx_lock(&erts_node_table_mtx);
	/*
	 * Another thread might have looked up this node after we
	 * decided to delete it (refc became zero). If so, the other
	 * thread incremented refc twice. Once for the new reference
	 * and once for this thread. Therefore, delete node if refc
	 * is 0 or -1 after a decrement.
	 */
	if (erts_refc_dectest(&enp->refc, -1) <= 0)
	    (void) hash_erase(&erts_node_table, (void *) enp);
	erts_smp_mtx_unlock(&erts_node_table_mtx);
    }
}
Пример #5
0
void erts_delete_dist_entry(DistEntry *dep)
{
    ASSERT(dep != erts_this_dist_entry);
    if(dep != erts_this_dist_entry) {
	erts_smp_mtx_lock(&erts_dist_table_mtx);
	/*
	 * Another thread might have looked up this dist entry after
	 * we decided to delete it (refc became zero). If so, the other
	 * thread incremented refc twice. Once for the new reference
	 * and once for this thread. Therefore, delete dist entry if
	 * refc is 0 or -1 after a decrement.
	 */
	if (erts_refc_dectest(&dep->refc, -1) <= 0)
	    (void) hash_erase(&erts_dist_table, (void *) dep);
	erts_smp_mtx_unlock(&erts_dist_table_mtx);
    }
}
Пример #6
0
/* Test that we can erase a key from the table */
int test_erase() {

    build_hash();

    /* The key should no longer be found */
    if(!hash_get(hash, (void*)"k1", (void**)&value)) {
        printf("Key k1 missing from initial hash.\n");
        return 1;
    }

    /* make sure that unset values actually fail */
    hash_erase(hash, (void*)"k1");

    value = "";

    /* The key should no longer be found */
    if(hash_get(hash, (void*)"k1", (void**)&value)) {
        printf("Found: '%s'\n", value);
    
        return 1;
    }

    return 0;
}
Пример #7
0
/*
 * Unregister a name
 * Return 0 if not registered
 * Otherwise returns 1
 *
 */
int erts_unregister_name(Process *c_p,
			 ErtsProcLocks c_p_locks,
			 Port *c_prt,
			 Eterm name)
{
    int res = 0;
    RegProc r, *rp;
    Port *port = c_prt;
    ErtsProcLocks current_c_p_locks = 0;
#ifdef ERTS_SMP

    /*
     * SMP note: If 'c_prt != NULL' and 'c_prt->reg->name == name',
     *           we are *not* allowed to temporarily release the lock
     *           on c_prt.
     */

    if (!c_p) {
	c_p_locks = 0;
    }
    current_c_p_locks = c_p_locks;

 restart:

    reg_safe_write_lock(c_p, &current_c_p_locks);
#endif

    r.name = name;
    if (is_non_value(name)) {
	/* Unregister current process name */
	ASSERT(c_p);
#ifdef ERTS_SMP
	if (current_c_p_locks != c_p_locks) {
	    erts_smp_proc_lock(c_p, c_p_locks);
	    current_c_p_locks = c_p_locks;
	}
#endif
	if (c_p->common.u.alive.reg) {
	    r.name = c_p->common.u.alive.reg->name;
	} else {
	    /* Name got unregistered while main lock was released */
	    res = 0;
	    goto done;
	}
    }

    if ((rp = (RegProc*) hash_get(&process_reg, (void*) &r)) != NULL) {
	if (rp->pt) {
	    if (port != rp->pt) {
#ifdef ERTS_SMP
		if (port) {
		    ASSERT(port != c_prt);
		    erts_port_release(port);
		    port = NULL;
		}

		if (erts_smp_port_trylock(rp->pt) == EBUSY) {
		    Eterm id = rp->pt->common.id; /* id read only... */
		    /* Unlock all locks, acquire port lock, and restart... */
		    if (current_c_p_locks) {
			erts_smp_proc_unlock(c_p, current_c_p_locks);
			current_c_p_locks = 0;
		    }
		    reg_write_unlock();
		    port = erts_id2port(id);
		    goto restart;
		}
#endif
		port = rp->pt;
	    }

	    ASSERT(rp->pt == port);
	    ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(port));

	    rp->pt->common.u.alive.reg = NULL;

	    if (IS_TRACED_FL(port, F_TRACE_PORTS)) {
                if (current_c_p_locks) {
                    erts_smp_proc_unlock(c_p, current_c_p_locks);
                    current_c_p_locks = 0;
                }
		trace_port(port, am_unregister, r.name);
	    }

	} else if (rp->p) {

#ifdef ERTS_SMP
	    erts_proc_safelock(c_p,
			       current_c_p_locks,
			       c_p_locks,
			       rp->p,
			       (c_p == rp->p) ?  current_c_p_locks : 0,
			       ERTS_PROC_LOCK_MAIN);
	    current_c_p_locks = c_p_locks;
#endif
	    rp->p->common.u.alive.reg = NULL;
	    if (IS_TRACED_FL(rp->p, F_TRACE_PROCS)) {
                trace_proc(rp->p, (c_p == rp->p) ? c_p_locks : ERTS_PROC_LOCK_MAIN,
                           rp->p, am_unregister, r.name);
	    }
#ifdef ERTS_SMP
	    if (rp->p != c_p) {
		erts_smp_proc_unlock(rp->p, ERTS_PROC_LOCK_MAIN);
	    }
#endif
	}
	hash_erase(&process_reg, (void*) &r);
	res = 1;
    }

 done:

    reg_write_unlock();
    if (c_prt != port) {
	if (port) {
	    erts_port_release(port);
	}
	if (c_prt) {
	    erts_smp_port_lock(c_prt);
	}
    }
#ifdef ERTS_SMP
    if (c_p && !current_c_p_locks) {
	erts_smp_proc_lock(c_p, c_p_locks);
    }
#endif
    return res;
}
Пример #8
0
/*
 * Unregister a name
 * Return 0 if not registered
 * Otherwise returns 1
 *
 */
int erts_unregister_name(Process *c_p,
			 ErtsProcLocks c_p_locks,
			 Port *c_prt,
			 Eterm name)
{
    int res = 0;
    RegProc r, *rp;
    Port *port = c_prt;
#ifdef ERTS_SMP
    ErtsProcLocks current_c_p_locks;

    /*
     * SMP note: If 'c_prt != NULL' and 'c_prt->reg->name == name',
     *           we are *not* allowed to temporarily release the lock
     *           on c_prt.
     */

    if (!c_p)
	c_p_locks = 0;
    current_c_p_locks = c_p_locks;

 restart:

    reg_safe_write_lock(c_p, &current_c_p_locks);
#endif
    
    r.name = name;
    if ((rp = (RegProc*) hash_get(&process_reg, (void*) &r)) != NULL) {
	if (rp->pt) {
#ifdef ERTS_SMP
	    if (port != rp->pt) {
		if (port) {
		    ERTS_SMP_LC_ASSERT(port != c_prt);
		    erts_smp_port_unlock(port);
		    port = NULL;
		}

		if (erts_smp_port_trylock(rp->pt) == EBUSY) {
		    Eterm id = rp->pt->id; /* id read only... */
		    /* Unlock all locks, acquire port lock, and restart... */
		    if (current_c_p_locks) {
			erts_smp_proc_unlock(c_p, current_c_p_locks);
			current_c_p_locks = 0;
		    }
		    reg_read_unlock();
		    port = erts_id2port(id, NULL, 0);
		    goto restart;
		}
		port = rp->pt;
	    }
#endif
	    ERTS_SMP_LC_ASSERT(rp->pt == port && erts_lc_is_port_locked(port));
	    rp->pt->reg = NULL;
	    
	    if (IS_TRACED_FL(port, F_TRACE_PORTS)) {
		trace_port(port, am_unregister, name);
	    }

	} else if (rp->p) {
	    Process* p = rp->p;
#ifdef ERTS_SMP
	    erts_proc_safelock(c_p,
			       current_c_p_locks,
			       c_p_locks,
			       rp->p,
			       0,
			       ERTS_PROC_LOCK_MAIN);
	    current_c_p_locks = c_p_locks;
#endif
	    p->reg = NULL;
#ifdef ERTS_SMP
	    if (rp->p != c_p)
		erts_smp_proc_unlock(rp->p, ERTS_PROC_LOCK_MAIN);
#endif
	    if (IS_TRACED_FL(p, F_TRACE_PROCS)) {
		trace_proc(c_p, p, am_unregister, name);
	    }
	}
	hash_erase(&process_reg, (void*) &r);
	res = 1;
    }

    reg_write_unlock();
    if (c_prt != port) {
	if (port)
	    erts_smp_port_unlock(port);
	if (c_prt)
	    erts_smp_port_lock(c_prt);
    }
#ifdef ERTS_SMP
    if (c_p && !current_c_p_locks)
	erts_smp_proc_lock(c_p, c_p_locks);
#endif
    return res;
}