Esempio n. 1
0
ulint
rw_lock_n_locked(void)
/*==================*/
{
    rw_lock_t*	lock;
    ulint		count		= 0;

    mutex_enter(&rw_lock_list_mutex);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {
        mutex_enter(rw_lock_get_mutex(lock));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)) {
            count++;
        }

        mutex_exit(rw_lock_get_mutex(lock));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    mutex_exit(&rw_lock_list_mutex);

    return(count);
}
Esempio n. 2
0
void
rw_lock_free(
    /*=========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
    ut_ad(rw_lock_validate(lock));
    ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
    ut_a(rw_lock_get_waiters(lock) == 0);
    ut_a(rw_lock_get_reader_count(lock) == 0);

    lock->magic_n = 0;

    mutex_free(rw_lock_get_mutex(lock));

    mutex_enter(&rw_lock_list_mutex);
    os_event_free(lock->event);

#ifdef __WIN__
    os_event_free(lock->wait_ex_event);
#endif

    if (UT_LIST_GET_PREV(list, lock)) {
        ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
    }
    if (UT_LIST_GET_NEXT(list, lock)) {
        ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
    }

    UT_LIST_REMOVE(list, rw_lock_list, lock);

    mutex_exit(&rw_lock_list_mutex);
}
Esempio n. 3
0
void
rw_lock_print(
    /*==========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
    rw_lock_debug_t* info;

    fprintf(stderr,
            "-------------\n"
            "RW-LATCH INFO\n"
            "RW-LATCH: %p ", (void*) lock);

    if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
            || (rw_lock_get_reader_count(lock) != 0)
            || (rw_lock_get_waiters(lock) != 0)) {

        if (rw_lock_get_waiters(lock)) {
            fputs(" Waiters for the lock exist\n", stderr);
        } else {
            putc('\n', stderr);
        }

        info = UT_LIST_GET_FIRST(lock->debug_list);
        while (info != NULL) {
            rw_lock_debug_print(info);
            info = UT_LIST_GET_NEXT(list, info);
        }
    }
}
Esempio n. 4
0
/******************************************************************//**
Checks if somebody has locked the rw-lock in the specified mode.
@return	TRUE if locked */
UNIV_INTERN
ibool
rw_lock_is_locked(
/*==============*/
	rw_lock_t*	lock,		/*!< in: rw-lock */
	ulint		lock_type)	/*!< in: lock type: RW_LOCK_SHARED,
					RW_LOCK_EX */
{
	ibool	ret	= FALSE;

	ut_ad(lock);
	ut_ad(rw_lock_validate(lock));

	if (lock_type == RW_LOCK_SHARED) {
		if (rw_lock_get_reader_count(lock) > 0) {
			ret = TRUE;
		}
	} else if (lock_type == RW_LOCK_EX) {
		if (rw_lock_get_writer(lock) == RW_LOCK_EX) {
			ret = TRUE;
		}
	} else {
		ut_error;
	}

	return(ret);
}
Esempio n. 5
0
ulint
rw_lock_n_locked(void)
/*==================*/
{
#ifndef UNIV_SYNC_DEBUG
    printf(
        "Sorry, cannot give rw-lock info in non-debug version!\n");
    ut_error;
    return(0);
#else
    rw_lock_t*	lock;
    ulint		count		= 0;

    mutex_enter(&rw_lock_list_mutex);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {
        mutex_enter(rw_lock_get_mutex(lock));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)) {
            count++;
        }

        mutex_exit(rw_lock_get_mutex(lock));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    mutex_exit(&rw_lock_list_mutex);

    return(count);
#endif
}
Esempio n. 6
0
void
rw_lock_print(
    /*==========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
#ifndef UNIV_SYNC_DEBUG
    printf(
        "Sorry, cannot give rw-lock info in non-debug version!\n");
#else
    ulint		count		= 0;
    rw_lock_debug_t* info;

    printf("-------------\n");
    printf("RW-LATCH INFO\n");
    printf("RW-LATCH: %lx ", (ulint)lock);

    if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
            || (rw_lock_get_reader_count(lock) != 0)
            || (rw_lock_get_waiters(lock) != 0)) {

        if (rw_lock_get_waiters(lock)) {
            printf(" Waiters for the lock exist\n");
        } else {
            printf("\n");
        }

        info = UT_LIST_GET_FIRST(lock->debug_list);
        while (info != NULL) {
            rw_lock_debug_print(info);
            info = UT_LIST_GET_NEXT(list, info);
        }
    }
#endif
}
Esempio n. 7
0
void
rw_lock_list_print_info(void)
/*=========================*/
{
#ifndef UNIV_SYNC_DEBUG
#else
    rw_lock_t*	lock;
    ulint		count		= 0;
    rw_lock_debug_t* info;

    mutex_enter(&rw_lock_list_mutex);

    printf("-------------\n");
    printf("RW-LATCH INFO\n");
    printf("-------------\n");

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {

        count++;

        mutex_enter(&(lock->mutex));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)
                || (rw_lock_get_waiters(lock) != 0)) {

            printf("RW-LOCK: %lx ", (ulint)lock);

            if (rw_lock_get_waiters(lock)) {
                printf(" Waiters for the lock exist\n");
            } else {
                printf("\n");
            }

            info = UT_LIST_GET_FIRST(lock->debug_list);
            while (info != NULL) {
                rw_lock_debug_print(info);
                info = UT_LIST_GET_NEXT(list, info);
            }
        }

        mutex_exit(&(lock->mutex));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    printf("Total number of rw-locks %ld\n", count);
    mutex_exit(&rw_lock_list_mutex);
#endif
}
Esempio n. 8
0
void
rw_lock_list_print_info(
    /*====================*/
    FILE*	file)		/* in: file where to print */
{
    rw_lock_t*	lock;
    ulint		count		= 0;
    rw_lock_debug_t* info;

    mutex_enter(&rw_lock_list_mutex);

    fputs("-------------\n"
          "RW-LATCH INFO\n"
          "-------------\n", file);

    lock = UT_LIST_GET_FIRST(rw_lock_list);

    while (lock != NULL) {

        count++;

        mutex_enter(&(lock->mutex));

        if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
                || (rw_lock_get_reader_count(lock) != 0)
                || (rw_lock_get_waiters(lock) != 0)) {

            fprintf(file, "RW-LOCK: %p ", (void*) lock);

            if (rw_lock_get_waiters(lock)) {
                fputs(" Waiters for the lock exist\n", file);
            } else {
                putc('\n', file);
            }

            info = UT_LIST_GET_FIRST(lock->debug_list);
            while (info != NULL) {
                rw_lock_debug_print(info);
                info = UT_LIST_GET_NEXT(list, info);
            }
        }

        mutex_exit(&(lock->mutex));
        lock = UT_LIST_GET_NEXT(list, lock);
    }

    fprintf(file, "Total number of rw-locks %ld\n", count);
    mutex_exit(&rw_lock_list_mutex);
}
Esempio n. 9
0
void
rw_lock_free(
    /*=========*/
    rw_lock_t*	lock)	/* in: rw-lock */
{
    ut_ad(rw_lock_validate(lock));
    ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
    ut_a(rw_lock_get_waiters(lock) == 0);
    ut_a(rw_lock_get_reader_count(lock) == 0);

    lock->magic_n = 0;

    mutex_free(rw_lock_get_mutex(lock));

    mutex_enter(&rw_lock_list_mutex);

    UT_LIST_REMOVE(list, rw_lock_list, lock);

    mutex_exit(&rw_lock_list_mutex);
}
Esempio n. 10
0
ibool
rw_lock_validate(
    /*=============*/
    rw_lock_t*	lock)
{
    ut_a(lock);

    mutex_enter(rw_lock_get_mutex(lock));

    ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
    ut_a((rw_lock_get_reader_count(lock) == 0)
         || (rw_lock_get_writer(lock) != RW_LOCK_EX));
    ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
         || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
         || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
    ut_a((rw_lock_get_waiters(lock) == 0)
         || (rw_lock_get_waiters(lock) == 1));
    ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));

    mutex_exit(rw_lock_get_mutex(lock));

    return(TRUE);
}
Esempio n. 11
0
/******************************************************************//**
Reports info of a wait array cell. */
static
void
sync_array_cell_print(
/*==================*/
	FILE*		file,	/*!< in: file where to print */
	sync_cell_t*	cell)	/*!< in: sync cell */
{
	mutex_t*	mutex;
	rw_lock_t*	rwlock;
	ulint		type;
	ulint		writer;

	type = cell->request_type;

	fprintf(file,
		"--Thread %lu has waited at %s line %lu"
		" for %.2f seconds the semaphore:\n",
		(ulong) os_thread_pf(cell->thread),
		innobase_basename(cell->file), (ulong) cell->line,
		difftime(time(NULL), cell->reservation_time));

	if (type == SYNC_MUTEX) {
		/* We use old_wait_mutex in case the cell has already
		been freed meanwhile */
		mutex = cell->old_wait_mutex;

		fprintf(file,
			"Mutex at %p created file %s line %lu, lock var %lu\n"
#ifdef UNIV_SYNC_DEBUG
			"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
			"waiters flag %lu\n",
			(void*) mutex, innobase_basename(mutex->cfile_name),
			(ulong) mutex->cline,
			(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
			mutex->file_name, (ulong) mutex->line,
#endif /* UNIV_SYNC_DEBUG */
			(ulong) mutex->waiters);

	} else if (type == RW_LOCK_EX
		   || type == RW_LOCK_WAIT_EX
		   || type == RW_LOCK_SHARED) {

		fputs(type == RW_LOCK_EX ? "X-lock on"
		      : type == RW_LOCK_WAIT_EX ? "X-lock (wait_ex) on"
		      : "S-lock on", file);

		rwlock = cell->old_wait_rw_lock;

		fprintf(file,
			" RW-latch at %p created in file %s line %lu\n",
			(void*) rwlock, innobase_basename(rwlock->cfile_name),
			(ulong) rwlock->cline);
		writer = rw_lock_get_writer(rwlock);
		if (writer != RW_LOCK_NOT_LOCKED) {
			fprintf(file,
				"a writer (thread id %lu) has"
				" reserved it in mode %s",
				(ulong) os_thread_pf(rwlock->writer_thread),
				writer == RW_LOCK_EX
				? " exclusive\n"
				: " wait exclusive\n");
		}

		fprintf(file,
			"number of readers %lu, waiters flag %lu, "
                        "lock_word: %lx\n"
			"Last time read locked in file %s line %lu\n"
			"Last time write locked in file %s line %lu\n",
			(ulong) rw_lock_get_reader_count(rwlock),
			(ulong) rwlock->waiters,
			rwlock->lock_word,
			innobase_basename(rwlock->last_s_file_name),
			(ulong) rwlock->last_s_line,
			rwlock->last_x_file_name,
			(ulong) rwlock->last_x_line);
	} else {
		ut_error;
	}

	if (!cell->waiting) {
		fputs("wait has ended\n", file);
	}
}
Esempio n. 12
0
void
rw_lock_x_lock_func(
    /*================*/
    rw_lock_t*	lock,	/* in: pointer to rw-lock */
    ulint		pass,	/* in: pass value; != 0, if the lock will
				be passed to another thread to unlock */
    const char*	file_name,/* in: file name where lock requested */
    ulint		line)	/* in: line where requested */
{
    ulint	index;	/* index of the reserved wait cell */
    ulint	state;	/* lock state acquired */
    ulint	i;	/* spin round count */

    ut_ad(rw_lock_validate(lock));

lock_loop:
    /* Acquire the mutex protecting the rw-lock fields */
    mutex_enter_fast(&(lock->mutex));

    state = rw_lock_x_lock_low(lock, pass, file_name, line);

    mutex_exit(&(lock->mutex));

    if (state == RW_LOCK_EX) {

        return;	/* Locking succeeded */

    } else if (state == RW_LOCK_NOT_LOCKED) {

        /* Spin waiting for the writer field to become free */
        i = 0;

        while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
                && i < SYNC_SPIN_ROUNDS) {
            if (srv_spin_wait_delay) {
                ut_delay(ut_rnd_interval(0,
                                         srv_spin_wait_delay));
            }

            i++;
        }
        if (i == SYNC_SPIN_ROUNDS) {
            os_thread_yield();
        }
    } else if (state == RW_LOCK_WAIT_EX) {

        /* Spin waiting for the reader count field to become zero */
        i = 0;

        while (rw_lock_get_reader_count(lock) != 0
                && i < SYNC_SPIN_ROUNDS) {
            if (srv_spin_wait_delay) {
                ut_delay(ut_rnd_interval(0,
                                         srv_spin_wait_delay));
            }

            i++;
        }
        if (i == SYNC_SPIN_ROUNDS) {
            os_thread_yield();
        }
    } else {
        i = 0; /* Eliminate a compiler warning */
        ut_error;
    }

    if (srv_print_latch_waits) {
        fprintf(stderr,
                "Thread %lu spin wait rw-x-lock at %p"
                " cfile %s cline %lu rnds %lu\n",
                os_thread_pf(os_thread_get_curr_id()), (void*) lock,
                lock->cfile_name, (ulong) lock->cline, (ulong) i);
    }

    rw_x_spin_wait_count++;

    /* We try once again to obtain the lock. Acquire the mutex protecting
    the rw-lock fields */

    mutex_enter(rw_lock_get_mutex(lock));

    state = rw_lock_x_lock_low(lock, pass, file_name, line);

    if (state == RW_LOCK_EX) {
        mutex_exit(rw_lock_get_mutex(lock));

        return;	/* Locking succeeded */
    }

    rw_x_system_call_count++;

    sync_array_reserve_cell(sync_primary_wait_array,
                            lock,
#ifdef __WIN__
                            /* On windows RW_LOCK_WAIT_EX signifies
                            that this thread should wait on the
                            special wait_ex_event. */
                            (state == RW_LOCK_WAIT_EX)
                            ? RW_LOCK_WAIT_EX :
#endif
                            RW_LOCK_EX,
                            file_name, line,
                            &index);

    rw_lock_set_waiters(lock, 1);

    mutex_exit(rw_lock_get_mutex(lock));

    if (srv_print_latch_waits) {
        fprintf(stderr,
                "Thread %lu OS wait for rw-x-lock at %p"
                " cfile %s cline %lu\n",
                os_thread_pf(os_thread_get_curr_id()), (void*) lock,
                lock->cfile_name, (ulong) lock->cline);
    }

    rw_x_system_call_count++;
    rw_x_os_wait_count++;

    sync_array_wait_event(sync_primary_wait_array, index);

    goto lock_loop;
}
Esempio n. 13
0
/**********************************************************************
Low-level function for acquiring an exclusive lock. */
UNIV_INLINE
ulint
rw_lock_x_lock_low(
    /*===============*/
    /* out: RW_LOCK_NOT_LOCKED if did
    not succeed, RW_LOCK_EX if success,
    RW_LOCK_WAIT_EX, if got wait reservation */
    rw_lock_t*	lock,	/* in: pointer to rw-lock */
    ulint		pass,	/* in: pass value; != 0, if the lock will
				be passed to another thread to unlock */
    const char*	file_name,/* in: file name where lock requested */
    ulint		line)	/* in: line where requested */
{
    ut_ad(mutex_own(rw_lock_get_mutex(lock)));

    if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {

        if (rw_lock_get_reader_count(lock) == 0) {

            rw_lock_set_writer(lock, RW_LOCK_EX);
            lock->writer_thread = os_thread_get_curr_id();
            lock->writer_count++;
            lock->pass = pass;

#ifdef UNIV_SYNC_DEBUG
            rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
                                   file_name, line);
#endif
            lock->last_x_file_name = file_name;
            lock->last_x_line = (unsigned int) line;

            /* Locking succeeded, we may return */
            return(RW_LOCK_EX);
        } else {
            /* There are readers, we have to wait */
            rw_lock_set_writer(lock, RW_LOCK_WAIT_EX);
            lock->writer_thread = os_thread_get_curr_id();
            lock->pass = pass;
            lock->writer_is_wait_ex = TRUE;

#ifdef UNIV_SYNC_DEBUG
            rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
                                   file_name, line);
#endif

            return(RW_LOCK_WAIT_EX);
        }

    } else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
               && os_thread_eq(lock->writer_thread,
                               os_thread_get_curr_id())) {

        if (rw_lock_get_reader_count(lock) == 0) {

            rw_lock_set_writer(lock, RW_LOCK_EX);
            lock->writer_count++;
            lock->pass = pass;
            lock->writer_is_wait_ex = FALSE;

#ifdef UNIV_SYNC_DEBUG
            rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
            rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
                                   file_name, line);
#endif

            lock->last_x_file_name = file_name;
            lock->last_x_line = (unsigned int) line;

            /* Locking succeeded, we may return */
            return(RW_LOCK_EX);
        }

        return(RW_LOCK_WAIT_EX);

    } else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
               && os_thread_eq(lock->writer_thread,
                               os_thread_get_curr_id())
               && (lock->pass == 0)
               && (pass == 0)) {

        lock->writer_count++;

#ifdef UNIV_SYNC_DEBUG
        rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
                               line);
#endif

        lock->last_x_file_name = file_name;
        lock->last_x_line = (unsigned int) line;

        /* Locking succeeded, we may return */
        return(RW_LOCK_EX);
    }

    /* Locking did not succeed */
    return(RW_LOCK_NOT_LOCKED);
}