summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc60
1 files changed, 36 insertions, 24 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 523e835f472..388abd99bd5 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -288,6 +288,11 @@ If join_results allocated new block(s) then we need call pack_cache again.
pthread_mutex_lock(M);}
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
+#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
+ DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
+ sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
+#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \
+ sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); }
#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \
@@ -310,6 +315,8 @@ If join_results allocated new block(s) then we need call pack_cache again.
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
+#define SEM_LOCK(M) sem_wait(M)
+#define SEM_UNLOCK(M) sem_post(M)
#define STRUCT_LOCK(M) pthread_mutex_lock(M)
#define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
#define BLOCK_LOCK_WR(B) B->query()->lock_writing()
@@ -426,7 +433,7 @@ void Query_cache_query::init_n_lock()
{
DBUG_ENTER("Query_cache_query::init_n_lock");
res=0; wri = 0; len = 0;
- pthread_cond_init(&lock, NULL);
+ sem_init(&lock, 0, 1);
pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
clients = 0;
lock_writing();
@@ -446,7 +453,7 @@ void Query_cache_query::unlock_n_destroy()
active semaphore
*/
this->unlock_writing();
- pthread_cond_destroy(&lock);
+ sem_destroy(&lock);
pthread_mutex_destroy(&clients_guard);
DBUG_VOID_RETURN;
}
@@ -462,9 +469,7 @@ void Query_cache_query::unlock_n_destroy()
void Query_cache_query::lock_writing()
{
- MUTEX_LOCK(&clients_guard);
- while (clients != 0)
- pthread_cond_wait(&lock,&clients_guard);
+ SEM_LOCK(&lock);
}
@@ -478,18 +483,12 @@ void Query_cache_query::lock_writing()
my_bool Query_cache_query::try_lock_writing()
{
DBUG_ENTER("Query_cache_block::try_lock_writing");
- if (pthread_mutex_trylock(&clients_guard))
- {
- DBUG_PRINT("qcache", ("can't lock mutex"));
- DBUG_RETURN(0);
- }
- if (clients != 0)
+ if (sem_trywait(&lock)!=0 || clients != 0)
{
- DBUG_PRINT("info", ("already locked (r)"));
- MUTEX_UNLOCK(&clients_guard);
+ DBUG_PRINT("info", ("can't lock semaphore"));
DBUG_RETURN(0);
}
- DBUG_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
+ DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1);
}
@@ -497,23 +496,28 @@ my_bool Query_cache_query::try_lock_writing()
void Query_cache_query::lock_reading()
{
MUTEX_LOCK(&clients_guard);
- clients++;
+ if ( ++clients == 1 )
+ SEM_LOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
}
void Query_cache_query::unlock_writing()
{
- MUTEX_UNLOCK(&clients_guard);
+ SEM_UNLOCK(&lock);
}
void Query_cache_query::unlock_reading()
{
+ /*
+ To avoid unlocking semaphore before unlocking mutex (that may cause
+ destroying locked mutex), we use temporary boolean variable 'unlock'.
+ */
MUTEX_LOCK(&clients_guard);
- if (--clients == 0)
- pthread_cond_broadcast(&lock);
+ bool ulock = ((--clients) == 0);
MUTEX_UNLOCK(&clients_guard);
+ if (ulock) SEM_UNLOCK(&lock);
}
extern "C"
@@ -1377,8 +1381,11 @@ void Query_cache::free_cache(my_bool destruction)
/* Becasue we did a flush, all cache memory must be in one this block */
bins[0].free_blocks->destroy();
total_blocks--;
- DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
- free_memory , query_cache_size));
+#ifndef DBUG_OFF
+ if (free_memory != query_cache_size)
+ DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
+ free_memory , query_cache_size));
+#endif
my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
make_disabled();
hash_free(&queries);
@@ -2573,7 +2580,7 @@ my_bool Query_cache::move_by_type(byte **border,
} while ( result_block != first_result_block );
}
Query_cache_query *new_query= ((Query_cache_query *) new_block->data());
- pthread_cond_init(&new_query->lock, NULL);
+ sem_init(&new_query->lock, 0, 1);
pthread_mutex_init(&new_query->clients_guard,MY_MUTEX_INIT_FAST);
/*
@@ -2948,6 +2955,7 @@ my_bool Query_cache::check_integrity()
my_bool result = 0;
uint i;
STRUCT_LOCK(&structure_guard_mutex);
+ DBUG_ENTER("check_integrity");
if (hash_check(&queries))
{
@@ -3030,6 +3038,8 @@ my_bool Query_cache::check_integrity()
result = 1;
break;
case Query_cache_block::RES_INCOMPLETE:
+ // This type of block can be not lincked yet (in multithread environment)
+ break;
case Query_cache_block::RES_BEG:
case Query_cache_block::RES_CONT:
case Query_cache_block::RESULT:
@@ -3048,11 +3058,13 @@ my_bool Query_cache::check_integrity()
}
else
{
+ BLOCK_LOCK_RD(query_block);
if (in_list(queries_blocks, query_block, "query from results"))
result = 1;
if (in_list(query_block->query()->result(), block,
"results"))
result = 1;
+ BLOCK_UNLOCK_RD(query_block);
}
break;
}
@@ -3160,15 +3172,15 @@ my_bool Query_cache::check_integrity()
} while (block != bins[i].free_blocks);
if (count != bins[i].number)
{
- DBUG_PRINT("qcache", ("bin[%d].number is %d, but bin have %d blocks",
- bins[i].number, count));
+ DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks",
+ bins[i].number, count));
result = 1;
}
}
}
DBUG_ASSERT(result == 0);
STRUCT_UNLOCK(&structure_guard_mutex);
- return result;
+ DBUG_RETURN(result);
}