From 029ddf28dd60a194d8ed97ed234548f13a02f75d Mon Sep 17 00:00:00 2001 From: cedric Date: Mon, 6 Jun 2011 17:08:06 +0000 Subject: [PATCH] eina: make Eina_File thread safe. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@59995 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/eina_file.c | 55 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/lib/eina_file.c b/src/lib/eina_file.c index ec7eb55..64b44fb 100644 --- a/src/lib/eina_file.c +++ b/src/lib/eina_file.c @@ -64,6 +64,7 @@ void *alloca (size_t); #include "eina_stringshare.h" #include "eina_hash.h" #include "eina_list.h" +#include "eina_lock.h" /*============================================================================* * Local * @@ -116,6 +117,8 @@ struct _Eina_File Eina_Hash *rmap; void *global_map; + Eina_Lock lock; + unsigned long long length; time_t mtime; ino_t inode; @@ -142,6 +145,7 @@ struct _Eina_File_Map static Eina_Hash *_eina_file_cache = NULL; static Eina_List *_eina_file_cache_lru = NULL; static Eina_List *_eina_file_cache_delete = NULL; +static Eina_Lock _eina_file_lock_cache; static int _eina_file_log_dom = -1; @@ -487,6 +491,8 @@ eina_file_init(void) return EINA_FALSE; } + eina_lock_new(&_eina_file_lock_cache); + return EINA_TRUE; } @@ -515,6 +521,8 @@ eina_file_shutdown(void) eina_hash_free(_eina_file_cache); + eina_lock_free(&_eina_file_lock_cache); + eina_log_domain_unregister(_eina_file_log_dom); _eina_file_log_dom = -1; return EINA_TRUE; @@ -771,6 +779,8 @@ eina_file_open(const char *filename, Eina_Bool shared) if (fstat(fd, &file_stat)) goto on_error; + eina_lock_take(&_eina_file_lock_cache); + file = eina_hash_find(_eina_file_cache, filename); if (file && (file->mtime != file_stat.st_mtime || file->length != (unsigned long long) file_stat.st_size @@ -814,6 +824,7 @@ eina_file_open(const char *filename, Eina_Bool shared) n->fd = fd; n->shared = shared; n->delete_me = EINA_FALSE; + eina_lock_new(&n->lock); if (file) eina_hash_del(_eina_file_cache, filename, file); eina_hash_direct_add(_eina_file_cache, n->filename, n); @@ -828,7 +839,11 @@ eina_file_open(const char *filename, Eina_Bool shared) _eina_file_cache_lru = eina_list_remove(_eina_file_cache_lru, n); } + eina_lock_take(&n->lock); n->refcount++; + eina_lock_release(&n->lock); + + eina_lock_release(&_eina_file_lock_cache); return n; @@ -840,13 +855,16 @@ eina_file_open(const char *filename, Eina_Bool shared) EAPI void eina_file_close(Eina_File *file) { + eina_lock_take(&file->lock); file->refcount--; + eina_lock_release(&file->lock); if (file->refcount != 0) return ; if (file->delete_me) { - _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, file); + _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, + file); _eina_file_real_close(file); } else @@ -877,6 +895,7 @@ EAPI void * eina_file_map_all(Eina_File *file, Eina_File_Populate rule) { int flags = MAP_SHARED; + void *ret = NULL; // bsd people will lack this feature #ifdef MAP_POPULATE @@ -886,6 +905,7 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule) if (file->length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB; #endif + eina_lock_take(&file->lock); if (file->global_map == MAP_FAILED) file->global_map = mmap(NULL, file->length, PROT_READ, flags, file->fd, 0); @@ -893,9 +913,11 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule) { _eina_file_map_rule_apply(rule, file->global_map, file->length); file->global_refcount++; - return file->global_map; + ret = file->global_map; } - return NULL; + + eina_lock_release(&file->lock); + return ret; } EAPI void * @@ -916,6 +938,8 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, key[0] = offset; key[1] = length; + eina_lock_take(&file->lock); + map = eina_hash_find(file->map, &key); if (!map) { @@ -930,18 +954,14 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, #endif map = malloc(sizeof (Eina_File_Map)); - if (!map) return NULL; + if (!map) goto on_error; map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset); map->offset = offset; map->length = length; map->refcount = 0; - if (map->map == MAP_FAILED) - { - free(map); - return NULL; - } + if (map->map == MAP_FAILED) goto on_error; eina_hash_add(file->map, &key, map); eina_hash_direct_add(file->rmap, map->map, map); @@ -951,17 +971,27 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, _eina_file_map_rule_apply(rule, map->map, length); + eina_lock_release(&file->lock); + return map->map; + + on_error: + free(map); + eina_lock_release(&file->lock); + + return NULL; } EAPI void eina_file_map_free(Eina_File *file, void *map) { + eina_lock_take(&file->lock); + if (file->global_map == map) { file->global_refcount--; - if (file->global_refcount > 0) return ; + if (file->global_refcount > 0) goto on_exit; munmap(file->global_map, file->length); file->global_map = MAP_FAILED; @@ -976,7 +1006,7 @@ eina_file_map_free(Eina_File *file, void *map) em->refcount--; - if (em->refcount > 0) return ; + if (em->refcount > 0) goto on_exit; key[0] = em->offset; key[1] = em->length; @@ -984,6 +1014,9 @@ eina_file_map_free(Eina_File *file, void *map) eina_hash_del(file->rmap, &map, em); eina_hash_del(file->map, &key, em); } + + on_exit: + eina_lock_release(&file->lock); } -- 2.7.4