Commit 732f9dd7 authored by marko's avatar marko

branches/zip: Protect ut_total_allocated_memory with ut_list_mutex.

Unprotected updates to ut_total_allocated_memory in
os_mem_alloc_large() and os_mem_free_large(), called during
fast index creation, may corrupt the variable and cause assertion failures.

Also, add UNIV_MEM_ALLOC() and UNIV_MEM_FREE() instrumentation around
os_mem_alloc_large() and os_mem_free_large(), so that Valgrind can
detect more errors.

rb://90 approved by Heikki Tuuri.  This addresses Issue #177.
parent b10078d3
2009-02-18 The InnoDB Team
* os/os0proc.c, ut/ut0mem.c, include/ut0mem.h:
Protect ut_total_allocated_memory with ut_list_mutex in
os_mem_alloc_large() and os_mem_free_large(). The lack of this
mutex protection could cause an assertion failure during fast
index creation. Also, add UNIV_MEM_ALLOC and UNIV_MEM_FREE
instrumentation to os_mem_alloc_large() and os_mem_free_large(),
so that Valgrind can detect more errors.
2009-02-11 The InnoDB Team 2009-02-11 The InnoDB Team
* handler/ha_innodb.cc: * handler/ha_innodb.cc:
......
...@@ -26,12 +26,17 @@ Created 5/30/1994 Heikki Tuuri ...@@ -26,12 +26,17 @@ Created 5/30/1994 Heikki Tuuri
#define ut0mem_h #define ut0mem_h
#include "univ.i" #include "univ.i"
#include "os0sync.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
/* The total amount of memory currently allocated from the OS with malloc */ /* The total amount of memory currently allocated from the operating
system with os_mem_alloc_large() or malloc(). Does not count malloc()
if srv_use_sys_malloc is set. Protected by ut_list_mutex. */
extern ulint ut_total_allocated_memory; extern ulint ut_total_allocated_memory;
/* Mutex protecting ut_total_allocated_memory and ut_mem_block_list */
extern os_fast_mutex_t ut_list_mutex;
UNIV_INLINE UNIV_INLINE
void* void*
ut_memcpy(void* dest, const void* sour, ulint n); ut_memcpy(void* dest, const void* sour, ulint n);
......
...@@ -127,10 +127,13 @@ os_mem_alloc_large( ...@@ -127,10 +127,13 @@ os_mem_alloc_large(
if (ptr) { if (ptr) {
*n = size; *n = size;
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size; ut_total_allocated_memory += size;
os_fast_mutex_unlock(&ut_list_mutex);
# ifdef UNIV_SET_MEM_TO_ZERO # ifdef UNIV_SET_MEM_TO_ZERO
memset(ptr, '\0', size); memset(ptr, '\0', size);
# endif # endif
UNIV_MEM_ALLOC(ptr, size);
return(ptr); return(ptr);
} }
...@@ -156,7 +159,10 @@ skip: ...@@ -156,7 +159,10 @@ skip:
" Windows error %lu\n", " Windows error %lu\n",
(ulong) size, (ulong) GetLastError()); (ulong) size, (ulong) GetLastError());
} else { } else {
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size; ut_total_allocated_memory += size;
os_fast_mutex_unlock(&ut_list_mutex);
UNIV_MEM_ALLOC(ptr, size);
} }
#elif defined __NETWARE__ || !defined OS_MAP_ANON #elif defined __NETWARE__ || !defined OS_MAP_ANON
size = *n; size = *n;
...@@ -178,7 +184,10 @@ skip: ...@@ -178,7 +184,10 @@ skip:
(ulong) size, (ulong) errno); (ulong) size, (ulong) errno);
ptr = NULL; ptr = NULL;
} else { } else {
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size; ut_total_allocated_memory += size;
os_fast_mutex_unlock(&ut_list_mutex);
UNIV_MEM_ALLOC(ptr, size);
} }
#endif #endif
return(ptr); return(ptr);
...@@ -195,11 +204,17 @@ os_mem_free_large( ...@@ -195,11 +204,17 @@ os_mem_free_large(
ulint size) /* in: size returned by ulint size) /* in: size returned by
os_mem_alloc_large() */ os_mem_alloc_large() */
{ {
os_fast_mutex_lock(&ut_list_mutex);
ut_a(ut_total_allocated_memory >= size); ut_a(ut_total_allocated_memory >= size);
os_fast_mutex_unlock(&ut_list_mutex);
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) { 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; ut_total_allocated_memory -= size;
os_fast_mutex_unlock(&ut_list_mutex);
UNIV_MEM_FREE(ptr, size);
return; return;
} }
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */ #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
...@@ -211,7 +226,11 @@ os_mem_free_large( ...@@ -211,7 +226,11 @@ os_mem_free_large(
" Windows error %lu\n", " Windows error %lu\n",
ptr, (ulong) size, (ulong) GetLastError()); ptr, (ulong) size, (ulong) GetLastError());
} else { } else {
os_fast_mutex_lock(&ut_list_mutex);
ut_a(ut_total_allocated_memory >= size);
ut_total_allocated_memory -= size; ut_total_allocated_memory -= size;
os_fast_mutex_unlock(&ut_list_mutex);
UNIV_MEM_FREE(ptr, size);
} }
#elif defined __NETWARE__ || !defined OS_MAP_ANON #elif defined __NETWARE__ || !defined OS_MAP_ANON
ut_free(ptr); ut_free(ptr);
...@@ -221,7 +240,11 @@ os_mem_free_large( ...@@ -221,7 +240,11 @@ os_mem_free_large(
" errno %lu\n", " errno %lu\n",
ptr, (ulong) size, (ulong) errno); ptr, (ulong) size, (ulong) errno);
} else { } else {
os_fast_mutex_lock(&ut_list_mutex);
ut_a(ut_total_allocated_memory >= size);
ut_total_allocated_memory -= size; ut_total_allocated_memory -= size;
os_fast_mutex_unlock(&ut_list_mutex);
UNIV_MEM_FREE(ptr, size);
} }
#endif #endif
} }
......
...@@ -29,16 +29,22 @@ Created 5/11/1994 Heikki Tuuri ...@@ -29,16 +29,22 @@ Created 5/11/1994 Heikki Tuuri
#endif #endif
#include "mem0mem.h" #include "mem0mem.h"
#include "os0sync.h"
#include "os0thread.h" #include "os0thread.h"
#include "srv0srv.h" #include "srv0srv.h"
#include <stdlib.h>
/* This struct is placed first in every allocated memory block */ /* This struct is placed first in every allocated memory block */
typedef struct ut_mem_block_struct ut_mem_block_t; typedef struct ut_mem_block_struct ut_mem_block_t;
/* The total amount of memory currently allocated from the OS with malloc */ /* The total amount of memory currently allocated from the operating
system with os_mem_alloc_large() or malloc(). Does not count malloc()
if srv_use_sys_malloc is set. Protected by ut_list_mutex. */
UNIV_INTERN ulint ut_total_allocated_memory = 0; UNIV_INTERN ulint ut_total_allocated_memory = 0;
/* Mutex protecting ut_total_allocated_memory and ut_mem_block_list */
UNIV_INTERN os_fast_mutex_t ut_list_mutex;
struct ut_mem_block_struct{ struct ut_mem_block_struct{
UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; UT_LIST_NODE_T(ut_mem_block_t) mem_block_list;
/* mem block list node */ /* mem block list node */
...@@ -49,11 +55,9 @@ struct ut_mem_block_struct{ ...@@ -49,11 +55,9 @@ struct ut_mem_block_struct{
#define UT_MEM_MAGIC_N 1601650166 #define UT_MEM_MAGIC_N 1601650166
/* List of all memory blocks allocated from the operating system /* List of all memory blocks allocated from the operating system
with malloc */ with malloc. Protected by ut_list_mutex. */
static UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list; static UT_LIST_BASE_NODE_T(ut_mem_block_t) ut_mem_block_list;
static os_fast_mutex_t ut_list_mutex; /* this protects the list */
static ibool ut_mem_block_list_inited = FALSE; static ibool ut_mem_block_list_inited = FALSE;
static ulint* ut_mem_null_ptr = NULL; static ulint* ut_mem_null_ptr = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment