Example #1
0
/****************************************************************//**
Frees large pages memory. */
UNIV_INTERN
void
os_mem_free_large(
/*==============*/
	void	*ptr,			/*!< in: pointer returned by
					os_mem_alloc_large() */
	ulint	size)			/*!< in: size returned by
					os_mem_alloc_large() */
{
	os_fast_mutex_lock(&ut_list_mutex);
	ut_a(ut_total_allocated_memory >= size);
	os_fast_mutex_unlock(&ut_list_mutex);

#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
	if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
		os_fast_mutex_lock(&ut_list_mutex);
		ut_a(ut_total_allocated_memory >= size);
		ut_total_allocated_memory -= size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_FREE(ptr, size);
		return;
	}
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
#ifdef __WIN__
	/* When RELEASE memory, the size parameter must be 0.
	Do not use MEM_RELEASE with MEM_DECOMMIT. */
	if (!VirtualFree(ptr, 0, MEM_RELEASE)) {
		fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
			" Windows error %lu\n",
			ptr, (ulong) size, (ulong) GetLastError());
	} else {
		os_fast_mutex_lock(&ut_list_mutex);
		ut_a(ut_total_allocated_memory >= size);
		ut_total_allocated_memory -= size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_FREE(ptr, size);
	}
#elif !defined OS_MAP_ANON
	ut_free(ptr);
#else
	if (munmap(ptr, size)) {
		fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
			" errno %lu\n",
			ptr, (ulong) size, (ulong) errno);
	} else {
		os_fast_mutex_lock(&ut_list_mutex);
		ut_a(ut_total_allocated_memory >= size);
		ut_total_allocated_memory -= size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_FREE(ptr, size);
	}
#endif
}
Example #2
0
/**********************************************************************//**
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
a nop. */
UNIV_INTERN
void
ut_free(
/*====*/
	void* ptr)  /*!< in, own: memory block, can be NULL */
{
#ifndef UNIV_HOTBACKUP
	ut_mem_block_t* block;

	if (ptr == NULL) {
		return;
	} else if (UNIV_LIKELY(srv_use_sys_malloc)) {
		free(ptr);
		return;
	}

	block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t));

	os_fast_mutex_lock(&ut_list_mutex);

	ut_a(block->magic_n == UT_MEM_MAGIC_N);
	ut_a(ut_total_allocated_memory >= block->size);

	ut_total_allocated_memory -= block->size;

	UT_LIST_REMOVE(mem_block_list, ut_mem_block_list, block);
	free(block);

	os_fast_mutex_unlock(&ut_list_mutex);
#else /* !UNIV_HOTBACKUP */
	free(ptr);
#endif /* !UNIV_HOTBACKUP */
}
Example #3
0
/**********************************************************//**
Acquires ownership of a mutex semaphore. */
UNIV_INTERN
void
os_mutex_enter(
/*===========*/
	os_mutex_t	mutex)	/*!< in: mutex to acquire */
{
#ifdef __WIN__
	DWORD	err;

	ut_a(mutex);

	/* Specify infinite time limit for waiting */
	err = WaitForSingleObject(mutex->handle, INFINITE);

	ut_a(err == WAIT_OBJECT_0);

	(mutex->count)++;
	ut_a(mutex->count == 1);
#else
	os_fast_mutex_lock(mutex->handle);

	(mutex->count)++;

	ut_a(mutex->count == 1);
#endif
}
Example #4
0
/**********************************************************//**
Resets an event semaphore to the nonsignaled state. Waiting threads will
stop to wait for the event.
The return value should be passed to os_even_wait_low() if it is desired
that this thread should not wait in case of an intervening call to
os_event_set() between this os_event_reset() and the
os_event_wait_low() call. See comments for os_event_wait_low().
@return	current signal_count. */
UNIV_INTERN
ib_int64_t
os_event_reset(
/*===========*/
	os_event_t	event)	/*!< in: event to reset */
{
	ib_int64_t	ret = 0;

#ifdef __WIN__
	ut_a(event);

	ut_a(ResetEvent(event->handle));
#else
	ut_a(event);

	os_fast_mutex_lock(&(event->os_mutex));

	if (!event->is_set) {
		/* Do nothing */
	} else {
		event->is_set = FALSE;
	}
	ret = event->signal_count;

	os_fast_mutex_unlock(&(event->os_mutex));
#endif
	return(ret);
}
Example #5
0
/**********************************************************//**
Sets an event semaphore to the signaled state: lets waiting threads
proceed. */
UNIV_INTERN
void
os_event_set(
/*=========*/
	os_event_t	event)	/*!< in: event to set */
{
#ifdef __WIN__
	ut_a(event);
	ut_a(SetEvent(event->handle));
#else
	ut_a(event);

	os_fast_mutex_lock(&(event->os_mutex));

	if (event->is_set) {
		/* Do nothing */
	} else {
		event->is_set = TRUE;
		event->signal_count += 1;
		ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
	}

	os_fast_mutex_unlock(&(event->os_mutex));
#endif
}
Example #6
0
/**********************************************************//**
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state).

Typically, if the event has been signalled after the os_event_reset()
we'll return immediately because event->is_set == TRUE.
There are, however, situations (e.g.: sync_array code) where we may
lose this information. For example:

thread A calls os_event_reset()
thread B calls os_event_set()   [event->is_set == TRUE]
thread C calls os_event_reset() [event->is_set == FALSE]
thread A calls os_event_wait()  [infinite wait!]
thread C calls os_event_wait()  [infinite wait!]

Where such a scenario is possible, to avoid infinite wait, the
value returned by os_event_reset() should be passed in as
reset_sig_count. */
UNIV_INTERN
void
os_event_wait_low(
/*==============*/
	os_event_t	event,		/*!< in: event to wait */
	ib_int64_t	reset_sig_count)/*!< in: zero or the value
					returned by previous call of
					os_event_reset(). */
{
#ifdef __WIN__
	DWORD	err;

	ut_a(event);

	UT_NOT_USED(reset_sig_count);

	/* Specify an infinite time limit for waiting */
	err = WaitForSingleObject(event->handle, INFINITE);

	ut_a(err == WAIT_OBJECT_0);

	if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
		os_thread_exit(NULL);
	}
#else
	ib_int64_t	old_signal_count;

	os_fast_mutex_lock(&(event->os_mutex));

	if (reset_sig_count) {
		old_signal_count = reset_sig_count;
	} else {
		old_signal_count = event->signal_count;
	}

	for (;;) {
		if (event->is_set == TRUE
		    || event->signal_count != old_signal_count) {

			os_fast_mutex_unlock(&(event->os_mutex));

			if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {

				os_thread_exit(NULL);
			}
			/* Ok, we may return */

			return;
		}

		pthread_cond_wait(&(event->cond_var), &(event->os_mutex));

		/* Solaris manual said that spurious wakeups may occur: we
		have to check if the event really has been signaled after
		we came here to wait */
	}
#endif
}
Example #7
0
ib_err_t
ib_cfg_shutdown(void)
/*=================*/
{
	os_fast_mutex_lock(&cfg_vars_mutex);

	/* TODO: Check for NULL values of allocated config variables. */
	memset(cfg_vars, 0x0, sizeof(cfg_vars));

	os_fast_mutex_unlock(&cfg_vars_mutex);

	os_fast_mutex_free(&cfg_vars_mutex);

	return(DB_SUCCESS);
}
Example #8
0
ib_err_t
ib_cfg_get(
/*=======*/
	const char*	name,		/*!< in: variable name */
	void*		value)		/*!< out: pointer to the place to
					store the retrieved value */
{
	ib_cfg_var_t*	cfg_var;
	ib_err_t	ret;

	os_fast_mutex_lock(&cfg_vars_mutex);

	cfg_var = ib_cfg_lookup_var(name);

	if (cfg_var != NULL) {
		ret = cfg_var->get(cfg_var, value);
	} else {
		ret = DB_NOT_FOUND;
	}

	os_fast_mutex_unlock(&cfg_vars_mutex);

	return(ret);
}
Example #9
0
ib_err_t
ib_cfg_var_get_type(
/*================*/
	const char*	name,		/*!< in: variable name */
	ib_cfg_type_t*	type)		/*!< out: variable type */
{
	ib_cfg_var_t*	cfg_var;
	ib_err_t	ret;

	os_fast_mutex_lock(&cfg_vars_mutex);

	cfg_var = ib_cfg_lookup_var(name);

	if (cfg_var != NULL) {
		*type = cfg_var->type;
		ret = DB_SUCCESS;
	} else {
		ret = DB_NOT_FOUND;
	}

	os_fast_mutex_unlock(&cfg_vars_mutex);

	return(ret);
}
Example #10
0
/**********************************************************************//**
Allocates memory.
@return	own: allocated memory */
UNIV_INTERN
void*
ut_malloc_low(
/*==========*/
	ulint	n,		/*!< in: number of bytes to allocate */
	ibool	assert_on_error)/*!< in: if TRUE, we crash mysqld if the
				memory cannot be allocated */
{
#ifndef UNIV_HOTBACKUP
	ulint	retry_count;
	void*	ret;

	if (UNIV_LIKELY(srv_use_sys_malloc)) {
		ret = malloc(n);
		ut_a(ret || !assert_on_error);

		return(ret);
	}

	ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */
	ut_a(ut_mem_block_list_inited);

	retry_count = 0;
retry:
	os_fast_mutex_lock(&ut_list_mutex);

	ret = malloc(n + sizeof(ut_mem_block_t));

	if (ret == NULL && retry_count < 60) {
		if (retry_count == 0) {
			ut_print_timestamp(stderr);

			fprintf(stderr,
				"  InnoDB: Error: cannot allocate"
				" %lu bytes of\n"
				"InnoDB: memory with malloc!"
				" Total allocated memory\n"
				"InnoDB: by InnoDB %lu bytes."
				" Operating system errno: %lu\n"
				"InnoDB: Check if you should"
				" increase the swap file or\n"
				"InnoDB: ulimits of your operating system.\n"
				"InnoDB: On FreeBSD check you"
				" have compiled the OS with\n"
				"InnoDB: a big enough maximum process size.\n"
				"InnoDB: Note that in most 32-bit"
				" computers the process\n"
				"InnoDB: memory space is limited"
				" to 2 GB or 4 GB.\n"
				"InnoDB: We keep retrying"
				" the allocation for 60 seconds...\n",
				(ulong) n, (ulong) ut_total_allocated_memory,
#ifdef __WIN__
				(ulong) GetLastError()
#else
				(ulong) errno
#endif
				);
		}

		os_fast_mutex_unlock(&ut_list_mutex);

		/* Sleep for a second and retry the allocation; maybe this is
		just a temporary shortage of memory */

		os_thread_sleep(1000000);

		retry_count++;

		goto retry;
	}

	if (ret == NULL) {
		/* Flush stderr to make more probable that the error
		message gets in the error file before we generate a seg
		fault */

		fflush(stderr);

		os_fast_mutex_unlock(&ut_list_mutex);

		/* Make an intentional seg fault so that we get a stack
		trace */
		if (assert_on_error) {
			ut_print_timestamp(stderr);

			fprintf(stderr,
				"  InnoDB: We now intentionally"
				" generate a seg fault so that\n"
				"InnoDB: on Linux we get a stack trace.\n");

			if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
		} else {
			return(NULL);
		}
	}

	UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t));

	((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t);
	((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N;

	ut_total_allocated_memory += n + sizeof(ut_mem_block_t);

	UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list,
			  ((ut_mem_block_t*)ret));
	os_fast_mutex_unlock(&ut_list_mutex);

	return((void*)((byte*)ret + sizeof(ut_mem_block_t)));
#else /* !UNIV_HOTBACKUP */
	void*	ret = malloc(n);
	ut_a(ret || !assert_on_error);

	return(ret);
#endif /* !UNIV_HOTBACKUP */
}
Example #11
0
/*********************************************************************//**
Set a configuration variable. "ap" must contain one argument whose type
depends on the type of the variable with the given "name". Returns
DB_SUCCESS if the variable with name "name" was found and if its value
was set.
ib_cfg_set_ap() @{
@return	DB_SUCCESS if set */
static
ib_err_t
ib_cfg_set_ap(
/*==========*/
	const char*	name,		/*!< in: variable name */
	va_list		ap)		/*!< in: variable value */
{
	ib_cfg_var_t*	cfg_var;
	ib_err_t	ret = DB_NOT_FOUND;

	os_fast_mutex_lock(&cfg_vars_mutex);

	cfg_var = ib_cfg_lookup_var(name);

	if (cfg_var != NULL) {

		/* check whether setting the variable is appropriate,
		according to its flag */
		if (cfg_var->flag & IB_CFG_FLAG_READONLY
		    || (cfg_var->flag & IB_CFG_FLAG_READONLY_AFTER_STARTUP
			&& srv_was_started)) {

			ret = DB_READONLY;
		} else {

			/* Get the parameter according to its type and
			call ::set() */
			switch (cfg_var->type) {
			case IB_CFG_IBOOL: {
				ib_bool_t	value;

				value = va_arg(ap, ib_bool_t);

				ret = cfg_var->set(cfg_var, &value);

				break;
			}

			case IB_CFG_ULINT: {
				ulint	value;

				value = va_arg(ap, ulint);

				ret = cfg_var->set(cfg_var, &value);

				break;
			}

			case IB_CFG_ULONG: {
				ulong	value;

				value = va_arg(ap, ulong);

				ret = cfg_var->set(cfg_var, &value);

				break;
			}

			case IB_CFG_TEXT: {
				const char*	value;

				value = va_arg(ap, const char*);

				ret = cfg_var->set(cfg_var, &value);

				break;
			}

			case IB_CFG_CB: {
				ib_cb_t	value;

				value = va_arg(ap, ib_cb_t);

				ret = cfg_var->set(cfg_var, &value);

				break;
			}
			/* do not add default: in order to produce a
			compilation warning if new type is added which is
			not handled here */
			}
		}
	}
	
	os_fast_mutex_unlock(&cfg_vars_mutex);

	return(ret);
}
Example #12
0
/****************************************************************//**
Allocates large pages memory.
@return	allocated memory */
UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
	ulint*	n)			/*!< in/out: number of bytes */
{
	void*	ptr;
	ulint	size;
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
	int shmid;
	struct shmid_ds buf;

	if (!os_use_large_pages || !os_large_page_size) {
		goto skip;
	}

	/* Align block size to os_large_page_size */
	ut_ad(ut_is_2pow(os_large_page_size));
	size = ut_2pow_round(*n + (os_large_page_size - 1),
			     os_large_page_size);

	shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
	if (shmid < 0) {
		fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate"
			" %lu bytes. errno %d\n", size, errno);
		ptr = NULL;
	} else {
		ptr = shmat(shmid, NULL, 0);
		if (ptr == (void *)-1) {
			fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
				" attach shared memory segment, errno %d\n",
				errno);
			ptr = NULL;
		}

		/* Remove the shared memory segment so that it will be
		automatically freed after memory is detached or
		process exits */
		shmctl(shmid, IPC_RMID, &buf);
	}

	if (ptr) {
		*n = size;
		os_fast_mutex_lock(&ut_list_mutex);
		ut_total_allocated_memory += size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_ALLOC(ptr, size);
		return(ptr);
	}

	fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
		" memory pool\n");
skip:
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */

#ifdef __WIN__
	SYSTEM_INFO	system_info;
	GetSystemInfo(&system_info);

	/* Align block size to system page size */
	ut_ad(ut_is_2pow(system_info.dwPageSize));
	/* system_info.dwPageSize is only 32-bit. Casting to ulint is required
	on 64-bit Windows. */
	size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
				  (ulint) system_info.dwPageSize);
	ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
			   PAGE_READWRITE);
	if (!ptr) {
		fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
			" Windows error %lu\n",
			(ulong) size, (ulong) GetLastError());
	} else {
		os_fast_mutex_lock(&ut_list_mutex);
		ut_total_allocated_memory += size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_ALLOC(ptr, size);
	}
#elif !defined OS_MAP_ANON
	size = *n;
	ptr = ut_malloc_low(size, TRUE, FALSE);
#else
# ifdef HAVE_GETPAGESIZE
	size = getpagesize();
# else
	size = UNIV_PAGE_SIZE;
# endif
	/* Align block size to system page size */
	ut_ad(ut_is_2pow(size));
	size = *n = ut_2pow_round(*n + (size - 1), size);
	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
		   MAP_PRIVATE | OS_MAP_ANON, -1, 0);
	if (UNIV_UNLIKELY(ptr == (void*) -1)) {
		fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
			" errno %lu\n",
			(ulong) size, (ulong) errno);
		ptr = NULL;
	} else {
		os_fast_mutex_lock(&ut_list_mutex);
		ut_total_allocated_memory += size;
		os_fast_mutex_unlock(&ut_list_mutex);
		UNIV_MEM_ALLOC(ptr, size);
	}
#endif
	return(ptr);
}