From d8f7de1b16ff7e68f7dd9464243efbdc547063fa Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 14 Feb 2005 15:09:09 +0000 Subject: [PATCH] Support dl-object cache Added the support of dl-object caches for PCM plugins. --- include/local.h | 5 ++++ include/pcm_ioplug.h | 3 ++ src/conf.c | 4 +++ src/dlmisc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ src/pcm/pcm.c | 16 +++++++++-- 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/include/local.h b/include/local.h index 6df4abca..61ec10d8 100644 --- a/include/local.h +++ b/include/local.h @@ -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 diff --git a/include/pcm_ioplug.h b/include/pcm_ioplug.h index 62c064ac..03b0540b 100644 --- a/include/pcm_ioplug.h +++ b/include/pcm_ioplug.h @@ -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 */ diff --git a/src/conf.c b/src/conf.c index 066e07e1..26007832 100644 --- a/src/conf.c +++ b/src/conf.c @@ -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; } diff --git a/src/dlmisc.c b/src/dlmisc.c index a5d174d7..6298e483 100644 --- a/src/dlmisc.c +++ b/src/dlmisc.c @@ -29,6 +29,7 @@ #define _GNU_SOURCE #include +#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); + } +} diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index a4df4698..c2fc9547 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -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) -- 2.47.1