aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorHo-Eun Ryu <ho-eun.ryu@windriver.com>2009-09-25 10:19:52 +0900
committerPatrick Tjin <pattjin@google.com>2014-07-21 22:03:21 -0700
commit3597788ce7c666b2e86df3932968f0745f4b7bd1 (patch)
treecca9197add4cf8b72dd3cdf33fbaa64ba6144498 /utils
parent08373062d895bb9673e7391551d4756cd68e37fa (diff)
downloadwrs_omxil_core-3597788ce7c666b2e86df3932968f0745f4b7bd1.tar.gz
utils:list,queue,module: add utility routines
it has list, queue, module and etc
Diffstat (limited to 'utils')
-rw-r--r--utils/inc/list.h74
-rw-r--r--utils/inc/log.h17
-rw-r--r--utils/inc/module.h44
-rw-r--r--utils/inc/queue.h48
-rw-r--r--utils/src/ebuild.mk22
-rw-r--r--utils/src/list.c258
-rw-r--r--utils/src/module.c257
-rw-r--r--utils/src/queue.c189
8 files changed, 909 insertions, 0 deletions
diff --git a/utils/inc/list.h b/utils/inc/list.h
new file mode 100644
index 0000000..4dcb9c2
--- /dev/null
+++ b/utils/inc/list.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#ifndef __LIST_H
+#define __LIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct list {
+ struct list *next;
+ struct list *prev;
+
+ void *data;
+};
+
+void __list_init(struct list *);
+
+struct list *__list_alloc(void);
+struct list *list_alloc(void *);
+
+void __list_free(struct list *);
+void list_free_all(struct list *);
+
+struct list *__list_last(struct list *);
+struct list *__list_first(struct list *);
+struct list *__list_entry(struct list *, int);
+int list_length(struct list *);
+
+struct list *__list_add_before(struct list *, struct list *);
+struct list *__list_add_after(struct list *, struct list *);
+struct list *__list_add_head(struct list *, struct list *);
+struct list *__list_add_tail(struct list *, struct list *);
+struct list *list_add_head(struct list *, void *);
+struct list *list_add_tail(struct list *, void *);
+
+struct list *__list_remove(struct list *, struct list *);
+struct list *__list_delete(struct list *, struct list *);
+struct list *list_delete(struct list *, void *);
+struct list *list_delete_all(struct list *, void *);
+
+struct list *list_find(struct list *, void *);
+struct list *list_find_reverse(struct list *, void *);
+
+#define __list_next(entry) ((entry) ? (entry->next) : NULL)
+#define __list_prev(entry) ((entry) ? (entry->prev) : NULL)
+
+#define list_foreach(list, ptr) \
+ for (ptr = list; \
+ ptr != NULL; \
+ ptr = __list_next(ptr))
+
+#define list_foreach_safe(list, ptr, nxt) \
+ for (ptr = list, nxt = __list_next(ptr); \
+ ptr != NULL; \
+ ptr = nxt, nxt = __list_next(ptr))
+
+#define list_foreach_reverse(list, ptr) \
+ for (ptr = __list_last(list); \
+ ptr != NULL; \
+ ptr = __list_prev(ptr))
+
+#define list_foreach_reverse_safe(list, ptr, prv) \
+ for (ptr = __list_last(list), prv = __list_prev(ptr); \
+ ptr != NULL; \
+ ptr = prv, prv = __list_prev(ptr))
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __LIST_H */
diff --git a/utils/inc/log.h b/utils/inc/log.h
new file mode 100644
index 0000000..dd22642
--- /dev/null
+++ b/utils/inc/log.h
@@ -0,0 +1,17 @@
+#ifndef __LOG_H
+#define __LOG_H
+
+#ifdef ANDROID
+ #include <cutils/log.h>
+#else
+ #include <stdio.h>
+ #define LOG(_p, ...) \
+ fprintf(stderr, _p "/" LOG_TAG ": " __VA_ARGS__)
+ #define LOGV(...) LOG("V", __VA_ARGS__)
+ #define LOGD(...) LOG("D", __VA_ARGS__)
+ #define LOGI(...) LOG("I", __VA_ARGS__)
+ #define LOGW(...) LOG("W", __VA_ARGS__)
+ #define LOGE(...) LOG("E", __VA_ARGS__)
+#endif
+
+#endif /* __LOG_H */
diff --git a/utils/inc/module.h b/utils/inc/module.h
new file mode 100644
index 0000000..bb697ef
--- /dev/null
+++ b/utils/inc/module.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#ifndef __MODULE_H
+#define __MODULE_H
+
+#include <dlfcn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct module;
+
+typedef int (*module_init_t)(struct module *module);
+typedef void (*module_exit_t)(struct module *module);
+
+struct module {
+ char *name;
+
+ int ref_count;
+ void *handle;
+
+ module_init_t init;
+ module_exit_t exit;
+
+ void *priv;
+ struct module *next;
+};
+
+#define MODULE_LAZY RTLD_LAZY
+#define MODULE_NOW RTLD_NOW
+#define MODUEL_GLOBAL RTLD_GLOBAL
+
+struct module *module_open(const char *path, int flag);
+int module_close(struct module *module);
+void *module_symbol(struct module *module, const char *string);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __MODULE_H */
diff --git a/utils/inc/queue.h b/utils/inc/queue.h
new file mode 100644
index 0000000..ec0b1f4
--- /dev/null
+++ b/utils/inc/queue.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#ifndef __QUEUE_H
+#define __QUEUE_H
+
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct queue {
+ struct list *head;
+ struct list *tail;
+ int length;
+};
+
+void __queue_init(struct queue *queue);
+struct queue *queue_alloc(void);
+/* FIXME */
+inline void __queue_free(struct queue *queue);
+/* FIXME */
+void queue_free_all(struct queue *queue);
+
+void __queue_push_head(struct queue *queue, struct list *entry);
+int queue_push_head(struct queue *queue, void *data);
+void __queue_push_tail(struct queue *queue, struct list *entry);
+int queue_push_tail(struct queue *queue, void *data);
+
+struct list *__queue_pop_head(struct queue *queue);
+void *queue_pop_head(struct queue *queue);
+struct list *__queue_pop_tail(struct queue *queue);
+void *queue_pop_tail(struct queue *queue);
+
+inline struct list *__queue_peek_head(struct queue *queue);
+inline struct list *__queue_peek_tail(struct queue *queue);
+inline void *queue_peek_head(struct queue *queue);
+inline void *queue_peek_tail(struct queue *queue);
+
+int queue_length(struct queue *queue);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __QUEUE_H */
diff --git a/utils/src/ebuild.mk b/utils/src/ebuild.mk
new file mode 100644
index 0000000..c8f4055
--- /dev/null
+++ b/utils/src/ebuild.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ list.c \
+ queue.c \
+ module.c
+
+LOCAL_MODULE := libwrs_omxil_utils
+
+LOCAL_CFLAGS :=
+
+LOCAL_CPPFLAGS :=
+
+LOCAL_LDFLAGS :=
+
+LOCAL_SHARED_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+ $(WRS_OMXIL_CORE_ROOT)/utils/inc
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/utils/src/list.c b/utils/src/list.c
new file mode 100644
index 0000000..553d85f
--- /dev/null
+++ b/utils/src/list.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#include <stdlib.h>
+
+#include <list.h>
+
+void __list_init(struct list *entry)
+{
+ if (entry) {
+ entry->prev = NULL;
+ entry->next = NULL;
+ entry->data = NULL;
+ }
+}
+
+struct list *__list_alloc(void)
+{
+ struct list *new;
+
+ new = malloc(sizeof(struct list));
+ __list_init(new);
+
+ return new;
+}
+
+struct list *list_alloc(void *data)
+{
+ struct list *new;
+
+ new = __list_alloc();
+ if (new)
+ new->data = data;
+
+ return new;
+}
+
+void __list_free(struct list *entry)
+{
+ free(entry);
+}
+
+void list_free_all(struct list *list)
+{
+ struct list *ptr, *tmp;
+
+ list_foreach_safe(list, ptr, tmp) {
+ __list_free(ptr);
+ }
+}
+
+struct list *__list_last(struct list *list)
+{
+ if (list)
+ while (list->next)
+ list = list->next;
+
+ return list;
+}
+
+struct list *__list_first(struct list *list)
+{
+ if (list)
+ while (list->prev)
+ list = list->prev;
+
+ return list;
+}
+
+struct list *__list_entry(struct list *list, int index)
+{
+ struct list *entry;
+ int i = 0;
+
+ list_foreach(list, entry) {
+ if (i == index)
+ break;
+ i++;
+ }
+
+ return entry;
+}
+
+int list_length(struct list *list)
+{
+ int length = 0;
+
+ while (list) {
+ list = list->next;
+ length++;
+ }
+
+ return length;
+}
+
+struct list *__list_add_before(struct list *entry, struct list *new)
+{
+ struct list *prev;
+
+ if (entry) {
+ prev = entry->prev;
+ if (prev)
+ prev->next = new;
+ new->prev = prev;
+ new->next = entry;
+ entry->prev = new;
+ }
+
+ return new;
+}
+
+struct list *__list_add_after(struct list *entry, struct list *new)
+{
+ struct list *next;
+
+ if (entry) {
+ next = entry->next;
+ if (next)
+ next->prev = new;
+ new->next = next;
+ new->prev = entry;
+ entry->next = new;
+
+ return entry;
+ }
+
+ return new;
+}
+
+struct list *__list_add_head(struct list *list, struct list *new)
+{
+ struct list *first;
+
+ if (list) {
+ first = __list_first(list);
+ __list_add_before(first, new);
+ }
+
+ return new;
+}
+
+struct list *__list_add_tail(struct list *list, struct list *new)
+{
+ struct list *last;
+
+ if (list) {
+ last = __list_last(list);
+ __list_add_after(last, new);
+
+ return list;
+ }
+ else
+ return new;
+}
+
+struct list *list_add_head(struct list *list, void *data)
+{
+ struct list *new;
+
+ new = list_alloc(data);
+ if (!new)
+ return NULL;
+
+ return __list_add_head(list, new);
+}
+
+struct list *list_add_tail(struct list *list, void *data)
+{
+ struct list *new;
+
+ new = list_alloc(data);
+ if (!new)
+ return NULL;
+
+ return __list_add_tail(list, new);
+}
+
+struct list *__list_remove(struct list *list, struct list *entry)
+{
+ struct list *prev, *next;
+
+ if (entry) {
+ prev = entry->prev;
+ next = entry->next;
+
+ if (prev)
+ prev->next = next;
+ else
+ list = next;
+ if (next)
+ next->prev = prev;
+
+ entry->prev = NULL;
+ entry->next = NULL;
+ }
+
+ return list;
+}
+
+struct list *__list_delete(struct list *list,
+ struct list *entry)
+{
+ list = __list_remove(list, entry);
+ __list_free(entry);
+
+ return list;
+}
+
+struct list *list_delete(struct list *list, void *data)
+{
+ struct list *ptr, *tmp;
+
+ list_foreach_safe(list, ptr, tmp) {
+ if (ptr->data == data) {
+ list = __list_delete(list, ptr);
+ break;
+ }
+ }
+
+ return list;
+}
+
+struct list *list_delete_all(struct list *list, void *data)
+{
+ struct list *ptr, *tmp;
+
+ list_foreach_safe(list, ptr, tmp) {
+ if (ptr->data == data)
+ list = __list_delete(list, ptr);
+ }
+
+ return list;
+}
+
+struct list *list_find(struct list *list, void *data)
+{
+ struct list *ptr;
+
+ list_foreach(list, ptr) {
+ if (ptr->data == data)
+ break;
+ }
+
+ return ptr;
+}
+
+struct list *list_find_reverse(struct list *list, void *data)
+{
+ struct list *ptr;
+
+ list_foreach_reverse(list, ptr) {
+ if (ptr->data == data)
+ break;
+ }
+
+ return ptr;
+}
diff --git a/utils/src/module.c b/utils/src/module.c
new file mode 100644
index 0000000..ce668c3
--- /dev/null
+++ b/utils/src/module.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <module.h>
+
+#define LOG_TAG "module"
+#include <log.h>
+
+static struct module *g_module_head;
+static char *g_module_err;
+
+static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define for_each_module(__module, __head) \
+ for ((__module) = (__head); (__module) != NULL; \
+ (__module) = (__module)->next)
+
+#define find_last_module(__head) \
+ ({ \
+ struct module *m; \
+ \
+ for_each_module(m, (__head)) { \
+ if (!m->next) \
+ break; \
+ } \
+ m; \
+ })
+
+
+static struct module *module_find_with_name(const char *filename)
+{
+ struct module *module;
+
+ for_each_module(module, g_module_head) {
+ if (!strcmp(module->name, filename))
+ return module;
+ }
+
+ return NULL;
+}
+
+static struct module *module_find_with_handle(const void *handle)
+{
+ struct module *module;
+
+ for_each_module(module, g_module_head) {
+ if (module->handle == handle)
+ return module;
+ }
+
+ return NULL;
+}
+
+static struct module *module_add_list(struct module *head,
+ struct module *add)
+{
+ struct module *last;
+
+ last = find_last_module(head);
+ if (last)
+ last->next = add;
+ else
+ g_module_head = add;
+
+ return g_module_head;
+}
+
+static struct module *module_del_list(struct module *head,
+ struct module *del)
+{
+ struct module *prev = NULL;
+
+ for_each_module(prev, head) {
+ if (prev->next == del)
+ break;
+ }
+
+ if (!prev)
+ g_module_head = del->next;
+ else
+ prev->next = del->next;
+
+ return g_module_head;
+}
+
+static inline void module_set_error(const char *dlerr)
+{
+ if (g_module_err)
+ free(g_module_err);
+
+ if (dlerr)
+ g_module_err = strdup(dlerr);
+ else
+ g_module_err = NULL;
+}
+
+const char *module_error(void)
+{
+ return g_module_err;
+}
+
+struct module *module_open(const char *file, int flag)
+{
+ struct module *new, *existing;
+ void *handle;
+ const char *dlerr;
+ int init_ret = 0;
+
+ pthread_mutex_lock(&g_lock);
+
+ existing = module_find_with_name(file);
+ if (existing) {
+ LOGE("found opened module %s\n", existing->name);
+ existing->ref_count++;
+ pthread_mutex_unlock(&g_lock);
+ return existing;
+ }
+
+ new = malloc(sizeof(*new));
+ if (!new) {
+ pthread_mutex_unlock(&g_lock);
+ return NULL;
+ }
+
+ new->ref_count = 1;
+ new->priv = NULL;
+ new->next = NULL;
+
+ dlerror();
+ new->handle = dlopen(file, flag);
+ dlerr = dlerror();
+ if (dlerr) {
+ LOGE("dlopen failed (%s)\n", dlerr);
+ module_set_error(dlerr);
+ pthread_mutex_unlock(&g_lock);
+ goto free_new;
+ }
+
+ existing = module_find_with_handle(new->handle);
+ if (existing) {
+ LOGE("found opened module %s\n", existing->name);
+ existing->ref_count++;
+ module_close(new);
+ pthread_mutex_unlock(&g_lock);
+ return existing;
+ }
+
+ dlerror();
+ new->init = dlsym(new->handle, "module_init");
+ dlerr = dlerror();
+ if (!dlerr) {
+ LOGE("module %s has init(), call the symbol\n", new->name);
+ init_ret = new->init(new);
+ }
+
+ if (init_ret) {
+ LOGE("module %s init() failed (%d)\n", new->name, init_ret);
+ pthread_mutex_unlock(&g_lock);
+ goto free_handle;
+ }
+
+ dlerror();
+ new->exit = dlsym(new->handle, "module_exit");
+ dlerr = dlerror();
+ if (dlerr)
+ new->exit = NULL;
+
+ new->name = strdup(file);
+ if (!new->name) {
+ if (new->exit)
+ new->exit(new);
+ goto free_handle;
+ }
+
+ module_add_list(g_module_head, new);
+
+ pthread_mutex_unlock(&g_lock);
+ return new;
+
+free_handle:
+ dlclose(new->handle);
+
+free_new:
+ free(new);
+
+ pthread_mutex_unlock(&g_lock);
+ return NULL;
+}
+
+int module_close(struct module *module)
+{
+ const char *dlerr;
+ int ret = 0;
+
+ if (!module || !module->handle)
+ return 0;
+
+ pthread_mutex_lock(&g_lock);
+
+ module->ref_count--;
+ ret = module->ref_count;
+
+ LOGV("module %s decrease refcont (%d)\n", module->name, module->ref_count);
+
+ if (!module->ref_count) {
+ if (module->exit)
+ module->exit(module);
+
+ dlerror();
+ dlclose(module->handle);
+ dlerr = dlerror();
+ if (dlerr) {
+ module_set_error(dlerr);
+ ret = -1;
+ }
+
+ module_del_list(g_module_head, module);
+ free(module->name);
+ free(module);
+
+ LOGV("module %s closed\n", module->name);
+ }
+
+ pthread_mutex_unlock(&g_lock);
+ return ret;
+}
+
+void *module_symbol(struct module *module, const char *string)
+{
+ void *symbol;
+ const char *dlerr;
+
+ if (!module || !module->handle || !string)
+ return NULL;
+
+ pthread_mutex_lock(&g_lock);
+
+ dlerror();
+ symbol = dlsym(module->handle, string);
+ dlerr = dlerror();
+ if (dlerr) {
+ LOGE("not founded symbol %s in module %s (%s)\n",
+ string, module->name, dlerr);
+ module_set_error(dlerr);
+ symbol = NULL;
+ }
+ else
+ LOGV("found symbol %s in module %s\n", string, module->name);
+
+ pthread_mutex_unlock(&g_lock);
+ return symbol;
+}
diff --git a/utils/src/queue.c b/utils/src/queue.c
new file mode 100644
index 0000000..2717928
--- /dev/null
+++ b/utils/src/queue.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2009 Wind River Systems.
+ */
+
+#include <stdlib.h>
+
+#include <queue.h>
+
+inline void __queue_init(struct queue *queue)
+{
+ queue->head = NULL;
+ queue->tail = NULL;
+ queue->length = 0;
+}
+
+struct queue *queue_alloc(void)
+{
+ struct queue *queue;
+
+ queue = malloc(sizeof(struct queue));
+ if (queue)
+ __queue_init(queue);
+
+ return queue;
+}
+
+inline void __queue_free(struct queue *queue)
+{
+ free(queue);
+}
+
+void queue_free_all(struct queue *queue)
+{
+ struct list *list = queue->head;
+
+ list_free_all(list);
+ __queue_init(queue);
+}
+
+void __queue_push_head(struct queue *queue, struct list *entry)
+{
+ queue->head = __list_add_head(queue->head, entry);
+ if (!queue->tail)
+ queue->tail = queue->head;
+
+ queue->length++;
+}
+
+int queue_push_head(struct queue *queue, void *data)
+{
+ struct list *entry = list_alloc(data);
+
+ if (!entry)
+ return -1;
+ else
+ queue->head = __list_add_head(queue->head, entry);
+
+ if (!queue->tail)
+ queue->tail = queue->head;
+
+ queue->length++;
+ return 0;
+}
+
+void __queue_push_tail(struct queue *queue, struct list *entry)
+{
+ queue->tail = list_add_tail(queue->tail, entry);
+ if (queue->tail->next)
+ queue->tail = queue->tail->next;
+ else
+ queue->head = queue->tail;
+
+ queue->length++;
+}
+
+int queue_push_tail(struct queue *queue, void *data)
+{
+ struct list *entry = list_alloc(data);
+
+ if (!entry)
+ return -1;
+ else
+ queue->tail = __list_add_tail(queue->tail, entry);
+
+ if (queue->tail->next)
+ queue->tail = queue->tail->next;
+ else
+ queue->head = queue->tail;
+
+ queue->length++;
+ return 0;
+}
+
+struct list *__queue_pop_head(struct queue *queue)
+{
+ struct list *entry = queue->head;
+
+ if (entry) {
+ queue->head = __list_remove(queue->head, entry);
+ if (!queue->head)
+ queue->tail = NULL;
+
+ queue->length--;
+ }
+
+ return entry;
+}
+
+void *queue_pop_head(struct queue *queue)
+{
+ struct list *entry;
+ void *data = NULL;
+
+ entry = __queue_pop_head(queue);
+ if (entry) {
+ data = entry->data;
+ __list_free(entry);
+ }
+
+ return data;
+}
+
+struct list *__queue_pop_tail(struct queue *queue)
+{
+ struct list *entry = queue->tail;
+ struct list *prev;
+
+ if (entry) {
+ prev = entry->prev;
+ queue->head = __list_remove(queue->head, entry);
+ queue->tail = prev;
+ queue->length--;
+ }
+
+ return entry;
+}
+
+void *queue_pop_tail(struct queue *queue)
+{
+ struct list *entry;
+ void *data = NULL;
+
+ entry = __queue_pop_tail(queue);
+ if (entry) {
+ data = entry->data;
+ __list_free(entry);
+ }
+
+ return data;
+}
+
+inline struct list *__queue_peek_head(struct queue *queue)
+{
+ return queue->head;
+}
+
+inline struct list *__queue_peek_tail(struct queue *queue)
+{
+ return queue->tail;
+}
+
+inline void *queue_peek_head(struct queue *queue)
+{
+ struct list *entry;
+ void *data = NULL;
+
+ entry = __queue_peek_head(queue);
+ if (entry)
+ data = entry->data;
+
+ return data;
+}
+
+inline void *queue_peek_tail(struct queue *queue)
+{
+ struct list *entry;
+ void *data = NULL;
+
+ entry = __queue_peek_tail(queue);
+ if (entry)
+ data = entry->data;
+
+ return data;
+}
+
+int queue_length(struct queue *queue)
+{
+ return queue->length;
+}