# HG changeset patch # User mroi # Date 1027246605 0 # Node ID dcde6d9cea7af5ddd7e6b2c9e7347a14449da03e # Parent 2759605b41f67ec657367b1e8bae1d261e55ae56 ensure serialized access to the cache to avoid concurrent access on the usage counters diff -r 2759605b41f6 -r dcde6d9cea7a read_cache.c --- a/read_cache.c Wed Jul 17 15:04:28 2002 +0000 +++ b/read_cache.c Sun Jul 21 10:16:45 2002 +0000 @@ -82,6 +82,7 @@ read_cache_chunk_t chunk[READ_CACHE_CHUNKS]; int current; int freeing; /* is set to one when we are about to dispose the cache */ + pthread_mutex_t lock; /* Bit of strange cross-linking going on here :) -- Gotta love C :) */ dvdnav_t *dvd_self; @@ -342,6 +343,7 @@ self->current = 0; self->freeing = 0; self->dvd_self = dvd_self; + pthread_mutex_init(&self->lock, NULL); dvdnav_read_cache_clear(self); for (i = 0; i < READ_CACHE_CHUNKS; i++) { self->chunk[i].cache_buffer = NULL; @@ -356,18 +358,21 @@ dvdnav_t *tmp; int i; + pthread_mutex_lock(&self->lock); self->freeing = 1; for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].cache_buffer && self->chunk[i].usage_count == 0) { free(self->chunk[i].cache_buffer); self->chunk[i].cache_buffer = NULL; } + pthread_mutex_unlock(&self->lock); for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].cache_buffer) return; /* all buffers returned, free everything */ tmp = self->dvd_self; + pthread_mutex_destroy(&self->lock); free(self); free(tmp); } @@ -379,9 +384,10 @@ if(!self) return; - for (i = 0; i < READ_CACHE_CHUNKS; i++) { + pthread_mutex_lock(&self->lock); + for (i = 0; i < READ_CACHE_CHUNKS; i++) self->chunk[i].cache_valid = 0; - } + pthread_mutex_unlock(&self->lock); } #ifdef DVDNAV_PROFILE @@ -409,6 +415,8 @@ if(!self->dvd_self->use_read_ahead) return; + pthread_mutex_lock(&self->lock); + /* find a free cache chunk that best fits the required size */ use = -1; for (i = 0; i < READ_CACHE_CHUNKS; i++) @@ -467,6 +475,8 @@ self->chunk[use].cache_valid = 1; } else dprintf("pre_caching was impossible, no cache chunk available\n"); + + pthread_mutex_unlock(&self->lock); } int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf) { @@ -475,6 +485,8 @@ if(!self) return 0; + pthread_mutex_lock(&self->lock); + use = -1; if(self->dvd_self->use_read_ahead) { /* first check, if sector is in current chunk */ @@ -493,10 +505,12 @@ self->chunk[use].usage_count++; *buf = &self->chunk[use].cache_buffer[(sector - self->chunk[use].cache_start_sector) * DVD_VIDEO_LB_LEN * block_count]; + pthread_mutex_unlock(&self->lock); return DVD_VIDEO_LB_LEN * block_count; } else { if (self->dvd_self->use_read_ahead) dprintf("cache miss on sector %d\n", sector); + pthread_mutex_unlock(&self->lock); return DVDReadBlocks(self->dvd_self->file, sector, block_count, *buf); } } @@ -512,11 +526,13 @@ if (!cache) return DVDNAV_STATUS_ERR; + pthread_mutex_lock(&cache->lock); for (i = 0; i < READ_CACHE_CHUNKS; i++) if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer && buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN) cache->chunk[i].usage_count--; - + pthread_mutex_unlock(&cache->lock); + if (cache->freeing) /* when we want to dispose the cache, try freeing it now */ dvdnav_read_cache_free(cache);