Beispiel #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);
}
Beispiel #2
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
}
Beispiel #3
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);
}
Beispiel #4
0
/******************************************************************//**
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
rw-lock is checked to be in the non-locked state. */
UNIV_INTERN
void
rw_lock_free_func(
/*==============*/
	rw_lock_t*	lock)	/*!< in: rw-lock */
{
	ut_ad(rw_lock_validate(lock));
	ut_a(lock->lock_word == X_LOCK_DECR);

#ifndef INNODB_RW_LOCKS_USE_ATOMICS
	mutex_free(rw_lock_get_mutex(lock));
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */

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

	os_event_free(lock->wait_ex_event);

	ut_ad(UT_LIST_GET_PREV(list, lock) == NULL
	      || UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
	ut_ad(UT_LIST_GET_NEXT(list, lock) == NULL
	      || 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);

	ut_d(lock->magic_n = 0);
}
Beispiel #5
0
void
rw_lock_create_func(
    /*================*/
    rw_lock_t*	lock,		/* in: pointer to memory */
    char*		cfile_name,	/* in: file name where created */
    ulint		cline)		/* in: file line where created */
{
    /* If this is the very first time a synchronization
    object is created, then the following call initializes
    the sync system. */

    mutex_create(rw_lock_get_mutex(lock));
    mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);

    lock->mutex.cfile_name = cfile_name;
    lock->mutex.cline = cline;

    rw_lock_set_waiters(lock, 0);
    rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
    lock->writer_count = 0;
    rw_lock_set_reader_count(lock, 0);

    lock->writer_is_wait_ex = FALSE;

    UT_LIST_INIT(lock->debug_list);

    lock->magic_n = RW_LOCK_MAGIC_N;
    lock->level = SYNC_LEVEL_NONE;

    lock->cfile_name = cfile_name;
    lock->cline = cline;

    lock->last_s_file_name = "not yet reserved";
    lock->last_x_file_name = "not yet reserved";
    lock->last_s_line = 0;
    lock->last_x_line = 0;

    mutex_enter(&rw_lock_list_mutex);

    UT_LIST_ADD_FIRST(list, rw_lock_list, lock);

    mutex_exit(&rw_lock_list_mutex);
}
Beispiel #6
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);
}
Beispiel #7
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);
}
Beispiel #8
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;
}
Beispiel #9
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);
}
Beispiel #10
0
void
rw_lock_s_lock_spin(
    /*================*/
    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	 i;	/* spin round count */

    ut_ad(rw_lock_validate(lock));

lock_loop:
    rw_s_spin_wait_count++;

    /* 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();
    }

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

    mutex_enter(rw_lock_get_mutex(lock));

    /* We try once again to obtain the lock */

    if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
        mutex_exit(rw_lock_get_mutex(lock));

        return; /* Success */
    } else {
        /* If we get here, locking did not succeed, we may
        suspend the thread to wait in the wait array */

        rw_s_system_call_count++;

        sync_array_reserve_cell(sync_primary_wait_array,
                                lock, RW_LOCK_SHARED,
                                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 rw-s-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_s_system_call_count++;
        rw_s_os_wait_count++;

        sync_array_wait_event(sync_primary_wait_array, index);

        goto lock_loop;
    }
}
Beispiel #11
0
void
rw_lock_create_func(
    /*================*/
    rw_lock_t*	lock,		/* in: pointer to memory */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
    ulint		level,		/* in: level */
# endif /* UNIV_SYNC_DEBUG */
    const char*	cmutex_name, 	/* in: mutex name */
#endif /* UNIV_DEBUG */
    const char*	cfile_name,	/* in: file name where created */
    ulint 		cline)		/* in: file line where created */
{
    /* If this is the very first time a synchronization object is
    created, then the following call initializes the sync system. */

    mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);

    lock->mutex.cfile_name = cfile_name;
    lock->mutex.cline = cline;

#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
    lock->mutex.cmutex_name = cmutex_name;
    lock->mutex.mutex_type = 1;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */

    rw_lock_set_waiters(lock, 0);
    rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
    lock->writer_count = 0;
    rw_lock_set_reader_count(lock, 0);

    lock->writer_is_wait_ex = FALSE;

#ifdef UNIV_SYNC_DEBUG
    UT_LIST_INIT(lock->debug_list);

    lock->level = level;
#endif /* UNIV_SYNC_DEBUG */

    lock->magic_n = RW_LOCK_MAGIC_N;

    lock->cfile_name = cfile_name;
    lock->cline = (unsigned int) cline;

    lock->last_s_file_name = "not yet reserved";
    lock->last_x_file_name = "not yet reserved";
    lock->last_s_line = 0;
    lock->last_x_line = 0;
    lock->event = os_event_create(NULL);

#ifdef __WIN__
    lock->wait_ex_event = os_event_create(NULL);
#endif

    mutex_enter(&rw_lock_list_mutex);

    if (UT_LIST_GET_LEN(rw_lock_list) > 0) {
        ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n
             == RW_LOCK_MAGIC_N);
    }

    UT_LIST_ADD_FIRST(list, rw_lock_list, lock);

    mutex_exit(&rw_lock_list_mutex);
}
Beispiel #12
0
/******************************************************************//**
Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */
UNIV_INTERN
void
rw_lock_create_func(
/*================*/
	rw_lock_t*	lock,		/*!< in: pointer to memory */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
	ulint		level,		/*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
	const char*	cmutex_name,	/*!< in: mutex name */
#endif /* UNIV_DEBUG */
	const char*	cfile_name,	/*!< in: file name where created */
	ulint		cline)		/*!< in: file line where created */
{
	/* If this is the very first time a synchronization object is
	created, then the following call initializes the sync system. */

#ifndef INNODB_RW_LOCKS_USE_ATOMICS
	mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
		     SYNC_NO_ORDER_CHECK);

	lock->mutex.cfile_name = cfile_name;
	lock->mutex.cline = cline;

	ut_d(lock->mutex.cmutex_name = cmutex_name);
	ut_d(lock->mutex.mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
	UT_NOT_USED(cmutex_name);
# endif
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */

	lock->lock_word = X_LOCK_DECR;
	lock->waiters = 0;

	/* We set this value to signify that lock->writer_thread
	contains garbage at initialization and cannot be used for
	recursive x-locking. */
	lock->recursive = FALSE;
	/* Silence Valgrind when UNIV_DEBUG_VALGRIND is not enabled. */
	memset((void*) &lock->writer_thread, 0, sizeof lock->writer_thread);
	UNIV_MEM_INVALID(&lock->writer_thread, sizeof lock->writer_thread);

#ifdef UNIV_SYNC_DEBUG
	UT_LIST_INIT(lock->debug_list);

	lock->level = level;
#endif /* UNIV_SYNC_DEBUG */

	ut_d(lock->magic_n = RW_LOCK_MAGIC_N);

	lock->cfile_name = cfile_name;
	lock->cline = (unsigned int) cline;

	lock->count_os_wait = 0;
	lock->last_s_file_name = "not yet reserved";
	lock->last_x_file_name = "not yet reserved";
	lock->last_s_line = 0;
	lock->last_x_line = 0;
	lock->event = os_event_create(NULL);
	lock->wait_ex_event = os_event_create(NULL);

	mutex_enter(&rw_lock_list_mutex);

	ut_ad(UT_LIST_GET_FIRST(rw_lock_list) == NULL
	      || UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N);

	UT_LIST_ADD_FIRST(list, rw_lock_list, lock);

	mutex_exit(&rw_lock_list_mutex);
}