summaryrefslogtreecommitdiff
path: root/mysys/mf_iocache.c
diff options
context:
space:
mode:
authorunknown <serg@serg.mysql.com>2002-06-30 16:14:48 +0000
committerunknown <serg@serg.mysql.com>2002-06-30 16:14:48 +0000
commitfa87affa0c66ba07cebe44363a9ea8eec0d8b26e (patch)
tree982282b567e1de58ac0c3525ec4d78ad82500a7a /mysys/mf_iocache.c
parent422d3873af935a3720ba869a866e17136dc2e99c (diff)
parent4d10683775edd2ad63e78acc09fc7d40b83efba9 (diff)
downloadmariadb-git-fa87affa0c66ba07cebe44363a9ea8eec0d8b26e.tar.gz
merged
include/myisam.h: Auto merged myisam/myisamchk.c: Auto merged
Diffstat (limited to 'mysys/mf_iocache.c')
-rw-r--r--mysys/mf_iocache.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 6e0a267165b..6ad5397e61f 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -68,6 +68,9 @@ static void my_aiowait(my_aio_result *result);
#define unlock_append_buffer(info)
#endif
+#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
+#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
+
static void
init_functions(IO_CACHE* info, enum cache_type type)
{
@@ -424,22 +427,24 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
DBUG_RETURN(0);
}
-
#ifdef THREAD
-
-/* Initialzie multi-thread usage of the IO cache */
-
+/* Prepare IO_CACHE for shared use */
void init_io_cache_share(IO_CACHE *info, IO_CACHE_SHARE *s, uint num_threads)
{
DBUG_ASSERT(info->type == READ_CACHE);
pthread_mutex_init(&s->mutex, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&s->cond, 0);
- s->count=num_threads;
+ pthread_cond_init (&s->cond, 0);
+ s->count=num_threads-1;
s->active=0; /* to catch errors */
info->share=s;
info->read_function=_my_b_read_r;
}
+/*
+ Remove a thread from shared access to IO_CACHE
+ Every thread should do that on exit for not
+ to deadlock other threads
+*/
void remove_io_thread(IO_CACHE *info)
{
pthread_mutex_lock(&info->share->mutex);
@@ -448,34 +453,41 @@ void remove_io_thread(IO_CACHE *info)
pthread_mutex_unlock(&info->share->mutex);
}
-
-int lock_io_cache(IO_CACHE *info)
+static int lock_io_cache(IO_CACHE *info)
{
pthread_mutex_lock(&info->share->mutex);
if (!info->share->count)
return 1;
- info->share->count--;
- pthread_cond_wait(&((info)->share->cond), &((info)->share->mutex));
- if (!++info->share->count)
+
+ --(info->share->count);
+ pthread_cond_wait(&info->share->cond, &info->share->mutex);
+ /*
+ count can be -1 here, if one thread was removed (remove_io_thread)
+ while all others were locked (lock_io_cache).
+ If this is the case, this thread behaves as if count was 0 from the
+ very beginning, that is returns 1 and does not unlock the mutex.
+ */
+ if (++(info->share->count))
+ return pthread_mutex_unlock(&info->share->mutex);
+ else
return 1;
- pthread_mutex_unlock(&info->share->mutex);
- return 0;
}
-void unlock_io_cache(IO_CACHE *info)
+static void unlock_io_cache(IO_CACHE *info)
{
pthread_cond_broadcast(&info->share->cond);
pthread_mutex_unlock(&info->share->mutex);
}
/*
- Read from the io cache in a thread safe manner
+ Read from IO_CACHE when it is shared between several threads.
+ It works as follows: when a thread tries to read from a file
+ (that is, after using all the data from the (shared) buffer),
+ it just hangs on lock_io_cache(), wating for other threads.
+ When the very last thread attempts a read, lock_io_cache()
+ returns 1, the thread does actual IO and unlock_io_cache(),
+ which signals all the waiting threads that data is in the buffer.
*/
-
-#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
-#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
-
-
int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
{
my_off_t pos_in_file;
@@ -491,24 +503,40 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
}
while (Count)
{
- uint cnt, len;
+ int cnt, len;
pos_in_file= info->pos_in_file + (uint)(info->read_end - info->buffer);
diff_length= (uint) (pos_in_file & (IO_SIZE-1));
length=IO_ROUND_UP(Count+diff_length)-diff_length;
- length= ((length <= info->read_length) ?
- length + IO_ROUND_DN(info->read_length - length) :
- length - IO_ROUND_UP(length - info->read_length)) ;
+ length=IO_ROUND_UP(Count+diff_length)-diff_length;
+ length=(length <= info->read_length) ?
+ length + IO_ROUND_DN(info->read_length - length) :
+ length - IO_ROUND_UP(length - info->read_length) ;
+ if (info->type != READ_FIFO && (length > info->end_of_file - pos_in_file))
+ length=info->end_of_file - pos_in_file;
+ if (length == 0)
+ {
+ info->error=(int) read_len;
+ DBUG_RETURN(1);
+ }
if (lock_io_cache(info))
{
+#if 0 && SAFE_MUTEX
+#define PRINT_LOCK(M) printf("Thread %d: mutex is %s\n", my_thread_id(), \
+ (((safe_mutex_t *)(M))->count ? "Locked" : "Unlocked"))
+#else
+#define PRINT_LOCK(M)
+#endif
+ PRINT_LOCK(&info->share->mutex);
info->share->active=info;
if (info->seek_not_done) /* File touched, do seek */
VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
- len=my_read(info->file,info->buffer, length, info->myflags);
- info->read_end=info->buffer + (len == (uint) -1 ? 0 : len);
- info->error=(len == length ? 0 : len);
+ len=(int)my_read(info->file,info->buffer, length, info->myflags);
+ info->read_end=info->buffer + (len == -1 ? 0 : len);
+ info->error=(len == (int)length ? 0 : len);
info->pos_in_file=pos_in_file;
unlock_io_cache(info);
+ PRINT_LOCK(&info->share->mutex);
}
else
{
@@ -516,15 +544,16 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count)
info->read_end= info->share->active->read_end;
info->pos_in_file= info->share->active->pos_in_file;
len= (info->error == -1 ? -1 : info->read_end-info->buffer);
+ PRINT_LOCK(&info->share->mutex);
}
info->read_pos=info->buffer;
info->seek_not_done=0;
- if (info->error)
+ if (len <= 0)
{
info->error=(int) read_len;
DBUG_RETURN(1);
}
- cnt=(len > Count) ? Count : len;
+ cnt=(len > Count) ? (int) Count : len;
memcpy(Buffer,info->read_pos, (size_t)cnt);
Count -=cnt;
Buffer+=cnt;
@@ -1098,11 +1127,19 @@ int end_io_cache(IO_CACHE *info)
DBUG_ENTER("end_io_cache");
#ifdef THREAD
- /* simple protection against multi-close: destroying share first */
if (info->share)
{
- pthread_cond_destroy(&info->share->cond);
+#ifdef SAFE_MUTEX
+ /* simple protection against multi-close: destroying share first */
+ if (pthread_cond_destroy (&info->share->cond) |
+ pthread_mutex_destroy(&info->share->mutex))
+ {
+ DBUG_RETURN(1);
+ }
+#else
+ pthread_cond_destroy (&info->share->cond);
pthread_mutex_destroy(&info->share->mutex);
+#endif
info->share=0;
}
#endif