Start on scrollback compression code (grid_save).

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2014-12-03 15:39:04 -05:00
parent 11ffa432eb
commit 287d80370e
2 changed files with 349 additions and 0 deletions

340
src/bin/grid_save.c Normal file
View File

@ -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);
}
}

9
src/bin/grid_save.h Normal file
View File

@ -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