This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository efl.
View the commit online.
commit 64b81d32568074d2d8f8eef6298caec7a93c060f
Author: Carsten Haitzler <[email protected]>
AuthorDate: Fri May 15 15:54:54 2026 +0100
eina - eina file - add an async thread to close fds in case they block
yes - close can block. i've seen it. this will remove stalls in the
main loop or in any thread if the close blocks on a slow fs.
this adds thread(s) to close fds (based on device id - this should
be limited).
@opt
---
src/lib/eina/eina_file_common.c | 7 +-
src/lib/eina/eina_file_common.h | 5 ++
src/lib/eina/eina_file_posix.c | 179 ++++++++++++++++++++++++++++++++++++++--
3 files changed, 185 insertions(+), 6 deletions(-)
diff --git a/src/lib/eina/eina_file_common.c b/src/lib/eina/eina_file_common.c
index 9e7cd081d3..6dc57d805f 100644
--- a/src/lib/eina/eina_file_common.c
+++ b/src/lib/eina/eina_file_common.c
@@ -1023,7 +1023,9 @@ eina_file_init(void)
eina_spinlock_release(&_eina_statgen_lock);
eina_lock_recursive_new(&_eina_file_lock_cache);
eina_magic_string_set(EINA_FILE_MAGIC, "Eina_File");
-
+#ifndef _WIN32
+ eina_file_posix_init();
+#endif
return EINA_TRUE;
}
@@ -1047,6 +1049,9 @@ eina_file_shutdown(void)
eina_hash_free(_eina_file_cache);
_eina_file_cache = NULL;
+#ifndef _WIN32
+ eina_file_posix_shutdown();
+#endif
eina_lock_free(&_eina_file_lock_cache);
eina_log_domain_unregister(_eina_file_log_dom);
diff --git a/src/lib/eina/eina_file_common.h b/src/lib/eina/eina_file_common.h
index 1478f3a945..07121f0465 100644
--- a/src/lib/eina/eina_file_common.h
+++ b/src/lib/eina/eina_file_common.h
@@ -328,6 +328,11 @@ int eina_file_map_key_cmp(const unsigned long long int *key1, int key1_length,
*/
int eina_file_map_key_hash(const unsigned long long int *key, int key_length);
+#ifndef _WIN32
+void eina_file_posix_init(void);
+void eina_file_posix_shutdown(void);
+#endif
+
/**
* @}
*/
diff --git a/src/lib/eina/eina_file_posix.c b/src/lib/eina/eina_file_posix.c
index 6c075941c3..2d8c448eab 100644
--- a/src/lib/eina/eina_file_posix.c
+++ b/src/lib/eina/eina_file_posix.c
@@ -66,6 +66,8 @@
#include "eina_log.h"
#include "eina_xattr.h"
#include "eina_file_common.h"
+#include "eina_thread.h"
+#include "eina_thread_queue.h"
/*============================================================================*
* Local *
@@ -96,6 +98,8 @@ struct _Eina_File_Iterator
int _eina_file_log_dom = -1;
+static void _eina_file_posix_fd_close(dev_t dev, int fd);
+
/*
* This complex piece of code is needed due to possible race condition.
* The code and description of the issue can be found at :
@@ -310,7 +314,8 @@ eina_file_real_close(Eina_File *file)
{
if (!file->copied && file->global_map != MAP_FAILED)
munmap(file->global_map, file->length);
- close(file->fd);
+ _eina_file_posix_fd_close(file->dev, file->fd);
+// close(file->fd);
}
}
@@ -836,7 +841,7 @@ eina_file_open(const char *path, Eina_Bool shared)
Eina_File *file;
Eina_File *n;
Eina_Stringshare *filename;
- struct stat file_stat;
+ struct stat file_stat = { 0 };
int fd = -1;
Eina_Statgen statgen;
@@ -893,7 +898,8 @@ eina_file_open(const char *path, Eina_Bool shared)
file->statgen = statgen;
eina_lock_release(&file->lock);
- close(fd);
+ _eina_file_posix_fd_close(file_stat.st_dev, fd);
+// close(fd);
eina_stringshare_del(filename);
return file;
}
@@ -958,7 +964,8 @@ eina_file_open(const char *path, Eina_Bool shared)
eina_hash_free(n->rmap);
eina_hash_free(n->map);
eina_stringshare_del(n->filename);
- close(n->fd);
+ _eina_file_posix_fd_close(n->dev, n->fd);
+// close(n->fd);
free(n);
eina_stringshare_del(filename);
return file;
@@ -971,7 +978,11 @@ eina_file_open(const char *path, Eina_Bool shared)
INF("Could not open file [%s].", filename);
eina_stringshare_del(filename);
- if (fd >= 0) close(fd);
+ if (fd >= 0)
+ {
+ _eina_file_posix_fd_close(file_stat.st_dev, fd);
+// close(fd);
+ }
if (file) eina_file_close(file);
return NULL;
}
@@ -1686,3 +1697,161 @@ eina_file_access(const char *path, Eina_File_Access_Mode mode)
return access(path, mode) == 0;
}
+
+typedef struct _Close_Thread
+{
+ dev_t dev;
+ Eina_Thread_Queue *thq;
+ Eina_Thread th;
+} Close_Thread;
+
+typedef struct _Close_Msg
+{
+ Eina_Thread_Queue_Msg head;
+ int dev;
+ int fd;
+} Close_Msg;
+
+static Eina_Lock _close_threads_lock;
+static Close_Thread *_close_threads = NULL;
+static int _close_threads_num = 0;
+
+#define EXIT_FD -999909999
+
+static void *
+_eina_file_posix_close_thread(void *arg, Eina_Thread t)
+{
+ Close_Thread *ct = arg;
+ Eina_Thread_Queue *thq = ct->thq;
+ Close_Msg *msg;
+ void *ref = NULL;
+
+ eina_thread_name_set(t, "Eina-fd-closer");
+ for (;;)
+ {
+ msg = eina_thread_queue_wait(thq, &ref);
+ if (msg)
+ {
+ int fd = msg->fd;
+ eina_thread_queue_wait_done(thq, ref);
+ if (fd == EXIT_FD) return NULL;
+ close(fd);
+ }
+ }
+ return NULL;
+}
+
+static Close_Thread *
+_eina_file_posix_close_thread_add(dev_t dev)
+{ // requires _close_threads_lock to be taken
+ Close_Thread *ct;
+
+ _close_threads_num++;
+ ct = realloc(_close_threads, _close_threads_num * sizeof(Close_Thread));
+ if (!ct)
+ {
+ _close_threads_num--;
+ return NULL;
+ }
+ _close_threads = ct;
+ _close_threads[_close_threads_num - 1].dev = dev;
+ _close_threads[_close_threads_num - 1].thq = eina_thread_queue_new();
+ if (!_close_threads[_close_threads_num - 1].thq)
+ {
+ _close_threads_num--;
+ return NULL;
+ }
+ if (!eina_thread_create(&(_close_threads[_close_threads_num - 1].th),
+ EINA_THREAD_NORMAL, -1,
+ _eina_file_posix_close_thread,
+ &(_close_threads[_close_threads_num - 1])))
+ {
+ eina_thread_queue_free(_close_threads[_close_threads_num - 1].thq);
+ _close_threads_num--;
+ return NULL;
+ }
+ return &(_close_threads[_close_threads_num - 1]);
+}
+
+static Close_Thread *
+_eina_file_posix_close_thread_find(dev_t dev)
+{ // requires _close_threads_lock to be taken
+ Close_Thread *ct = NULL;
+ int i;
+
+ for (i = 0; i < _close_threads_num; i++)
+ {
+ if (_close_threads[i].dev == dev)
+ {
+ ct = &(_close_threads[i]);
+ break;
+ }
+ }
+ return ct;
+}
+
+static void
+_eina_file_posix_fd_close(dev_t dev, int fd)
+{
+ Close_Thread *ct;
+ Close_Msg *msg;
+ void *ref = NULL;
+
+ eina_lock_take(&_close_threads_lock);
+ ct = _eina_file_posix_close_thread_find(dev);
+ if (!ct) _eina_file_posix_close_thread_add(dev);
+ eina_lock_release(&_close_threads_lock);
+
+ if (!ct) goto err; // EEEK we can't alloc a closer thread?
+ msg = eina_thread_queue_send(ct->thq, sizeof(Close_Msg), &ref);
+ if (!msg) goto err;
+ msg->dev = dev;
+ msg->fd = fd;
+ eina_thread_queue_send_done(ct->thq, ref);
+ return;
+err:
+ close(fd);
+ return;
+}
+
+static void
+_eina_file_posix_closers_clear(void)
+{ // requires _close_threads_lock to be taken
+ int i;
+
+ if (!_close_threads) return;
+ for (i = 0; i < _close_threads_num; i++)
+ {
+ Close_Msg *msg;
+ Close_Thread *ct = &_close_threads[i];
+ void *ref;
+
+ msg = eina_thread_queue_send(ct->thq, sizeof(Close_Msg), &ref);
+ if (msg)
+ {
+ msg->dev = ct->dev;
+ msg->fd = EXIT_FD;
+ eina_thread_queue_send_done(ct->thq, ref);
+ }
+ eina_thread_join(ct->th);
+ eina_thread_queue_free(ct->thq);
+ }
+ free(_close_threads);
+ _close_threads = NULL;
+ _close_threads_num = 0;
+}
+
+void
+eina_file_posix_init(void)
+{
+ eina_lock_new(&_close_threads_lock);
+}
+
+void
+eina_file_posix_shutdown(void)
+{
+ eina_lock_take(&_close_threads_lock);
+ _eina_file_posix_closers_clear();
+ eina_lock_release(&_close_threads_lock);
+ eina_lock_free(&_close_threads_lock);
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.