Пример #1
0
void erts_lcnt_lock_opt(erts_lcnt_lock_t *lock, Uint16 option) {
    erts_aint_t r_state = 0, w_state = 0;
    erts_lcnt_thread_data_t *eltd;
    
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
    if (!ERTS_LCNT_LOCK_TYPE(lock)) return;

    eltd = lcnt_get_thread_data();

    ASSERT(eltd);
    
    w_state = ethr_atomic_read(&lock->w_state);
    
    if (option & ERTS_LCNT_LO_WRITE) {
        r_state = ethr_atomic_read(&lock->r_state);
        ethr_atomic_inc( &lock->w_state);
    }
    if (option & ERTS_LCNT_LO_READ) {
        ethr_atomic_inc( &lock->r_state);
    }
    
    /* we cannot acquire w_lock if either w or r are taken */
    /* we cannot acquire r_lock if w_lock is taken */	
    
    if ((w_state > 0) || (r_state > 0)) {
	eltd->lock_in_conflict = 1;
	if (eltd->timer_set == 0)
	    lcnt_time(&eltd->timer);
	eltd->timer_set++;
    } else {
	eltd->lock_in_conflict = 0;
    }
}
Пример #2
0
void *
at_thread(void *unused)
{
    int i;
    long val, go;

    val = ethr_atomic_inc_read(&at_ready);
    ASSERT(val > 0);
    ASSERT(val <= AT_THREADS);

    do {
	go = ethr_atomic_read(&at_go);
    } while (!go);

    for (i = 0; i < AT_ITER; i++) {
	val = ethr_atomic_read_bor(&at_data, at_set_val);
	ASSERT(val >= (i == 0 ? 0 : at_set_val) + (long) 4711);
	ASSERT(val <= at_max_val);

	val = ethr_atomic_read_band(&at_data, ~at_rm_val);
	ASSERT(val >= at_set_val + (long) 4711);
	ASSERT(val <= at_max_val);

	val = ethr_atomic_read(&at_data);
	ASSERT(val >= at_set_val + (long) 4711);
	ASSERT(val <= at_max_val);

	val = ethr_atomic_inc_read(&at_data);
	ASSERT(val > at_set_val + (long) 4711);
	ASSERT(val <= at_max_val);

	val = ethr_atomic_dec_read(&at_data);
	ASSERT(val >= at_set_val + (long) 4711);
	ASSERT(val <= at_max_val);

	ethr_atomic_inc(&at_data);

	ethr_atomic_dec(&at_data);

	val = ethr_atomic_add_read(&at_data, (long) 4711);
	ASSERT(val >= at_set_val + (long) 2*4711);
	ASSERT(val <= at_max_val);

	ethr_atomic_add(&at_data, (long) -4711);
	ASSERT(val >= at_set_val + (long) 4711);
	ASSERT(val <= at_max_val);
    }

    ethr_atomic_inc(&at_done);
    return NULL;
}
Пример #3
0
void erts_lcnt_lock(erts_lcnt_lock_t *lock) {
    erts_aint_t w_state;
    erts_lcnt_thread_data_t *eltd;
    
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
    if (!ERTS_LCNT_LOCK_TYPE(lock)) return;

    w_state = ethr_atomic_read(&lock->w_state);
    ethr_atomic_inc( &lock->w_state);

    eltd = lcnt_get_thread_data();

    ASSERT(eltd);

    if (w_state > 0) {
	eltd->lock_in_conflict = 1;
	/* only set the timer if nobody else has it
	 * This should only happen when proc_locks aquires several locks
	 * 'atomicly'. All other locks will block the thread if w_state > 0
	 * i.e. locked.
	 */
	if (eltd->timer_set == 0)
	    lcnt_time(&eltd->timer);
	eltd->timer_set++;

    } else {
	eltd->lock_in_conflict = 0;
    }
}
Пример #4
0
void erts_lcnt_unlock(erts_lcnt_lock_t *lock) {
#ifdef DEBUG
    erts_aint_t w_state;
    erts_aint_t flowstate;
#endif
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
#ifdef DEBUG
    /* flowstate */
    flowstate = ethr_atomic_read(&lock->flowstate);
    ASSERT(flowstate == 1);
    ethr_atomic_dec( &lock->flowstate);

    /* write state */
    w_state = ethr_atomic_read(&lock->w_state);
    ASSERT(w_state > 0)
#endif
    ethr_atomic_dec(&lock->w_state);
}
Пример #5
0
static void print_lock_x(erts_lcnt_lock_t *lock, Uint16 flag, char *action, char *extra) {
    erts_aint_t colls, tries, w_state, r_state;
    erts_lcnt_lock_stats_t *stats = NULL;
    
    char *type;
    int i;
    
    type = lcnt_lock_type(lock->flag);
    r_state = ethr_atomic_read(&lock->r_state);
    w_state = ethr_atomic_read(&lock->w_state);

    
    if (lock->flag & flag) {
        erts_printf("%20s [%30s] [r/w state %4ld/%4ld] id %T %s\r\n", 
		action, 
		lock->name, 
		r_state, 
		w_state, 
		lock->id, 
		extra);
    }
}
Пример #6
0
void erts_lcnt_lock_post_x(erts_lcnt_lock_t *lock, char *file, unsigned int line) {
    erts_lcnt_thread_data_t *eltd;
    erts_lcnt_time_t timer;
    erts_lcnt_time_t time_wait;
    erts_lcnt_lock_stats_t *stats;
#ifdef DEBUG
    erts_aint_t flowstate;
#endif

    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
    if (!ERTS_LCNT_LOCK_TYPE(lock)) return;
    
#ifdef DEBUG
    if (!(lock->flag & (ERTS_LCNT_LT_RWMUTEX | ERTS_LCNT_LT_RWSPINLOCK))) {
	flowstate = ethr_atomic_read(&lock->flowstate);
	ASSERT(flowstate == 0);
    	ethr_atomic_inc( &lock->flowstate);
    }
#endif
    
    eltd = lcnt_get_thread_data();
    
    ASSERT(eltd);

    /* if lock was in conflict, time it */
    
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_LOCATION) {
	stats = lcnt_get_lock_stats(lock, file, line);
    } else {
	stats = &lock->stats[0];
    }

    if (eltd->timer_set) {
	lcnt_time(&timer);
	
	lcnt_time_diff(&time_wait, &timer, &(eltd->timer));
	lcnt_update_stats(stats, eltd->lock_in_conflict, &time_wait);
	
	eltd->timer_set--;
	ASSERT(eltd->timer_set >= 0);
    } else {
	lcnt_update_stats(stats, eltd->lock_in_conflict, NULL);
    }

}
Пример #7
0
void erts_lcnt_trylock(erts_lcnt_lock_t *lock, int res) {
    /* Determine lock_state via res instead of state */
#ifdef DEBUG
    erts_aint_t flowstate;
#endif
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
    if (res != EBUSY) {

#ifdef DEBUG
        flowstate = ethr_atomic_read(&lock->flowstate);
        ASSERT(flowstate == 0);
        ethr_atomic_inc( &lock->flowstate);
#endif
        ethr_atomic_inc(&lock->w_state);

        lcnt_update_stats(&(lock->stats[0]), 0, NULL);

    } else {
        ethr_atomic_inc(&lock->stats[0].tries);
        ethr_atomic_inc(&lock->stats[0].colls);
    }
}
Пример #8
0
static void
atomic_test(void)
{
    long data_init, data_final, val;
    int res, i;
    ethr_tid tid[AT_THREADS];
    ethr_thr_opts thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;

    atomic_basic_test();

#if ETHR_SIZEOF_PTR > 4
	at_rm_val = ((long) 1) << 57;
	at_set_val = ((long) 1) << 60;
#else
	at_rm_val = ((long) 1) << 27;
	at_set_val = ((long) 1) << 30;
#endif

    at_max_val = at_set_val + at_rm_val + ((long) AT_THREADS + 1) * 4711;
    data_init = at_rm_val + (long) 4711;
    data_final = at_set_val + (long) 4711;

    thr_opts.detached = 1;

    print_line("Initializing");
    ethr_atomic_init(&at_ready, 0);
    ethr_atomic_init(&at_go, 0);
    ethr_atomic_init(&at_done, data_init);
    ethr_atomic_init(&at_data, data_init);

    val = ethr_atomic_read(&at_data);
    ASSERT(val == data_init);
    ethr_atomic_set(&at_done, 0);
    val = ethr_atomic_read(&at_done);
    ASSERT(val == 0);

    print_line("Creating threads");
    for (i = 0; i < AT_THREADS; i++) {
	res = ethr_thr_create(&tid[i], at_thread, NULL, &thr_opts);
	ASSERT(res == 0);
    }

    print_line("Waiting for threads to ready up");
    do {
	val = ethr_atomic_read(&at_ready);
	ASSERT(val >= 0);
	ASSERT(val <= AT_THREADS);
    } while (val != AT_THREADS);

    print_line("Letting threads loose");
    val = ethr_atomic_xchg(&at_go, 17);
    ASSERT(val == 0);
    val = ethr_atomic_read(&at_go);
    ASSERT(val == 17);


    print_line("Waiting for threads to finish");
    do {
	val = ethr_atomic_read(&at_done);
	ASSERT(val >= 0);
	ASSERT(val <= AT_THREADS);
    } while (val != AT_THREADS);

    print_line("Checking result");
    val = ethr_atomic_read(&at_data);
    ASSERT(res == 0);
    ASSERT(val == data_final);
    print_line("Result ok");
    
}