#define DEBUG_LIST 1
#ifdef DEBUG_LIST
//TODO warning removal here
//https://www.tutorialspoint.com/data_structures_algorithms/hash_table_program_in_c.htm
#include<stdio.h>
#include<stdlib.h>
#include<sys/queue.h>
#define SIZE 20
struct DataItem {
int data;
int key;
};
struct DataItem* hashArray[SIZE];
struct DataItem* dummyItem;
struct DataItem* item;//todo optmize
int hashCode(int key) {
return key % SIZE;
}
//todo change name later for function
struct DataItem *search(int key) {
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] != NULL) {
if(hashArray[hashIndex]->key == key)
return hashArray[hashIndex];
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= SIZE;
}
return NULL;
}
void insert(int key,int data) {
struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem));
item->data = data;
item->key = key;
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty or deleted cell
while(hashArray[hashIndex] != NULL && hashArray[hashIndex]->key != -1) {
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= SIZE;
}
hashArray[hashIndex] = item;
}
struct DataItem* delete(struct DataItem* item) {
int key = item->key;
//get the hash
int hashIndex = hashCode(key);
//move in array until an empty
while(hashArray[hashIndex] != NULL) {
if(hashArray[hashIndex]->key == key) {
struct DataItem* temp = hashArray[hashIndex];
//assign a dummy item at deleted position
hashArray[hashIndex] = dummyItem;
return temp;
}
//go to next cell
++hashIndex;
//wrap around the table
hashIndex %= SIZE;
}
return NULL;
}
void display() {
int i = 0;
for(i = 0; i<SIZE; i++) {
if(hashArray[i] != NULL)
printf(" (%d,%d)",hashArray[i]->key,hashArray[i]->data);
else
printf(" ~~ ");
}
printf("\n");
}
/*-----------------------------above hashmap implementation ------------------------------*/
struct probe{
LIST_ENTRY(probe) list_ping ;
LIST_ENTRY(probe) list_pong ;
unsigned int addr_start ;
unsigned int addr_end ;
unsigned int page_addr ;
};
typedef LIST_HEAD(probe_head, probe) probe_head ;
struct mem_protect{
probe_head probe_ping;
probe_head probe_pong;
unsigned int active_probe ;
unsigned int page_addr_mask ;
unsigned int max_probe_cnt ;
unsigned int probe_cnt ;
};
enum cpu_t{
CortexA8,
other};
static struct mem_protect mem_protect ;
/*----------------------------- LOCAL FUNCTIONS ------------------------------*/
int mem_protect_probe_init(unsigned int cpu)//CortexA8
{
int ret = -1 ;
do{
LIST_INIT( &(mem_protect.probe_ping) ) ;
LIST_INIT( &(mem_protect.probe_pong) ) ;
mem_protect.active_probe = 0 ;
if(cpu != CortexA8)
break ;
/* 1MB
*/
mem_protect.page_addr_mask = 0xFFF00000;
mem_protect.max_probe_cnt = 5 ;
mem_protect.probe_cnt = 0 ;
ret = 0 ;
}while(0) ;
return ret ;
}
int mem_protect_list_probes()
{
int ret = -1;
do{
probe_head * active_head = NULL, *inactive_head = NULL ;
if(mem_protect.active_probe){
active_head = &(mem_protect.probe_pong) ;
inactive_head = &(mem_protect.probe_ping) ;
}else{
active_head = &(mem_protect.probe_ping) ;
inactive_head = &(mem_protect.probe_pong) ;
}
struct probe *pitter = NULL ;//TODO KW check
printf("List all the probe info: totally %d probes\r\n",mem_protect.probe_cnt);
//now ping == pong ,without mem_protect.active_probe ==1 precondition
LIST_FOREACH(pitter, inactive_head, list_ping){
printf("inactive_list: list foreach (address start | address end | page):%x\t%x\t%x\r\n",pitter->addr_start, pitter->addr_end,pitter->page_addr);
//last_probe=pitter ;
//if( pitter->addr_start >= addr )
//break ;
}
LIST_FOREACH(pitter, active_head, list_pong){
printf("Active_list: list foreach (address start || address end || page):%x\t%x\t%x\r\n",pitter->addr_start, pitter->addr_end,pitter->page_addr);
}
ret = 0;
}while(0) ;
return ret;
}
//TODO replace printf by atdebug(0,
#define ERROR_DEL_NULLLIST (-1)
#define ERROR_DEL_NOTFOUND (-2)
int mem_protect_del_probe(unsigned int addr)
{
int ret = ERROR_DEL_NULLLIST;
do
{
if(0==mem_protect.probe_cnt)
{
ret = ERROR_DEL_NULLLIST;
break;
}
probe_head * active_head = NULL , *inactive_head = NULL ;
if(mem_protect.active_probe){
active_head = &(mem_protect.probe_pong) ;
inactive_head = &(mem_protect.probe_ping) ;
}else{
active_head = &(mem_protect.probe_ping) ;
inactive_head = &(mem_protect.probe_pong) ;
}
struct probe *last_probe= NULL, *pitter ;
LIST_FOREACH(pitter, inactive_head, list_ping){
if( pitter->addr_start == addr )
{
last_probe=pitter ;
break ;
}
}
if(last_probe == NULL)
{
ret = ERROR_DEL_NOTFOUND;
break;
}
//TODO add page property recover here
struct DataItem* DataItemTarget = search(addr&0x100000);
if(DataItemTarget == NULL)
{
printf("invalid addr to delete \n");
ret = -1;
}
else if (DataItemTarget->data == 1)
{
if (!delete(DataItemTarget)) //if not null ,it delete ok
{
ret = 0;
}
ret = -2;
}
else
{
(DataItemTarget->data)--;
ret = 0;
}
if(mem_protect.active_probe){
LIST_REMOVE(last_probe,list_ping);
mem_protect.active_probe = 0 ;
LIST_REMOVE(last_probe,list_pong);
}
else
{
LIST_REMOVE(last_probe,list_pong);
mem_protect.active_probe = 1 ;
LIST_REMOVE(last_probe,list_ping);
}
mem_protect.probe_cnt-- ;
}while(0) ;
return ret;
}
int mem_protect_add_probe(unsigned int addr, unsigned int len)
{
int ret = -1 ;
//mutex->lock
do{
if(mem_protect.probe_cnt >= mem_protect.max_probe_cnt)
{
break ;
}
if(len > ~(mem_protect.page_addr_mask) )
{
break ;
}
/*TODO: cross different page
*/
struct probe* probe = malloc( sizeof(*probe) ) ;
if(NULL == probe)
{
break ;
}
memset(probe, 0, sizeof(*probe) ) ;
probe->addr_start = addr ;
probe->addr_end = addr+len ;
probe->page_addr = addr & mem_protect.page_addr_mask ;
probe_head * active_head, *inactive_head ;
if(mem_protect.active_probe){
active_head = &(mem_protect.probe_pong) ;
inactive_head = &(mem_protect.probe_ping) ;
}else{
active_head = &(mem_protect.probe_ping) ;
inactive_head = &(mem_protect.probe_pong) ;
}
struct probe *last_probe = NULL , *pitter = NULL ;
LIST_FOREACH(pitter, inactive_head, list_ping){
last_probe=pitter ;
if( pitter->addr_start >= addr )
{
break ;
}
}
if(mem_protect.active_probe){
if(last_probe)
{
LIST_INSERT_AFTER(last_probe, probe, list_ping) ;
}
else
{
LIST_INSERT_HEAD(inactive_head, probe, list_ping) ;
}
mem_protect.active_probe = 0 ;
if(last_probe)
{
LIST_INSERT_AFTER(last_probe, probe, list_pong) ;
}
else
{
LIST_INSERT_HEAD(active_head, probe, list_pong) ;
}
}else{
if(last_probe)
{
LIST_INSERT_AFTER(last_probe, probe, list_pong) ;
}
else
{
LIST_INSERT_HEAD(inactive_head, probe, list_pong) ;
}
mem_protect.active_probe = 1 ;
if(last_probe)
{
LIST_INSERT_AFTER(last_probe, probe, list_ping) ;
}
else
{
LIST_INSERT_HEAD(active_head, probe, list_ping) ;
}
}
TODO enable
//mmu_set_access_permission(addr, len) ;
struct DataItem* DataItemTarget = search(addr&0x100000);
if(DataItemTarget == NULL)
{
insert(addr&0x100000,1);
}
else
{
(DataItemTarget->data)++; //key data
}
mem_protect.probe_cnt++ ;
if(1==mem_protect.probe_cnt){
//TODO enable
//setup_memprotect_exception_handler() ;
}
ret = 0 ;
}while(0) ;
//mutex->unlock
return ret ;
}
int main(void){
dummyItem = (struct DataItem*) malloc(sizeof(struct DataItem));//for delete use ,never delete it
dummyItem->data = -1;
dummyItem->key = -1;
//later move it into mem_protect_probe_init
int ret1 = mem_protect_probe_init(CortexA8);//CortexA8
int ret2 = mem_protect_add_probe(0x8f000000,4);
ret2 = mem_protect_add_probe(0x8f000010,4);
ret2 = mem_protect_add_probe(0x8f000020,4);
ret2 = mem_protect_add_probe(0x8f000030,4);
ret2 = mem_protect_add_probe(0x8f000040,4);
//printlist
int ret0 = mem_protect_list_probes();
//delete list
int ret3 = 0;
ret3 = mem_protect_del_probe(0x8f000040);
ret3 =mem_protect_del_probe(0x8f000030);
ret3 =mem_protect_del_probe(0x8f000020);
ret3 =mem_protect_del_probe(0x8f000010);
ret3 =mem_protect_del_probe(0x8f000000);
ret0 = mem_protect_list_probes();
printf("del null list item%d \r\n",mem_protect_del_probe(0x8f000040));
#if 0
ret2 = mem_protect_add_probe(0x8f000010,4);
ret2 = mem_protect_add_probe(0x8f000020,4);
printf("del invalid item %d \r\n",mem_protect_del_probe(0x8f000048));
ret0 = mem_protect_list_probes();
#endif
return 0;
}
#endif