Mercurial > hg > CbC > old > DPP
view memory.c @ 12:7f2db1e1bf2f default tip
use CBC_COMPILER environment val
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 04 Jul 2019 18:53:38 +0900 |
parents | 190dadd8405b |
children |
line wrap: on
line source
/* memory fragment management library Shinji Kono (2006) usage: MemoryPtr db = 0; add_memory(address,length,&db); memory pattern is copyied and stored in a binary tree in db. All patterns are shared. memory pattern database (binary tree by pattern) */ #include <stdio.h> #include <stdlib.h> #include "memory.h" #include "crc32.h" #include <string.h> #define MEMORY_REPORT 1 #if MEMORY_REPORT int memory_header; int memcmp_count; int memory_body; int restore_count; int restore_size; int range_count; int range_size; #endif extern void die_exit(char *); void die_exit(char *msg) { fprintf(stderr,"%s\n",msg); exit(1); } // static MemoryPtr memory_root; /* make memory fragment as a part of the program state */ MemoryPtr create_memory(void *adr, int length) { MemoryPtr m = (MemoryPtr)malloc(sizeof(Memory)); if (!m) die_exit("Cann't alloc memory list."); m->left = m->right = 0; m->length = length; m->adr = m->body = adr; #if MEMORY_REPORT memory_header++; #endif return m; } /* Compute hash value of a memory fragment */ void compute_memory_hash1(MemoryPtr m) { m->hash = Get_CRC((unsigned char *)m->adr,m->length); } void free_memory(MemoryPtr m) { m->left = m->right = 0; m->adr = m->body = 0; free(m); } /* Compare memory contents ( doesn't care about its address ) */ int cmp_content(MemoryPtr a,MemoryPtr b) { if (a->length != b->length) { if (a->length > b->length) { return 1; } else { return -1; } } if (a->hash == b->hash) { #if MEMORY_REPORT memcmp_count ++; #endif return memcmp(a->body,b->body,a->length); } else if (a->hash > b->hash) { return 1; } else { return -1; } } /* Compare entire memory contents ( doesn't care about its address ) */ static int cmp_memory1(MemoryPtr a,MemoryPtr b) { int r; if ((r=cmp_content(a,b))) return r; if (a->adr==b->adr) { return 0; } return (a->adr > b->adr) ? 1 : -1; } int cmp_memory(MemoryPtr a,MemoryPtr b) { int r; while(1) { if ((r=cmp_memory1(a,b))) return r; if (a->left && b->left) { if ((r=cmp_memory(a->left,b->left))) return r; } else if (a->left || b->left) { return (a->left > b->left)? 1 : -1; } if (a->right && b->right) { a = a->right; b = b->right; // recursive loop } else if (a->right || b->right) { return (a->right > b->right)? 1 : -1; } else { return 0; // singleton } } } /* Make a copy of real memory fragments */ MemoryPtr copy_memory1(MemoryPtr m) { MemoryPtr new = create_memory(m->adr,m->length); void *p = (void *)malloc(m->length); if (!p) { die_exit("can't alloc memory body"); return 0; } #if MEMORY_REPORT memory_body += m->length; #endif memcpy(p,m->adr,m->length); m->body = new->body = p; // abondon original memory pattern new->hash = m->hash; return new; } MemoryPtr copy_memory(MemoryPtr m, MemoryPtr *db) { MemoryPtr new, out; if (!m) return m; new = create_memory(m->adr,m->length); new->hash = m->hash; // look up is necessary to share its memory pattern memory_lookup(new, db, copy_memory1, &out); if (m->left) new->left = copy_memory(m->left, db); if (m->right) new->right = copy_memory(m->right, db); return new; } /* restore copied memory save to the original addresses */ void restore_memory(MemoryPtr m) { while (m) { memcpy(m->adr,m->body,m->length); #if MEMORY_REPORT restore_count ++; restore_size += m->length; #endif if (m->left) restore_memory(m->left); m = m->right; } } /* get hash for all memeory fragments initial value of hash should be zero */ int get_memory_hash(MemoryPtr m, int hash) { if (!m) return hash; compute_memory_hash1(m); if (m->left) hash = get_memory_hash(m->left, hash); if (m->right) return get_memory_hash(m->right, hash); return m->hash | hash; } /* add modified memory fragments to the pattern database */ MemoryPtr add_memory(void *ptr,int length, MemoryPtr *parent) { Memory m, *out; m.adr = m.body = ptr; m.length = length; m.left = m.right = 0; compute_memory_hash1(&m); memory_lookup(&m, parent, copy_memory1, &out); return out; } int memory_lookup(MemoryPtr m, MemoryPtr *parent, MemoryPtr (*new_memory)(MemoryPtr), MemoryPtr *out) { MemoryPtr db; int r; while(1) { db = *parent; if (!db) { /* not found */ if (new_memory && out) { db = new_memory(m); db->left = db->right = 0; *out = *parent = db; } return 0; } if(!(r = cmp_memory1(m,db))) { /* bingo */ if (out) { *out = db; } return 1; } else if (r>0) { parent = &db->left; } else if (r<0) { parent = &db->right; } } /* !NOT REACHED */ } /* memory range list management for state registration this list points the real memory */ MemoryPtr add_memory_range(void *ptr,int length, MemoryPtr *parent) { Memory m, *out; m.adr = ptr; m.length = length; m.left = m.right = 0; memory_range_lookup(&m, parent, &out); return out; } static int cmp_range(MemoryPtr a,MemoryPtr b) { if (a->adr==b->adr) { if (a->length != b->length) die_exit("memory range inconsitency"); return 0; } return (a->adr > b->adr) ? 1 : -1; } int memory_range_lookup(MemoryPtr m, MemoryPtr *parent, MemoryPtr *out) { MemoryPtr db; int r; while(1) { db = *parent; if (!db) { /* not found */ if (out) { db = create_memory(m->adr, m->length); *out = *parent = db; } #if MEMORY_REPORT range_count++; range_size+=m->length; #endif return 0; } if(!(r = cmp_range(m,db))) { /* bingo (actually an error) */ if (out) { *out = db; } return 1; } else if (r>0) { parent = &db->left; } else if (r<0) { parent = &db->right; } } /* !NOT REACHED */ } /* */ void memory_usage() { #if MEMORY_REPORT printf(" memory_header %d\n",memory_header); printf(" memcmp_count %d\n",memcmp_count); printf(" memory_body %d\n",memory_body); printf(" restore_count %d\n",restore_count); printf(" restore_size %d\n",restore_size); printf(" range_count %d\n",range_count); printf(" range_size %d\n",range_size); #endif } /* end */