From: cedric Date: Thu, 3 Dec 2009 15:35:04 +0000 (+0000) Subject: * eet: All operation on Eet_File should be thread safe. This should X-Git-Tag: submit/2.0alpha-wayland/20121127.222001~419 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=42f372563aa5c8d7ab08326f10d07a9e23b1020d;p=profile%2Fivi%2Feet.git * eet: All operation on Eet_File should be thread safe. This should make use of all eet primitive thread safe now. Please any bug or lock that you find. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eet@44172 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/configure.ac b/configure.ac index 9099406..868cc8a 100644 --- a/configure.ac +++ b/configure.ac @@ -175,11 +175,12 @@ AC_SUBST(pkgconfig_requires_private) EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"]) - ### Checks for libraries # Evil library for compilation on Windows +EFL_CHECK_PTHREAD([have_pthread="yes"], [have_pthread="no"]) + EFL_EET_BUILD="" case "$host_os" in mingw* | cegcc*) @@ -417,6 +418,7 @@ echo " Gnutls...............: ${have_gnutls}" echo " Openssl..............: ${have_openssl}" echo " Cipher support.....: ${have_cipher}" echo " Signature..........: ${have_signature}" +echo " Thread Support.......: ${have_pthread}" echo echo " Amalgamation.........: ${do_amalgamation}" echo " Documentation........: ${build_doc}" diff --git a/m4/efl_pthread.m4 b/m4/efl_pthread.m4 new file mode 100644 index 0000000..7bd341c --- /dev/null +++ b/m4/efl_pthread.m4 @@ -0,0 +1,71 @@ +dnl Copyright (C) 2008 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if several ASM instruction sets are available or not. + +dnl Usage: EFL_CHECK_EFL_CHECK_PTHREAD([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EFL_PTHREAD_FLAGS) +dnl Define EFL_HAVE_PTHREAD + +AC_DEFUN([EFL_CHECK_PTHREAD], +[ + +dnl configure option + +AC_ARG_ENABLE([pthread], + [AC_HELP_STRING([--disable-pthread], [enable POSIX threads code @<:@default=yes@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_pthread="yes" + else + _efl_enable_pthread="no" + fi + ], + [_efl_enable_pthread="yes"]) + +AC_MSG_CHECKING([whether to build POSIX threads code]) +AC_MSG_RESULT([${_efl_enable_pthread}]) + +dnl check if the compiler supports pthreads + +_efl_have_pthread="no" + +if test "x${_efl_enable_pthread}" = "xyes" ; then + AC_CHECK_HEADER(pthread.h, + [_efl_have_pthread="yes"], + [_efl_have_pthread="no"]) +fi + +AC_MSG_CHECKING([whether system support POSIX threads]) +AC_MSG_RESULT([${_efl_enable_pthread}]) + +if test "x${_efl_have_pthread}" = "xyes" ; then + case "$host_os" in + mingw*) + EFL_PTHREAD_CFLAGS="-mthreads" + EFL_PTHREAD_LIBS="-mthreads -lpthreadGC2" + ;; + solaris*) + EFL_PTHREAD_CFLAGS="-mt" + EFL_PTHREAD_LIBS="-mt" + ;; + *) + EFL_PTHREAD_CFLAGS="-pthread" + EFL_PTHREAD_LIBS="-pthread" + ;; + esac +fi + +AC_SUBST(EFL_PTHREAD_CFLAGS) +AC_SUBST(EFL_PTHREAD_LIBS) + +if test "x${_efl_have_pthread}" = "xyes" ; then + AC_DEFINE(EFL_HAVE_PTHREAD, 1, [Define to mention that POSIX threads are supported]) +fi + +if test "x${_efl_have_pthread}" = "xyes" ; then + ifelse([$1], , :, [$1]) +else + ifelse([$2], , :, [$2]) +fi +]) diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c index 82d1773..b40ea93 100644 --- a/src/lib/eet_lib.c +++ b/src/lib/eet_lib.c @@ -60,6 +60,23 @@ void *alloca (size_t); # include #endif +#ifdef EFL_HAVE_PTHREAD +# ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include +# elif defined (__SUNPRO_C) +# include +# elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || ( defined (__MACH__) && defined (__APPLE__)) +# include +# include +# include +# elif defined (__linux__) +# define _GNU_SOURCE +# include +# endif +# include +#endif + #include #include "Eet.h" @@ -103,6 +120,10 @@ struct _Eet_File time_t mtime; +#ifdef EFL_HAVE_PTHREAD + pthread_mutex_t file_lock; +#endif + unsigned char writes_pending : 1; unsigned char delete_me_now : 1; }; @@ -210,6 +231,29 @@ static Eet_Error eet_flush2(Eet_File *ef); static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name); static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len); +#ifdef EFL_HAVE_PTHREAD +static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER; + +#define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock); +#define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock); + +#define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL); +#define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock); +#define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock); +#define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock); + +#else + +#define LOCK_CACHE ; +#define UNLOCK_CACHE ; + +#define INIT_FILE(File) ; +#define LOCK_FILE(File) ; +#define UNLOCK_FILE(File) ; +#define DESTROY_FILE(File) ; + +#endif + /* cache. i don't expect this to ever be large, so arrays will do */ static int eet_writers_num = 0; static int eet_writers_alloc = 0; @@ -1279,6 +1323,7 @@ eet_memopen_read(const void *data, size_t size) if (!ef) return NULL; + INIT_FILE(ef); ef->ed = NULL; ef->path = NULL; ef->key = NULL; @@ -1311,6 +1356,7 @@ eet_open(const char *file, Eet_File_Mode mode) /* find the current file handle in cache*/ ef = NULL; + LOCK_CACHE; if (mode == EET_FILE_MODE_READ) { ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); @@ -1335,6 +1381,7 @@ eet_open(const char *file, Eet_File_Mode mode) } ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); } + UNLOCK_CACHE; /* try open the file based on mode */ if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) @@ -1399,6 +1446,7 @@ eet_open(const char *file, Eet_File_Mode mode) return NULL; /* fill some of the members */ + INIT_FILE(ef); ef->fp = fp; ef->key = NULL; ef->readfp = NULL; @@ -1451,11 +1499,13 @@ eet_open(const char *file, Eet_File_Mode mode) /* add to cache */ if (ef->references == 1) { + LOCK_CACHE; if (ef->mode == EET_FILE_MODE_READ) eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); + UNLOCK_CACHE; } return ef; @@ -1539,10 +1589,14 @@ eet_close(Eet_File *ef) return EET_ERROR_NONE; /* remove from cache */ + LOCK_CACHE; if (ef->mode == EET_FILE_MODE_READ) eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); + UNLOCK_CACHE; + + DESTROY_FILE(ef); /* free up data */ if (ef->header) @@ -1616,18 +1670,18 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe if (eet_check_header(ef)) return NULL; + LOCK_FILE(ef); + /* hunt hash bucket */ efn = find_node_by_name(ef, name); - if (!efn) - return NULL; + if (!efn) goto on_error; /* get size (uncompressed, if compressed at all) */ size = efn->data_size; /* allocate data */ data = malloc(size); - if (!data) - return NULL; + if (!data) goto on_error; /* uncompressed data */ if (efn->compression == 0) @@ -1639,17 +1693,13 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe memcpy(data, efn->data, efn->size); else if (!read_data_from_disk(ef, efn, data, size)) - { - free(data); - return NULL; - } + goto on_error; if (efn->ciphered && cipher_key) { if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz)) { - free(data); if (data_deciphered) free(data_deciphered); - return NULL; + goto on_error; } free(data); data = data_deciphered; @@ -1673,18 +1723,14 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe { tmp_data = malloc(compr_size); if (!tmp_data) - { - free(data); - return NULL; - } + goto on_error; free_tmp = 1; if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) { free(tmp_data); - free(data); - return NULL; + goto on_error; } } @@ -1692,10 +1738,9 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe { if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz)) { - free(data); if (free_tmp) free(tmp_data); if (data_deciphered) free(data_deciphered); - return NULL; + goto on_error; } free(tmp_data); tmp_data = data_deciphered; @@ -1706,10 +1751,7 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe dlen = size; if (uncompress((Bytef *)data, &dlen, tmp_data, (uLongf)compr_size)) - { - free(data); - return NULL; - } + goto on_error; if (free_tmp) free(tmp_data); @@ -1719,7 +1761,14 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe if (size_ret) *size_ret = size; + UNLOCK_FILE(ef); + return data; + + on_error: + UNLOCK_FILE(ef); + free(data); + return NULL; } EAPI void * @@ -1751,13 +1800,14 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) if (eet_check_header(ef)) return NULL; + LOCK_FILE(ef); + /* hunt hash bucket */ efn = find_node_by_name(ef, name); - if (!efn) - return NULL; + if (!efn) goto on_error; if (efn->offset < 0 && efn->data == NULL) - return NULL; + goto on_error; /* get size (uncompressed, if compressed at all) */ size = efn->data_size; @@ -1774,7 +1824,13 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) if (size_ret) *size_ret = size; + UNLOCK_FILE(ef); + return data; + + on_error: + UNLOCK_FILE(ef); + return NULL; } EAPI int @@ -1795,25 +1851,35 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int (ef->mode != EET_FILE_MODE_READ_WRITE)) return 0; + LOCK_FILE(ef); + if (!ef->header) { /* allocate header */ ef->header = calloc(1, sizeof(Eet_File_Header)); if (!ef->header) - return 0; + goto on_error; ef->header->magic = EET_MAGIC_FILE_HEADER; /* allocate directory block in ram */ ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); if (!ef->header->directory) - return 0; + { + free(ef->header); + ef->header = NULL; + goto on_error; + } /* 8 bit hash table (256 buckets) */ ef->header->directory->size = 8; /* allocate base hash table */ ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); if (!ef->header->directory->nodes) - return 0; + { + free(ef->header->directory); + ef->header = NULL; + goto on_error; + } } /* figure hash bucket */ @@ -1824,8 +1890,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int if (compress || !cipher_key) { data2 = malloc(data_size); - if (!data2) - return 0; + if (!data2) goto on_error; } /* if we want to compress */ @@ -1905,7 +1970,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int if (!efn) { free(data2); - return 0; + goto on_error; } efn->name = strdup(name); efn->name_size = strlen(efn->name) + 1; @@ -1923,7 +1988,12 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int /* flags that writes are pending */ ef->writes_pending = 1; + UNLOCK_FILE(ef); return data_size; + + on_error: + UNLOCK_FILE(ef); + return 0; } EAPI int @@ -1953,6 +2023,8 @@ eet_delete(Eet_File *ef, const char *name) if (eet_check_header(ef)) return 0; + LOCK_FILE(ef); + /* figure hash bucket */ hash = _eet_hash_gen(name, ef->header->directory->size); @@ -1982,6 +2054,8 @@ eet_delete(Eet_File *ef, const char *name) if (exists_already) ef->writes_pending = 1; + UNLOCK_FILE(ef); + /* update access time */ return exists_already; } @@ -2016,6 +2090,8 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret) return NULL; } + LOCK_FILE(ef); + /* loop through all entries */ num = (1 << ef->header->directory->size); for (i = 0; i < num; i++) @@ -2042,10 +2118,7 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret) { free(list_ret); - if (count_ret) - *count_ret = 0; - - return NULL; + goto on_error; } list_ret = new_list; } @@ -2056,11 +2129,21 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret) } } + UNLOCK_FILE(ef); + /* return count and list */ if (count_ret) *count_ret = list_count; return list_ret; + + on_error: + UNLOCK_FILE(ef); + + if (count_ret) + *count_ret = 0; + + return NULL; } EAPI int @@ -2075,6 +2158,8 @@ eet_num_entries(Eet_File *ef) (ef->mode != EET_FILE_MODE_READ_WRITE))) return -1; + LOCK_FILE(ef); + /* loop through all entries */ num = (1 << ef->header->directory->size); for (i = 0; i < num; i++) @@ -2083,6 +2168,8 @@ eet_num_entries(Eet_File *ef) ret++; } + UNLOCK_FILE(ef); + return ret; }