summaryrefslogtreecommitdiffstats
path: root/TOOLS/cache2.c
blob: 0be7b44aa4a80159773673f88c69cd11c92fc697 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

// gcc cache2.c ../osdep/shmem.o -o cache2

// Initial draft of my new cache system...
// includes some simulation code, using usleep() to emulate limited bandwith
// TODO: seeking, data consistency checking

#define READ_SPEED 20
#define FILL_SPEED 10

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../osdep/shmem.h"

typedef struct {
  // constats:
  void *buffer;      // base pointer of the alllocated buffer memory
  int buffer_size;   // size of the alllocated buffer memory
  int sector_size;   // size of a single sector (2048/2324)
     // Note: buffer_size should be N*sector_size, where N is integer...
  int back_size;  // we should keep back_size amount of old bytes for backward seek
  int fill_limit; // we should fill buffer if space>fill_limit
  // reader's pointers:
  int read_filepos;
  // filler's pointers:
  int min_filepos; // buffer contain only a part of the file, from min-max pos
  int max_filepos;
  int offset;      // filepos <-> bufferpos  offset value (filepos of the buffer's first byte)
  // commands/locking:
  int cmd_lock;   // 1 if we will seek/reset buffer, 2 if we are ready for cmd
  int fifo_flag;  // 1 if we should use FIFO to notice cache about buffer reads.
} cache_vars_t;

int min_fill=0;
int sleep_flag=0;

void cache_stats(cache_vars_t* s){
  int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
  printf("0x%06X  [0x%06X]  0x%06X   ",s->min_filepos,s->read_filepos,s->max_filepos);
  printf("%3d %%  (%3d%%)\n",100*newb/s->buffer_size,100*min_fill/s->buffer_size);
}

int cache_read(cache_vars_t* s,int size){
  int total=0;
  while(size>0){
    int pos,newb,len;
    
    pos=s->read_filepos - s->offset;
    if(pos<0) pos+=s->buffer_size; else
    if(pos>=s->buffer_size) pos-=s->buffer_size;
    
    newb=s->max_filepos-s->read_filepos; // new bytes in the buffer

    if(newb<min_fill) min_fill=newb; // statistics...

    if(newb<=0){
	// waiting for buffer fill...
	usleep(10000); // 10ms
	continue;
    }
    
//    printf("*** newb: %d bytes ***\n",newb);
    
    if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap...
    if(newb>size) newb=size;
    
    // len=write(mem,newb)
    printf("Buffer read: %d bytes\n",newb);
    len=newb;usleep(len*READ_SPEED*sleep_flag);
    // ...
    
    s->read_filepos+=len;
    size-=len;
    total+=len;
    
  }
  return total;
}

int cache_fill(cache_vars_t* s){
  int read,back,newb,space,len,pos,endpos;
  
  read=s->read_filepos;
  
  // calc number of back-bytes:
  back=read - s->min_filepos;
  if(back<0) back=0; // strange...
  if(back>s->back_size) back=s->back_size;
  
  // calc number of new bytes:
  newb=s->max_filepos - read;
  if(newb<0) newb=0; // strange...

  // calc free buffer space:
  space=s->buffer_size - (newb+back);
  
  // calc bufferpos:
  pos=s->max_filepos - s->offset;
  if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around
  
  if(space<s->fill_limit){
//    printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit);
    return 0; // no fill...
  }

//  printf("### read=0x%X  back=%d  newb=%d  space=%d  pos=%d\n",read,back,newb,space,pos);
     
  // reduce space if needed:
  if(space>s->buffer_size-pos) space=s->buffer_size-pos;
  
  if(space>32768) space=32768; // limit one-time block size
  
  s->min_filepos=read-back; // avoid seeking-back to temp area...
  
  // ....
  printf("Buffer fill: %d bytes of %d\n",space,s->buffer_size);
  len=space; usleep(len*FILL_SPEED*sleep_flag);
  // ....
  
  s->max_filepos+=len;
  if(pos+len>=s->buffer_size){
      // wrap...
      s->offset+=s->buffer_size;
  }
  
  return len;
  
}

cache_vars_t* cache_init(int size,int sector){
  int num;
  cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t));
  memset(s,0,sizeof(cache_vars_t));
  num=size/sector;
  s->buffer_size=num*sector;
  s->sector_size=sector;
  s->buffer=shmem_alloc(s->buffer_size);
  s->fill_limit=8*sector;
  s->back_size=size/2;
  return s;
}

int main(){

  cache_vars_t* s=cache_init(1024*1024,2048);
  
//  while(cache_fill(s)){ }  // fill buffer:
  
  min_fill=s->buffer_size;
  sleep_flag=1; // start simulation
  
  if(fork()){
    while(1){
      if(!cache_fill(s)) usleep(10000); // wait 10ms for buffer space
      //cache_stats(s);
    }
  } else {
    srand(12345);
    while(1){
        int len=10+rand()&8191;
        cache_stats(s);
	cache_read(s,len);
    }
  }

}