예제 #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
static void lcnt_update_stats(erts_lcnt_lock_stats_t *stats, int lock_in_conflict, erts_lcnt_time_t *time_wait) {
    
    ethr_atomic_inc(&stats->tries);

    if (lock_in_conflict)
	ethr_atomic_inc(&stats->colls);

    if (time_wait) {
	lcnt_time_add(&(stats->timer), time_wait);
	stats->timer_n++;
    }
}
예제 #3
0
void erts_lcnt_trylock_opt(erts_lcnt_lock_t *lock, int res, Uint16 option) {
    if (erts_lcnt_rt_options & ERTS_LCNT_OPT_SUSPEND) return;
    /* Determine lock_state via res instead of state */
    if (res != EBUSY) {
        if (option & ERTS_LCNT_LO_WRITE) ethr_atomic_inc(&lock->w_state);
        if (option & ERTS_LCNT_LO_READ ) ethr_atomic_inc(&lock->r_state);
        lcnt_update_stats(&(lock->stats[0]), 0, NULL);
    } else {
        ethr_atomic_inc(&lock->stats[0].tries);
        ethr_atomic_inc(&lock->stats[0].colls);
    }
}
예제 #4
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;
}
예제 #5
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;
    }
}
예제 #6
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);
    }
}
예제 #7
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);
    }

}