]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Support dl-object cache
authorTakashi Iwai <tiwai@suse.de>
Mon, 14 Feb 2005 15:09:09 +0000 (15:09 +0000)
committerTakashi Iwai <tiwai@suse.de>
Mon, 14 Feb 2005 15:09:09 +0000 (15:09 +0000)
Added the support of dl-object caches for PCM plugins.

include/local.h
include/pcm_ioplug.h
src/conf.c
src/dlmisc.c
src/pcm/pcm.c

index 6df4abca1f5df0d53a3d6b0526f86ae216587185..61ec10d8abb4fbd768560b8a7bc42dad435386c2 100644 (file)
@@ -232,4 +232,9 @@ static inline int snd_open_device(const char *filename, int fmode)
 #define snd_open_device(filename, fmode) open(filename, fmode);
 #endif
 
+/* dlobj cache */
+void *snd_dlobj_cache_lookup(const char *name);
+int snd_dlobj_cache_add(const char *name, void *dlobj, void *open_func);
+void snd_dlobj_cache_cleanup(void);
+
 #endif
index 62c064ac1fe7201f3c408e1e2295bda6f98e5764..03b0540b278a090641008441585d6aaf4d4b9ac4 100644 (file)
@@ -37,10 +37,13 @@ enum {
 typedef struct snd_pcm_ioplug snd_pcm_ioplug_t;
 typedef struct snd_pcm_ioplug_callback snd_pcm_ioplug_callback_t;
 
+#define SND_PCM_IOPLUG_FLAG_LISTED     (1<<0)
+
 /* exported pcm data */
 struct snd_pcm_ioplug {
        /* must be filled before calling snd_pcm_ioplug_create() */
        const char *name;
+       unsigned int flags;     /* SND_PCM_IOPLUG_FLAG_XXX */
        int poll_fd;
        unsigned int poll_events;
        unsigned int mmap_rw;           /* pseudo mmap */
index 066e07e1e31fbe8b04e7894e690fc14d9834d455..26007832406a6072439c82d52ff0186e85dd276f 100644 (file)
@@ -3113,6 +3113,10 @@ int snd_config_update_free_global(void)
                snd_config_update_free(snd_config_global_update);
        snd_config_global_update = NULL;
        pthread_mutex_unlock(&snd_config_update_mutex);
+
+       /* FIXME: better to place this in another place... */
+       snd_dlobj_cache_cleanup();
+
        return 0;
 }
 
index a5d174d7a7b51b094fc9ba331299a7d31d75240c..6298e4831eb1994c0ceccc5056f0ed7d36616110 100644 (file)
@@ -29,6 +29,7 @@
 
 #define _GNU_SOURCE
 #include <dlfcn.h>
+#include "list.h"
 #include "local.h"
 
 #ifndef DOC_HIDDEN
@@ -143,3 +144,70 @@ void *snd_dlsym(void *handle, const char *name, const char *version)
                return NULL;
        return dlsym(handle, name);
 }
+
+/*
+ * dlobj cache
+ *
+ * FIXME: add reference counter and proper locking
+ */
+
+struct dlobj_cache {
+       const char *name;
+       void *obj;
+       void *func;
+       struct list_head list;
+};
+
+static LIST_HEAD(pcm_dlobj_list);
+
+void *snd_dlobj_cache_lookup(const char *name)
+{
+       struct list_head *p;
+       struct dlobj_cache *c;
+
+       list_for_each(p, &pcm_dlobj_list) {
+               c = list_entry(p, struct dlobj_cache, list);
+               if (strcmp(c->name, name) == 0)
+                       return c->func;
+       }
+       return NULL;
+}
+
+int snd_dlobj_cache_add(const char *name, void *dlobj, void *open_func)
+{
+       struct list_head *p;
+       struct dlobj_cache *c;
+
+       list_for_each(p, &pcm_dlobj_list) {
+               c = list_entry(p, struct dlobj_cache, list);
+               if (strcmp(c->name, name) == 0)
+                       return 0; /* already exists */
+       }
+       c = malloc(sizeof(*c));
+       if (! c)
+               return -ENOMEM;
+       c->name = strdup(name);
+       if (! c->name) {
+               free(c);
+               return -ENOMEM;
+       }
+       c->obj = dlobj;
+       c->func = open_func;
+       list_add_tail(&c->list, &pcm_dlobj_list);
+       return 0;
+}
+
+void snd_dlobj_cache_cleanup(void)
+{
+       struct list_head *p;
+       struct dlobj_cache *c;
+
+       while (! list_empty(&pcm_dlobj_list)) {
+               p = pcm_dlobj_list.next;
+               c = list_entry(p, struct dlobj_cache, list);
+               list_del(p);
+               snd_dlclose(c->obj);
+               free(c->name);
+               free(c);
+       }
+}
index a4df4698ae76b5972fd852ca0858955b0c63b8c1..c2fc9547846c3431650fb649691a3f8d503414ed 100644 (file)
@@ -2019,6 +2019,11 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
 #ifndef PIC
        snd_pcm_open_symbols(); /* this call is for static linking only */
 #endif
+       open_func = snd_dlobj_cache_lookup(open_name);
+       if (open_func) {
+               err = 0;
+               goto _err;
+       }
        h = snd_dlopen(lib, RTLD_NOW);
        if (h)
                open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_PCM_DLSYM_VERSION));
@@ -2032,17 +2037,22 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
                err = -ENXIO;
        }
        _err:
-       if (type_conf)
-               snd_config_delete(type_conf);
        if (err >= 0) {
                err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);
                if (err >= 0) {
+                       if (h /*&& (mode & SND_PCM_KEEP_ALIVE)*/) {
+                               snd_dlobj_cache_add(open_name, h, open_func);
+                               h = NULL;
+                       }
                        (*pcmp)->dl_handle = h;
                        err = 0;
                } else {
-                       snd_dlclose(h);
+                       if (h)
+                               snd_dlclose(h);
                }
        }
+       if (type_conf)
+               snd_config_delete(type_conf);
        if (buf)
                free(buf);
        if (buf1)