diff memory.c @ 0:d4bc23cb728b

Import from CVS (CVS_DB/member/atsuki/cbc/DPP)
author Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp>
date Wed, 16 Dec 2015 15:16:11 +0900
parents
children 190dadd8405b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memory.c	Wed Dec 16 15:16:11 2015 +0900
@@ -0,0 +1,359 @@
+/*
+
+    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 */