diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 5bc4ea7c30381444de202b3b1a3ef640941eae4f..3e802360d233788f26758934a76cc3f9ee849f2f 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,9 @@
+2010-07-27	The InnoDB Team
+
+	* include/mem0pool.h, mem/mem0mem.c, mem/mem0pool.c, srv/srv0start.c:
+	Fix Bug#55581 shutdown with innodb-use-sys-malloc=0: assert
+	mutex->magic_n == MUTEX_MAGIC_N.
+
 2010-06-30	The InnoDB Team
 
 	* btr/btr0sea.c, ha/ha0ha.c, handler/ha_innodb.cc, include/btr0sea.h:
diff --git a/storage/innodb_plugin/include/mem0pool.h b/storage/innodb_plugin/include/mem0pool.h
index 5e93bf88a4726beefdc5cf9cfe59c5c42bf38097..fa8be296ec90694949b182ea9e2c86ea050c631b 100644
--- a/storage/innodb_plugin/include/mem0pool.h
+++ b/storage/innodb_plugin/include/mem0pool.h
@@ -100,18 +100,6 @@ mem_pool_get_reserved(
 /*==================*/
 	mem_pool_t*	pool);	/*!< in: memory pool */
 /********************************************************************//**
-Reserves the mem pool mutex. */
-UNIV_INTERN
-void
-mem_pool_mutex_enter(void);
-/*======================*/
-/********************************************************************//**
-Releases the mem pool mutex. */
-UNIV_INTERN
-void
-mem_pool_mutex_exit(void);
-/*=====================*/
-/********************************************************************//**
 Validates a memory pool.
 @return	TRUE if ok */
 UNIV_INTERN
diff --git a/storage/innodb_plugin/mem/mem0mem.c b/storage/innodb_plugin/mem/mem0mem.c
index c0ce8a3e1aca1e1d13c77c6da87839ccde9cf2af..1dd4db3084105f9292fcedd9df06383dea79278d 100644
--- a/storage/innodb_plugin/mem/mem0mem.c
+++ b/storage/innodb_plugin/mem/mem0mem.c
@@ -367,7 +367,7 @@ mem_heap_create_block(
 	block->line = line;
 
 #ifdef MEM_PERIODIC_CHECK
-	mem_pool_mutex_enter();
+	mutex_enter(&(mem_comm_pool->mutex));
 
 	if (!mem_block_list_inited) {
 		mem_block_list_inited = TRUE;
@@ -376,7 +376,7 @@ mem_heap_create_block(
 
 	UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
 
-	mem_pool_mutex_exit();
+	mutex_exit(&(mem_comm_pool->mutex));
 #endif
 	mem_block_set_len(block, len);
 	mem_block_set_type(block, type);
@@ -479,11 +479,11 @@ mem_heap_block_free(
 	UT_LIST_REMOVE(list, heap->base, block);
 
 #ifdef MEM_PERIODIC_CHECK
-	mem_pool_mutex_enter();
+	mutex_enter(&(mem_comm_pool->mutex));
 
 	UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
 
-	mem_pool_mutex_exit();
+	mutex_exit(&(mem_comm_pool->mutex));
 #endif
 
 	ut_ad(heap->total_size >= block->len);
@@ -556,7 +556,7 @@ mem_validate_all_blocks(void)
 {
 	mem_block_t*	block;
 
-	mem_pool_mutex_enter();
+	mutex_enter(&(mem_comm_pool->mutex));
 
 	block = UT_LIST_GET_FIRST(mem_block_list);
 
@@ -568,6 +568,6 @@ mem_validate_all_blocks(void)
 		block = UT_LIST_GET_NEXT(mem_block_list, block);
 	}
 
-	mem_pool_mutex_exit();
+	mutex_exit(&(mem_comm_pool->mutex));
 }
 #endif
diff --git a/storage/innodb_plugin/mem/mem0pool.c b/storage/innodb_plugin/mem/mem0pool.c
index c4f8af607e07f05eb6d818fa45ea2243f1dac506..3291453eeb56bd3cf9e1e052dd76f1ed7bbc3326 100644
--- a/storage/innodb_plugin/mem/mem0pool.c
+++ b/storage/innodb_plugin/mem/mem0pool.c
@@ -34,6 +34,7 @@ Created 5/12/1997 Heikki Tuuri
 #include "ut0lst.h"
 #include "ut0byte.h"
 #include "mem0mem.h"
+#include "srv0start.h"
 
 /* We would like to use also the buffer frames to allocate memory. This
 would be desirable, because then the memory consumption of the database
@@ -121,23 +122,33 @@ mysql@lists.mysql.com */
 UNIV_INTERN ulint	mem_n_threads_inside		= 0;
 
 /********************************************************************//**
-Reserves the mem pool mutex. */
-UNIV_INTERN
+Reserves the mem pool mutex if we are not in server shutdown. Use
+this function only in memory free functions, since only memory
+free functions are used during server shutdown. */
+UNIV_INLINE
 void
-mem_pool_mutex_enter(void)
-/*======================*/
+mem_pool_mutex_enter(
+/*=================*/
+	mem_pool_t*	pool)		/*!< in: memory pool */
 {
-	mutex_enter(&(mem_comm_pool->mutex));
+	if (srv_shutdown_state < SRV_SHUTDOWN_EXIT_THREADS) {
+		mutex_enter(&(pool->mutex));
+	}
 }
 
 /********************************************************************//**
-Releases the mem pool mutex. */
-UNIV_INTERN
+Releases the mem pool mutex if we are not in server shutdown. As
+its corresponding mem_pool_mutex_enter() function, use it only
+in memory free functions */
+UNIV_INLINE
 void
-mem_pool_mutex_exit(void)
-/*=====================*/
+mem_pool_mutex_exit(
+/*================*/
+	mem_pool_t*	pool)		/*!< in: memory pool */
 {
-	mutex_exit(&(mem_comm_pool->mutex));
+	if (srv_shutdown_state < SRV_SHUTDOWN_EXIT_THREADS) {
+		mutex_exit(&(pool->mutex));
+	}
 }
 
 /********************************************************************//**
@@ -567,7 +578,7 @@ mem_area_free(
 
 	n = ut_2_log(size);
 
-	mutex_enter(&(pool->mutex));
+	mem_pool_mutex_enter(pool);
 	mem_n_threads_inside++;
 
 	ut_a(mem_n_threads_inside == 1);
@@ -595,7 +606,7 @@ mem_area_free(
 		pool->reserved += ut_2_exp(n);
 
 		mem_n_threads_inside--;
-		mutex_exit(&(pool->mutex));
+		mem_pool_mutex_exit(pool);
 
 		mem_area_free(new_ptr, pool);
 
@@ -611,7 +622,7 @@ mem_area_free(
 	}
 
 	mem_n_threads_inside--;
-	mutex_exit(&(pool->mutex));
+	mem_pool_mutex_exit(pool);
 
 	ut_ad(mem_pool_validate(pool));
 }
@@ -630,7 +641,7 @@ mem_pool_validate(
 	ulint		free;
 	ulint		i;
 
-	mutex_enter(&(pool->mutex));
+	mem_pool_mutex_enter(pool);
 
 	free = 0;
 
@@ -658,7 +669,7 @@ mem_pool_validate(
 
 	ut_a(free + pool->reserved == pool->size);
 
-	mutex_exit(&(pool->mutex));
+	mem_pool_mutex_exit(pool);
 
 	return(TRUE);
 }
diff --git a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
index e517b9a86b0dc0ae03611ad3cfcbbb1c0137a098..ba9fc831b39d42960ad564a5eb0b4919a9069de2 100644
--- a/storage/innodb_plugin/srv/srv0start.c
+++ b/storage/innodb_plugin/srv/srv0start.c
@@ -2018,9 +2018,13 @@ innobase_shutdown_for_mysql(void)
 	pars_lexer_close();
 	log_mem_free();
 	buf_pool_free();
-	ut_free_all_mem();
 	mem_close();
 
+	/* ut_free_all_mem() frees all allocated memory not freed yet
+	in shutdown, and it will also free the ut_list_mutex, so it
+	should be the last one for all operation */
+	ut_free_all_mem();
+
 	if (os_thread_count != 0
 	    || os_event_count != 0
 	    || os_mutex_count != 0