Start on scrollback compression code (grid_save).
Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
parent
11ffa432eb
commit
287d80370e
|
@ -0,0 +1,340 @@
|
|||
#include "private.h"
|
||||
#include "grid_save.h"
|
||||
#include "grid.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if defined (__MacOSX__) || (defined (__MACH__) && defined (__APPLE__))
|
||||
# ifndef MAP_ANONYMOUS
|
||||
# define MAP_ANONYMOUS MAP_ANON
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MEM_ALLOC_ALIGN 16
|
||||
#define MEM_BLOCKS 1024
|
||||
|
||||
#define GS_MMAP_SIZE 131072
|
||||
#define GS_ALLOC_MASK (TS_MMAP_SIZE - 1)
|
||||
|
||||
typedef struct _Alloc Alloc;
|
||||
|
||||
struct _Alloc
|
||||
{
|
||||
unsigned int size, last, count, allocated;
|
||||
short slot;
|
||||
unsigned char gen;
|
||||
unsigned char __pad;
|
||||
};
|
||||
|
||||
/* local variables */
|
||||
static int freeze = 0;
|
||||
static int comp = 0;
|
||||
static int uncomp = 0;
|
||||
static int freeops = 0;
|
||||
static int compfreeze = 0;
|
||||
static unsigned char cur_gen = 0;
|
||||
static Ecore_Idler *_save_idler = NULL;
|
||||
static Ecore_Timer *_save_timer = NULL;
|
||||
static Eina_List *_grids = NULL;
|
||||
static uint64_t _allocated = 0;
|
||||
|
||||
static int
|
||||
_alloc_roundup_block_size(int sz)
|
||||
{
|
||||
return MEM_ALLOC_ALIGN * ((sz + MEM_ALLOC_ALIGN - 1) / MEM_ALLOC_ALIGN);
|
||||
}
|
||||
|
||||
static Alloc *
|
||||
_alloc_find(void *mem)
|
||||
{
|
||||
unsigned char *memptr;
|
||||
int i;
|
||||
|
||||
memptr = mem;
|
||||
for (i = 0; i < MEM_BLOCKS; i++)
|
||||
{
|
||||
unsigned char *al;
|
||||
|
||||
al = (unsigned char *)alloc[i];
|
||||
if (!al) continue;
|
||||
if (memptr < al) continue;
|
||||
if ((al + GS_MMAP_SIZE) <= memptr) continue;
|
||||
return alloc[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
_alloc_new(int size, unsigned char gen)
|
||||
{
|
||||
Alloc *al;
|
||||
unsigned char *ptr;
|
||||
unsigned int newsize, sz;
|
||||
int i, firstnull = -1;
|
||||
|
||||
// allocations sized up to nearest size alloc alignment
|
||||
newsize = _alloc_roundup_block_size(size);
|
||||
for (i = 0; i < MEM_BLOCKS; i++)
|
||||
{
|
||||
if (!alloc[i])
|
||||
{
|
||||
if (firstnull < 0) firstnull = i;
|
||||
continue;
|
||||
}
|
||||
// if generation count matches
|
||||
if (alloc[i]->gen == gen)
|
||||
{
|
||||
// if there is space in the block
|
||||
if ((alloc[i]->size - alloc[i]->last) >= newsize)
|
||||
{
|
||||
ptr = (unsigned char *)alloc[i];
|
||||
ptr += alloc[i]->last;
|
||||
alloc[i]->last += newsize;
|
||||
alloc[i]->count++;
|
||||
alloc[i]->allocated += newsize;
|
||||
_allocated += newsize;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// out of slots for new blocks - no null blocks
|
||||
if (firstnull < 0)
|
||||
{
|
||||
ERR("Cannot find new null blocks");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// so allocate a new block
|
||||
sz = GS_MMAP_SIZE;
|
||||
// get mmaped anonymous memory so when freed it goes away from the system
|
||||
ptr = mmap(NULL, sz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
ERR("Cannot allocate more memory with mmap MAP_ANONYMOUS");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// note - we SHOULD memset to 0, but we are assuming mmap anon give 0 pages
|
||||
//memset(ptr, 0, newsize);
|
||||
|
||||
al = (Alloc *)ptr;
|
||||
al->size = sz;
|
||||
al->last = sizeof(Alloc) + newsize;
|
||||
al->count = 1;
|
||||
al->allocated = newsize;
|
||||
al->slot = firstnull;
|
||||
al->gen = gen;
|
||||
_allocated += newsize;
|
||||
alloc[al->slot] = al;
|
||||
ptr = (unsigned char *)al;
|
||||
ptr += sizeof(Alloc);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *
|
||||
_grid_save_new(int size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (!size) return NULL;
|
||||
ptr = _alloc_new(size, cur_gen);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
_grid_save_free(void *ptr)
|
||||
{
|
||||
Alloc *al;
|
||||
unsigned int sz;
|
||||
Grid_Save_Comp *gs;
|
||||
|
||||
if (!ptr) return;
|
||||
|
||||
gs = ptr;
|
||||
if (gs->comp)
|
||||
sz = sizeof(Grid_Save_Comp) + gs->w;
|
||||
else
|
||||
sz = sizeof(Grid_Save) + ((gs->w - 1) * sizeof(Grid_Cell));
|
||||
sz = roundup_block_size(sz);
|
||||
_allocated -= sz;
|
||||
|
||||
al = _alloc_find(ptr);
|
||||
if (!al)
|
||||
{
|
||||
ERR("Cannot find %p in alloc blocks", ptr);
|
||||
return;
|
||||
}
|
||||
al->count--;
|
||||
al->allocated -= sz;
|
||||
if (al->count > 0) return;
|
||||
alloc[al->slot] = NULL;
|
||||
munmap(al, al->size);
|
||||
}
|
||||
|
||||
static void
|
||||
_mem_gen_next(void)
|
||||
{
|
||||
cur_gen++;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
_mem_gen_get(void)
|
||||
{
|
||||
return cur_gen;
|
||||
}
|
||||
|
||||
static void
|
||||
_mem_defrag(void)
|
||||
{
|
||||
int i, j = 0;
|
||||
Alloc *alloc2[MEM_BLOCKS];
|
||||
|
||||
for (i = 0; i < MEM_BLOCKS; i++)
|
||||
{
|
||||
if (alloc[i])
|
||||
{
|
||||
alloc2[j] = alloc[i];
|
||||
alloc2[j]->slot = j;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: quicksort blocks with most space at start
|
||||
for (i = 0; i < j; i++) alloc[i] = alloc2[i];
|
||||
for (; i < MEM_BLOCKS; i++) alloc[i] = NULL;
|
||||
}
|
||||
|
||||
static Grid_Save *
|
||||
_grid_save_comp(Grid_Save *gs)
|
||||
{
|
||||
/* Grid_Save *gs2; */
|
||||
/* Grid_Save_Comp *gsc; */
|
||||
|
||||
if (gs->comp) return gs;
|
||||
|
||||
compfreeze++;
|
||||
if (!gs->z)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_grid_walk(Evas_Object *obj)
|
||||
{
|
||||
Grid *sd;
|
||||
int i = 0;
|
||||
|
||||
if (!(sd = evas_object_smart_data_get(obj))) return;
|
||||
|
||||
if (!sd->back) return;
|
||||
for (; i < sd->backmax; i++)
|
||||
{
|
||||
Grid_Save_Comp *gsc;
|
||||
|
||||
if ((gsc = (Grid_Save_Comp *)sd->back[i]))
|
||||
{
|
||||
if (!(sd->back[i] = _grid_save_comp(sd->back[i])))
|
||||
continue;
|
||||
|
||||
gsc = (Grid_Save_Comp *)sd->back[i];
|
||||
if (gsc->comp) comp++;
|
||||
else uncomp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_cb_save_idler(void *data EINA_UNUSED)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_Object *obj;
|
||||
|
||||
_mem_gen_next();
|
||||
|
||||
comp = 0;
|
||||
uncomp = 0;
|
||||
|
||||
EINA_LIST_FOREACH(_grids, l, obj)
|
||||
_grid_walk(obj);
|
||||
|
||||
_mem_defrag();
|
||||
|
||||
freeops = 0;
|
||||
|
||||
_mem_gen_next();
|
||||
|
||||
_save_idler = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_cb_save_timer(void *data EINA_UNUSED)
|
||||
{
|
||||
if (!_save_idler)
|
||||
_save_idler = ecore_idler_add(_cb_save_idler, NULL);
|
||||
_save_timer = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_grid_save_compressor_check(Eina_Bool frozen)
|
||||
{
|
||||
if (freeze) return;
|
||||
if (_save_idler) return;
|
||||
|
||||
if ((uncomp > 256) || (freeops > 256))
|
||||
{
|
||||
if ((_save_timer) && (!frozen))
|
||||
ecore_timer_reset(_save_timer);
|
||||
else if (!_save_timer)
|
||||
_save_timer = ecore_timer_add(0.2, _cb_save_timer, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_grid_save_register(Evas_Object *obj)
|
||||
{
|
||||
_grid_save_freeze();
|
||||
_grids = eina_list_append(_grids, obj);
|
||||
_grid_save_thaw();
|
||||
}
|
||||
|
||||
void
|
||||
_grid_save_unregister(Evas_Object *obj)
|
||||
{
|
||||
_grid_save_freeze();
|
||||
_grids = eina_list_remove(_grids, obj);
|
||||
_grid_save_thaw();
|
||||
}
|
||||
|
||||
void
|
||||
_grid_save_freeze(void)
|
||||
{
|
||||
if (!freeze++)
|
||||
{
|
||||
if (_save_timer) ecore_timer_freeze(_save_timer);
|
||||
}
|
||||
|
||||
if (_save_idler) ecore_idler_del(_save_idler);
|
||||
_save_idler = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_grid_save_thaw(void)
|
||||
{
|
||||
freeze--;
|
||||
if (freeze <= 0)
|
||||
{
|
||||
if (_save_timer) ecore_timer_thaw(_save_timer);
|
||||
_grid_save_compressor_check(EINA_TRUE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _GRID_SAVE_H
|
||||
# define _GRID_SAVE_H 1
|
||||
|
||||
void _grid_save_register(Evas_Object *obj);
|
||||
void _grid_save_unregister(Evas_Object *obj);
|
||||
void _grid_save_freeze(void);
|
||||
void _grid_save_thaw(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue