*/
#define EINA_SMALL_PAGE eina_cpu_page_size()
-#define EINA_HUGE_PAGE 16 * 1024 * 1024
+
+// FIXME: This assumes HugeTLB size of 2Mb. How to get this information at runtime?
+#define EINA_HUGE_PAGE (2 * 1024 * 1024)
+#define EINA_HUGE_PAGE_MIN (8 * EINA_HUGE_PAGE)
#ifdef HAVE_DIRENT_H
typedef struct _Eina_File_Iterator Eina_File_Iterator;
}
#endif
+static char *
+_page_aligned_address(const char *map, unsigned long int offset, Eina_Bool hugetlb)
+{
+ const uintptr_t align = hugetlb ? EINA_HUGE_PAGE : EINA_SMALL_PAGE;
+ uintptr_t pmap = (uintptr_t) map;
+
+ pmap = (pmap + offset) - ((pmap + offset) & (align - 1));
+
+ return (char *) pmap;
+}
+
static int
-_eina_file_map_rule_apply(Eina_File_Populate rule, void *addr, unsigned long int size, Eina_Bool hugetlb)
+_eina_file_map_rule_apply(Eina_File_Populate rule, const void *map, unsigned long int offset,
+ unsigned long int size, unsigned long long maplen, Eina_Bool hugetlb)
{
int tmp = 42;
int flag = MADV_RANDOM;
+ char *addr;
switch (rule)
{
default: return tmp; break;
}
+ if (offset >= maplen) return tmp;
+
+ // Align address, clamp size
+ addr = _page_aligned_address(map, offset, hugetlb);
+ if (size > 0)
+ {
+ size += ((char *) map + offset) - addr;
+ offset -= ((char *) map + offset) - addr;
+ if ((offset + size) > maplen)
+ {
+ if (offset > maplen) return tmp;
+ size = maplen - offset;
+ }
+ }
+
madvise(addr, size, flag);
#ifndef MAP_POPULATE
if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
#endif
#ifdef MAP_HUGETLB
- if (file->length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB;
+ if (file->length >= EINA_HUGE_PAGE_MIN) flags |= MAP_HUGETLB;
#endif
eina_mmap_safety_enabled_set(EINA_TRUE);
else
hugetlb = file->global_hugetlb;
- _eina_file_map_rule_apply(rule, file->global_map, file->length, hugetlb);
+ _eina_file_map_rule_apply(rule, file->global_map, 0, file->length, file->length, hugetlb);
file->global_refcount++;
ret = file->global_map;
}
if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
#endif
#ifdef MAP_HUGETLB
- if (length > EINA_HUGE_PAGE) flags |= MAP_HUGETLB;
+ if (length >= EINA_HUGE_PAGE_MIN) flags |= MAP_HUGETLB;
#endif
map = malloc(sizeof (Eina_File_Map));
map->refcount++;
- _eina_file_map_rule_apply(rule, map->map, length, map->hugetlb);
+ _eina_file_map_rule_apply(rule, map->map, 0, length, map->length, map->hugetlb);
eina_lock_release(&file->lock);
eina_file_map_populate(Eina_File *file, Eina_File_Populate rule, const void *map,
unsigned long int offset, unsigned long int length)
{
+ Eina_File_Map *em;
+
EINA_SAFETY_ON_NULL_RETURN(file);
eina_lock_take(&file->lock);
if (map == file->global_map)
- {
- _eina_file_map_rule_apply(rule, ((char*) map) + offset, length,
- file->global_hugetlb);
- }
- else
- {
- Eina_File_Map *em;
-
- em = eina_hash_find(file->rmap, &map);
- if (em) _eina_file_map_rule_apply(rule, ((char *) em->map) + offset,
- length, em->hugetlb);
- }
+ _eina_file_map_rule_apply(rule, map, offset, length, file->length, file->global_hugetlb);
+ else if ((em = eina_hash_find(file->rmap, &map)) != NULL)
+ _eina_file_map_rule_apply(rule, map, offset, length, em->length, em->hugetlb);
eina_lock_release(&file->lock);
}
file_map = eina_file_map_new(e_file, EINA_FILE_WILLNEED, map_offset, map_length);
fail_if(!file_map);
correct_map_check= strcmp((char*) file_map, eina_map_test_string);
- fail_if(correct_map_check != 0);
-
- eina_file_map_free(e_file, file_map);
+ fail_if(correct_map_check != 0);
// test : offset = memory_page_size AND length = file->length - memory_page_size => correct partly map
map_offset = memory_page_size;
correct_map_check = strcmp((char*)file2_map, big_buffer + memory_page_size);
fail_if(correct_map_check != 0);
+ // test no crash with eina_file_map_populate()
+ eina_file_map_populate(e_file, EINA_FILE_POPULATE, file_map, 0, 0);
+ eina_file_map_populate(e_file, EINA_FILE_POPULATE, file_map, file_length / 2, 0);
+ eina_file_map_populate(e_file, EINA_FILE_POPULATE, file_map, 0, file_length * 2);
+ eina_file_map_populate(e_file, EINA_FILE_POPULATE, file_map, file_length / 2, big_buffer_size);
+ eina_file_map_populate(e_file, EINA_FILE_POPULATE, file_map, big_buffer_size + 1, file_length);
+
eina_file_map_free(e_file, file_map);
+ eina_file_map_free(e_file, file_map); // test no crash
eina_file_map_free(e_file2, file2_map);
eina_file_close(e_file);
eina_file_close(e_file2);