From deb8776de5b46e280371fc0db894db96287cf681 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 18 Jul 2013 19:21:58 +0900 Subject: [PATCH] evas/cserve2: Add functions to resize shm files - cserve2_shm_segment_request() Creates a new shm segment (Shm_Handle) from an existing file, without changing the current mmap. - cserve2_shm_resize() Grows the file and remaps in memory (new virtual address). - cserve2_shm_id_get() Returns the shm creation ID. --- src/bin/evas/evas_cserve2.h | 3 + src/bin/evas/evas_cserve2_shm.c | 104 +++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/bin/evas/evas_cserve2.h b/src/bin/evas/evas_cserve2.h index 158e3e2ab0..e7e53f3774 100644 --- a/src/bin/evas/evas_cserve2.h +++ b/src/bin/evas/evas_cserve2.h @@ -264,8 +264,11 @@ void cserve2_message_handler(int fd, Fd_Flags flags, void *data); void cserve2_shm_init(); void cserve2_shm_shutdown(); Shm_Handle *cserve2_shm_request(const char *infix, size_t size); +Shm_Handle *cserve2_shm_segment_request(Shm_Handle *shm, size_t size); +Shm_Handle *cserve2_shm_resize(Shm_Handle *shm, size_t newsize); void cserve2_shm_unref(Shm_Handle *shm); const char *cserve2_shm_name_get(const Shm_Handle *shm); +int cserve2_shm_id_get(const Shm_Handle *shm); off_t cserve2_shm_map_offset_get(const Shm_Handle *shm); off_t cserve2_shm_offset_get(const Shm_Handle *shm); size_t cserve2_shm_map_size_get(const Shm_Handle *shm); diff --git a/src/bin/evas/evas_cserve2_shm.c b/src/bin/evas/evas_cserve2_shm.c index 7dcf05dbb6..2df0bb5e60 100644 --- a/src/bin/evas/evas_cserve2_shm.c +++ b/src/bin/evas/evas_cserve2_shm.c @@ -28,6 +28,7 @@ struct _Shm_Handle size_t map_size; size_t image_size; int refcount; + int shmid; void *data; }; @@ -77,7 +78,7 @@ cserve2_shm_request(const char *infix, size_t size) do { snprintf(shmname, sizeof(shmname), "/evas-shm-%x-%s-%08x", - (int) getuid(), infix, id++); + (int) getuid(), infix, ++id); fd = shm_open(shmname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1 && errno != EEXIST) { @@ -110,6 +111,100 @@ cserve2_shm_request(const char *infix, size_t size) shm->image_size = size; shm->map_size = map_size; + shm->shmid = id; + + return shm; +} + +Shm_Handle * +cserve2_shm_segment_request(Shm_Handle *shm, size_t size) +{ + Shm_Handle *segment; + size_t map_size; + Shm_Mapping *map = shm->mapping; + int fd; + + segment = calloc(1, sizeof (Shm_Handle)); + if (!segment) return NULL; + + fd = shm_open(map->name, O_RDWR, S_IRUSR | S_IWUSR); + if (!fd) + { + ERR("Could not reopen shm handle: %m"); + free(segment); + return NULL; + } + + map_size = cserve2_shm_size_normalize(size); + map_size += map->length; + + if (ftruncate(fd, map_size) == -1) + { + ERR("Could not set the size of the shm: %m"); + close(fd); + free(segment); + return NULL; + } + close(fd); + + segment->mapping = map; + segment->map_offset = map->length; + segment->map_size = map_size - map->length; + segment->image_size = size; + segment->image_offset = segment->map_offset; + map->length = map_size; + map->segments = eina_inlist_append(map->segments, EINA_INLIST_GET(segment)); + + return segment; +} + +Shm_Handle * +cserve2_shm_resize(Shm_Handle *shm, size_t newsize) +{ + size_t map_size; + int fd; + + if (!shm) + return NULL; + + if (shm->map_offset || shm->image_offset) + { + CRIT("Can not resize shm with non-zero offset"); + return NULL; + } + + if (eina_inlist_count(shm->mapping->segments) > 1) + { + CRIT("Can not resize shm with more than one segment"); + return NULL; + } + + fd = shm_open(shm->mapping->name, O_RDWR, S_IRUSR | S_IWUSR); + if (!fd) + { + ERR("Could not reopen shm handle: %m"); + return NULL; + } + + map_size = cserve2_shm_size_normalize(newsize); + if (ftruncate(fd, map_size)) + { + ERR("Could not set the size of the shm: %m"); + close(fd); + return NULL; + } + + if (shm->data) + { + munmap(shm->data, shm->image_size); + shm->data = mmap(NULL, shm->image_size, PROT_WRITE, MAP_SHARED, + fd, shm->image_offset); + } + close(fd); + + shm->map_size = map_size; + shm->image_size = newsize; + shm->mapping->length = map_size; return shm; } @@ -139,6 +234,12 @@ cserve2_shm_name_get(const Shm_Handle *shm) return shm->mapping->name; } +int +cserve2_shm_id_get(const Shm_Handle *shm) +{ + return shm->shmid; +} + off_t cserve2_shm_map_offset_get(const Shm_Handle *shm) { @@ -220,6 +321,7 @@ _cserve2_shm_cleanup() else DBG("cserve2 cleanup: ignoring %s", f_info->path); } + eina_iterator_free(iter); } void