From 0f6198855c173189e128eada7fcffc8e5007ad5b Mon Sep 17 00:00:00 2001 From: raster Date: Fri, 10 Jul 2009 06:52:09 +0000 Subject: [PATCH] cserve for evas now has a threaded loader - much better when multiple clients aare hammering it with load requests git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@41293 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/bin/evas_cserve_main.c | 156 ++++++++++++++++++++++++++++++++++++---- src/lib/cserve/evas_cs.h | 1 + src/lib/cserve/evas_cs_server.c | 7 ++ src/lib/include/evas_common.h | 2 + 4 files changed, 153 insertions(+), 13 deletions(-) diff --git a/src/bin/evas_cserve_main.c b/src/bin/evas_cserve_main.c index 5d46ae1..770485f 100644 --- a/src/bin/evas_cserve_main.c +++ b/src/bin/evas_cserve_main.c @@ -9,6 +9,10 @@ # include #endif +#ifdef BUILD_PTHREAD +#include +#endif + #include "Evas.h" #include "evas_cs.h" @@ -23,6 +27,7 @@ typedef struct _Img Img; typedef struct _Lopt Lopt; +typedef struct _Load_Inf Load_Inf; struct _Lopt { @@ -57,11 +62,18 @@ struct _Img Eina_Bool alpha : 1; } image; int incache; + LK(lock); Eina_Bool dead : 1; Eina_Bool active : 1; Eina_Bool useless : 1; }; +struct _Load_Inf +{ + Img *img; + Client *c; +}; + // config static int stat_res_interval = 2; @@ -72,6 +84,7 @@ static int server_id = 0; static Evas_Cache_Image *cache = NULL; static Eina_Hash *active_images = NULL; +LK(cache_lock); static Eina_List *cache_images = NULL; static int cache_usage = 0; static int cache_max_usage = 1 * 1024; @@ -155,6 +168,7 @@ stats_hash_image_cb(const Eina_Hash *hash __UNUSED__, { Img *img = data; + saved_load_time += img->stats.load1 * img->stats.load1saved; saved_loaddata_time += img->stats.load2 * img->stats.load2saved; if (img->ref > 1) @@ -185,6 +199,7 @@ stats_calc(void) if (active_images) eina_hash_foreach(active_images, stats_hash_image_cb, NULL); + LKL(cache_lock); EINA_LIST_FOREACH(cache_images, l, img) { saved_loads += img->stats.load1saved; @@ -197,6 +212,7 @@ stats_calc(void) real_memory += (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) >> 12) << 12; } } + LKU(cache_lock); if (saved_memory > saved_memory_peak) saved_memory_peak = saved_memory; if (real_memory > real_memory_peak) @@ -416,6 +432,7 @@ img_init(void) active_images = eina_hash_string_superfast_new(NULL); cache = evas_cache_image_init(&cache_funcs); + LKI(cache_lock); } static void @@ -476,6 +493,7 @@ img_loaddata(Img *img) if (img->mem) return; t = get_time(); + LKL(cache_lock); evas_cache_image_load_data((Image_Entry *)img); t = get_time() - t; img->stats.load2 = t; @@ -486,6 +504,7 @@ img_loaddata(Img *img) (4096 * (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) / 4096)) + sizeof(Mem); if (!img->active) cache_usage += img->usage; + LKU(cache_lock); cache_clean(); } @@ -512,12 +531,14 @@ static void cache_clean(void) { D("... cache clean!!! do\n"); + LKL(cache_lock); while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) && (cache_images)) { Img *img; Eina_List *l; + LKL(img->lock); D("... clean loop %i > %i\n", cache_usage, (cache_max_usage + cache_max_adjust) * 1024); l = eina_list_last(cache_images); if (!l) break; @@ -530,6 +551,7 @@ cache_clean(void) D("... IMG FREE %p\n", img); img_free(img); } + LKU(cache_lock); } static void @@ -539,8 +561,10 @@ cache_timeout(time_t t) Img *img; if (cache_item_timeout < 0) return; + LKL(cache_lock); EINA_LIST_FOREACH_SAFE(cache_images, l, l_next, img) { + LKL(img->lock); if ((t - img->cached) > cache_item_timeout) { cache_images = eina_list_remove_list(cache_images, l); @@ -548,7 +572,10 @@ cache_timeout(time_t t) cache_usage -= img->usage; img_free(img); } + else + LKU(img->lock); } + LKU(cache_lock); } static void @@ -580,6 +607,7 @@ mem_cache_adjust(void) if (pval != cache_max_adjust) { D("... cache clean\n"); + // FIXME lock problem cache_clean(); } } @@ -592,7 +620,7 @@ img_cache(Img *img) { D("... img %p '%s' dead\n", img , img->file.file); img_free(img); - return; + return; } if ((cache_usage + img->usage) > ((cache_max_usage + cache_max_adjust) * 1024)) { @@ -609,11 +637,14 @@ img_cache(Img *img) printf("EEEEEEEEEEEEEEEEK!\n"); return; } + LKL(cache_lock); cache_images = eina_list_prepend(cache_images, img); + LKU(cache_lock); img->incache++; cache_usage += img->usage; img->active = 0; img->cached = t_now; + // FIXME: lock problem if (cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) cache_clean(); } @@ -622,7 +653,9 @@ static void img_dead(Img *img) { if (img->active) return; + LKL(cache_lock); cache_images = eina_list_remove(cache_images, img); + LKU(cache_lock); img->incache--; cache_usage -= img->usage; img_free(img); @@ -691,10 +724,12 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts) } // FIXME: keep hash of cached images too + LKL(cache_lock); EINA_LIST_FOREACH_SAFE(cache_images, l, l_next, img) { if (!strcmp(img->key, buf)) { + LKL(img->lock); if (img_ok(img)) { D("... found cached\n"); @@ -708,10 +743,14 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts) D("... sats update\n"); stats_update(); D("... return %p\n", img); + LKU(img->lock); + LKU(cache_lock); return img; } + LKU(img->lock); } } + LKU(cache_lock); D("... ned new img\n"); return img_new(file, key, load_opts, buf); } @@ -815,6 +854,46 @@ getinfo_hash_image_cb(const Eina_Hash *hash __UNUSED__, return 1; } +#ifdef BUILD_PTHREAD +static void * +load_data_thread(void *data) +{ + Load_Inf *li = data; + Img *img = li->img; + Client *c = li->c; + Op_Loaddata_Reply msg; + + free(li); + LKL(img->lock); + if (img->mem) + { + memset(&msg, 0, sizeof(msg)); + msg.mem.id = img->mem->id; + msg.mem.offset = img->mem->offset; + msg.mem.size = img->mem->size; + D("... reply\n"); + evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); + LKU(c->lock); + return NULL; + } + img_loaddata(img); + memset(&msg, 0, sizeof(msg)); + if (img->mem) + { + msg.mem.id = img->mem->id; + msg.mem.offset = img->mem->offset; + msg.mem.size = img->mem->size; + } + else + msg.mem.id = msg.mem.offset = msg.mem.size = 0; + LKU(img->lock); + D("... reply\n"); + evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); + LKU(c->lock); + return NULL; +} +#endif + static int message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data) { @@ -903,7 +982,9 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * D("... remove %p from list\n", img); c->data = eina_list_remove(c->data, img); D("... unload %p\n", img); + LKL(img->lock); img_unload(img); + LKU(img->lock); } } break; @@ -923,26 +1004,62 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * D("... load saved - cached %p\n", img); img->stats.load2saved++; stats_update(); + memset(&msg, 0, sizeof(msg)); + if (img->mem) + { + msg.mem.id = img->mem->id; + msg.mem.offset = img->mem->offset; + msg.mem.size = img->mem->size; + } + else + msg.mem.id = msg.mem.offset = msg.mem.size = 0; + D("... reply\n"); + evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); } else { +#ifdef BUILD_PTHREAD + pthread_t tid; + pthread_attr_t attr; + Load_Inf *li; + D("... load data %p\n", img); + pthread_attr_init(&attr); + li = calloc(1, sizeof(Load_Inf)); + if (li) + { + li->img= img; + li->c = c; + LKL(c->lock); + if (pthread_create(&tid, &attr, load_data_thread, li)) + { + perror("pthread_create()"); + } + else + pthread_detach(tid); + } + pthread_attr_destroy(&attr); +#else img_loaddata(img); + memset(&msg, 0, sizeof(msg)); + if (img->mem) + { + msg.mem.id = img->mem->id; + msg.mem.offset = img->mem->offset; + msg.mem.size = img->mem->size; + } + else + msg.mem.id = msg.mem.offset = msg.mem.size = 0; + D("... reply\n"); + evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); +#endif } - memset(&msg, 0, sizeof(msg)); - if (img->mem) - { - msg.mem.id = img->mem->id; - msg.mem.offset = img->mem->offset; - msg.mem.size = img->mem->size; - } - else - msg.mem.id = msg.mem.offset = msg.mem.size = 0; } else - msg.mem.id = msg.mem.offset = msg.mem.size = 0; - D("... reply\n"); - evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); + { + msg.mem.id = msg.mem.offset = msg.mem.size = 0; + evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)); + } } break; case OP_UNLOADDATA: @@ -956,10 +1073,12 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * if ((img) && (rep->server_id == server_id)) { D("... dref--\n"); + LKL(img->lock); img->dref--; if (img->dref < 0) img->dref = 0; D("... unload data %p '%s'\n", img, img->file.file); img_unloaddata(img); + LKU(img->lock); } } break; @@ -974,10 +1093,12 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * if ((img) && (rep->server_id == server_id)) { D("... dref--\n"); + LKL(img->lock); img->dref--; if (img->dref < 0) img->dref = 0; D("... useless %p\n", img); img_useless(img); + LKU(img->lock); } } break; @@ -991,8 +1112,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * img = rep->handle; if ((img) && (rep->server_id == server_id)) { + LKL(img->lock); c->data = eina_list_remove(c->data, img); + // FIXME: preload doesnt work async img_preload(img); + LKU(img->lock); } } case OP_FORCEDUNLOAD: @@ -1005,10 +1129,12 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * img = rep->handle; if ((img) && (rep->server_id == server_id)) { + LKL(img->lock); D("remove %p from list\n", img); c->data = eina_list_remove(c->data, img); D("... forced unload now\n"); img_forcedunload(img); + LKU(img->lock); } } break; @@ -1068,10 +1194,12 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * if (active_images) eina_hash_foreach(active_images, getinfo_hash_image_cb, &imgs); D("... walk foreach list output\n"); + LKL(cache_lock); EINA_LIST_FOREACH(cache_images, l, img) { imgs = eina_list_append(imgs, img); } + LKU(cache_lock); D("... walk image cache\n"); EINA_LIST_FOREACH(imgs, l, img) { @@ -1100,6 +1228,7 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * { Op_Getinfo_Item *itt, it; + LKL(img->lock); D("... img %p\n", img); memset(&it, 0, sizeof(Op_Getinfo_Item)); itt = (Op_Getinfo_Item *)p; @@ -1155,6 +1284,7 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char * memcpy(itt, &it, sizeof(Op_Getinfo_Item)); D("... memcpy done n\n", img); p += sizeof(Op_Getinfo_Item) + it.file_key_size; + LKU(img->lock); } D("... walk all imgs done\n"); msg->active.mem_total = diff --git a/src/lib/cserve/evas_cs.h b/src/lib/cserve/evas_cs.h index 68b3085..d23e028 100644 --- a/src/lib/cserve/evas_cs.h +++ b/src/lib/cserve/evas_cs.h @@ -80,6 +80,7 @@ struct _Client void *data; pid_t pid; int req_from, req_to; + LK(lock); }; struct _Mem diff --git a/src/lib/cserve/evas_cs_server.c b/src/lib/cserve/evas_cs_server.c index 63286a3..7d149fa 100644 --- a/src/lib/cserve/evas_cs_server.c +++ b/src/lib/cserve/evas_cs_server.c @@ -68,9 +68,11 @@ evas_cserve_server_del(Server *s) EINA_LIST_FREE(s->clients, c) { + LKL(c->lock); close(c->fd); if (c->buf) free(c->buf); if (c->inbuf) free(c->inbuf); + LKD(c->lock); free(c); } close(s->fd); @@ -100,6 +102,7 @@ server_accept(Server *s) } c->server = s; c->fd = new_fd; + LKI(c->lock); s->clients = eina_list_append(s->clients, c); } @@ -183,10 +186,12 @@ evas_cserve_client_send(Client *c, int opcode, int size, unsigned char *data) ints = (int *)data2; ints[0] = size; ints[1] = opcode; +// LKL(c->lock); c->req_to++; ints[2] = c->req_to; memcpy(data2 + (sizeof(int) * 3), data, size); client_write(c, data2, size + (sizeof(int) * 3)); +// LKU(c->lock); free(data2); } @@ -361,11 +366,13 @@ evas_cserve_server_wait(Server *s, int timeout) } EINA_LIST_FREE(dead, c) { + LKL(c->lock); if (c->func) c->func(c->data, c); s->clients = eina_list_remove(s->clients, c); close(c->fd); if (c->buf) free(c->buf); if (c->inbuf) free(c->inbuf); + LKD(c->lock); free(c); } } diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index c11a074..f4b7286 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -94,6 +94,7 @@ # define LKI(x) pthread_mutex_init(&(x), NULL); # define LKD(x) pthread_mutex_destroy(&(x)); # define LKL(x) pthread_mutex_lock(&(x)); +# define LKT(x) pthread_mutex_trylock(&(x)); # define LKU(x) pthread_mutex_unlock(&(x)); # define TH(x) pthread_t x # define THI(x) int x @@ -108,6 +109,7 @@ # define LKI(x) # define LKD(x) # define LKL(x) +# define LKT(x) 0 # define LKU(x) # define TH(x) # define THI(x) -- 2.7.4