diff options
author | Ho-Eun Ryu <ho-eun.ryu@windriver.com> | 2009-09-25 10:19:52 +0900 |
---|---|---|
committer | Patrick Tjin <pattjin@google.com> | 2014-07-21 22:03:21 -0700 |
commit | 3597788ce7c666b2e86df3932968f0745f4b7bd1 (patch) | |
tree | cca9197add4cf8b72dd3cdf33fbaa64ba6144498 /utils | |
parent | 08373062d895bb9673e7391551d4756cd68e37fa (diff) | |
download | wrs_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.h | 74 | ||||
-rw-r--r-- | utils/inc/log.h | 17 | ||||
-rw-r--r-- | utils/inc/module.h | 44 | ||||
-rw-r--r-- | utils/inc/queue.h | 48 | ||||
-rw-r--r-- | utils/src/ebuild.mk | 22 | ||||
-rw-r--r-- | utils/src/list.c | 258 | ||||
-rw-r--r-- | utils/src/module.c | 257 | ||||
-rw-r--r-- | utils/src/queue.c | 189 |
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; +} |