Unexpected Recursive Call

37 Views Asked by At

I am working on creating a cache access function in C and have ran into a strange issue with an unexpected recursive call. I may just be misunderstanding recursion in this case but I'm very confused as to why this is happening. This is my current function, mem_access provides read/write to my simulated memory. This is the function:

int cache_access(cache_t *c, addr_t addr, void *value, int size, int iswrite){
        int addr_offset = addr & ((1<<LOGBSIZE)-1); //all bits 0 - LOGBSIZE, anded with addr
        int addr_index = (addr>>(LOGBSIZE)) & ((1<<c->cache_s)-1); // addr >> LOGBSIZE (allows for index to be low order bits), then based on cache_s we extract that number of low order bits.
        int addr_tag = addr & ~((1<<(c->cache_s + LOGBSIZE))-1); //to get the tag we remove the low order bits and and with addr
        cacheset_t current_set = c->cache_sets[addr_index];

        int delay_total = 0;
        delay_total += c->cache_delay;
        for(int i = 0; i < c->cache_E; i++){
                //hit
                cacheline_t *line = &(current_set.lines[i]);
                if(addr_tag == line->tag && line->valid == 1){
                        if(iswrite){

                                memcpy(value, line->block, size);
                                line->dirty = 1;
                        }else{  
                                memcpy(line->block, value, size);
                        }

                        // update lru
                        update_LRU(&current_set, i, c->cache_E);
                        
                        return delay_total;
                //miss  
                }else{
                        //index 0 in useinfo
                        int evict_index = ((uint8_t *)current_set.useinfo)[0];
                        if(current_set.lines[evict_index].dirty != 0){
                                //concatenation of  tag and index
                                addr_t evict_addr = (current_set.lines[evict_index].tag) | (addr_index<<LOGBSIZE);
                                //write block to next lower level
                                if(c->cache_next == NULL){
                                        delay_total += mem_access(evict_addr, current_set.lines[evict_index].block + addr_offset, (1 << LOGBSIZE), 1);
                                }else{
                                        delay_total += cache_access(c->cache_next, evict_addr, current_set.lines[evict_index].block + addr_offset, (1<<LOGBSIZE), 1);
                                }
                                                }
                        //recursively check lower levels in cache, reading in from either cache or memory to the block
                        //(assumed) source of recursive error
                        if(c->cache_next == NULL){
                                delay_total += mem_access(addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);
                        }else{
                                delay_total+=cache_access(c->cache_next, addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);  
                        }
                        current_set.lines[evict_index].valid = 1;
                        current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
                        current_set.lines[evict_index].tag = addr_tag;

                        //update line with tag and set valid to 1
                        line[i].valid = 1;
                        line[i].tag = addr_tag;
                
                        update_LRU(&current_set, i, c->cache_E);
                        
                        return delay_total;     
                }
        }
}

When I run in GDB, this is what I am greeted with:

39         for(int i = 0; i < c->cache_E; i++){
(gdb) 
41                 cacheline_t *line = &(current_set.lines[i]);
(gdb) 
42                 if(addr_tag == line->tag && line->valid == 1){
(gdb) 
58                         int evict_index = ((uint8_t *)current_set.useinfo)[0];
(gdb) 
59                         if(current_set.lines[evict_index].dirty != 0){
(gdb) 
70                         if(c->cache_next == NULL){
(gdb) 
71                                 delay_total += mem_access(addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);
(gdb) 
75              current_set.lines[evict_index].valid = 1;
(gdb) x/16xb current_set.lines[evict_index].block
0x555555559c20: 0x00    0x01    0x02    0x03    0x04    0x05    0x06    0x07
0x555555559c28: 0x08    0x09    0x0a    0x0b    0x0c    0x0d    0x0e    0x0f
(gdb) n
76                         current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
(gdb) 
77                         current_set.lines[evict_index].tag = addr_tag;
(gdb) 
80                         line[i].valid = 1;
(gdb) 
81                         line[i].tag = addr_tag;
(gdb) 
83                         update_LRU(&current_set, i, c->cache_E);
(gdb) 
85              return delay_total; 
(gdb) 
88  }
(gdb) 
cache_access (c=0x55555555a580, addr=131072, value=0x7fffffffe324, size=1, iswrite=0) at cachesim.c:73
73                                 delay_total+=cache_access(c->cache_next,addr, value, size, 0);  
(gdb) x/16xb current_set.lines[evict_index].block
0x55555555a660: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x55555555a668: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
(gdb) n
75              current_set.lines[evict_index].valid = 1;
(gdb) n
76                         current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
(gdb) 
77                         current_set.lines[evict_index].tag = addr_tag;
(gdb) 
80                         line[i].valid = 1;
(gdb) 
81                         line[i].tag = addr_tag;
(gdb) 
83                         update_LRU(&current_set, i, c->cache_E);
(gdb) q

So my main question is why is this recursive call (using all parameters of the initial cache_access call) happening? It is causing the data in my block to be overwritten. Shouldn't it end after the return? Thanks for any help.

0

There are 0 best solutions below