1 /* CACHE.H    (c)Copyright Greg Smith, 2002-2009                     */
2 /*            Buffer Cache Manager                                   */
3 
4 /*-------------------------------------------------------------------
5   Description:
6     Manages multiple caches in a multi-threaded environment.  A cache
7     is dynamically created and destroyed.  It's size or number of
8     entries is also dynamically determined.  A cache entry contains
9     an identifying `key', `flags' which indicate whether an entry is
10     busy or not, and a `buf' which is a pointer to the cached object.
11 
12   Cache entry:
13     The structure of a cache entry is:
14       U64       key;
15       U32       flag;
16       int       len;
17       void     *buf;
18       int       value;
19       U64       age;
20     The first 8 bits of the flag indicates if the entry is `busy' or
21     not.  If any of the first 8 bits are non-zero then the entry is
22     considered `busy' and will not be stolen or otherwise reused.
23 
24   APIs:
25 
26     General query functions:
27       int         cache_nbr(int ix); [0]
28                   Number of entries
29 
30       int         cache_busy(int ix);
31                   Number of busy entries
32 
33       int         cache_empty(int ix);
34                   Number of empty entries [1]
35 
36       int         cache_waiters(int ix);
37                   Number of waiters for a non-busy cache entry
38 
39       long long   cache_size(int ix);
40                   Size of all allocated objects
41 
42       long long   cache_hits(int ix);
43                   Number of successful lookups
44 
45       long long   cache_misses(int ix);
46                   Number of unsuccessful lookups
47 
48       int         cache_busy_percent(int ix);
49                   Percentage (0 .. 100) of entries that are busy
50 
51       int         cache_empty_percent(int ix);
52                   Percentage of entries that are empty [1]
53 
54       int         cache_hit_percent(int ix);
55                   Percentage of successful lookups to total lookups
56 
57      Notes        [0] `ix' identifies the cache.  This is an integer
58                       and is reserved in `cache.h'
59                   [1] An empty entry contains a zero key value.
60                       A valid key should not be all zeroes
61                       (0x0000000000000000) or all ones
62                       (0xffffffffffffffff).   All ones is used to
63                       indicate an error circumstance.
64 
65     Entry specific functions:
66       U64         cache_getkey(int ix, int i); [0]
67                   Return key for the specified cache entry
68 
69       U64         cache_setkey(int ix, int i, U64 key);
70                   Set the key for the specified cache entry;
71                   the old key is returned
72 
73       U32         cache_getflag(int ix, int i);
74                   Return the flag for the specified cache entry
75 
76       U32         cache_setflag(int ix, int i, U32 andbits, U32 orbits);
77                   Set the flag for the specified cache entry; first
78                   the `andbits' value is `and'ed against the entry then
79                   the `orbits' value is `or'ed against the entry.  The
80                   old flag is returned.
81 
82       U64         cache_getage(int ix, int i); [1]
83                   Return age for the specified cache entry
84 
85       U64         cache_setage(int ix, int i);
86                   Set age for the specified cache entry
87 
88       void       *cache_getbuf(int ix, int i, int len);
89                   Return address of the object buf for the cache entry.
90                   If `len' is non-zero, then if the current object
91                   is null or `len' is greater than the current object
92                   length then the old object is freed and a new
93                   object is obtained.
94 
95       void       *cache_setbuf(int ix, int i, void *buf, int len);
96                   The old object address and length is replaced.
97                   The address of the old object is returned and
98                   can be freed using `free()'.
99 
100       int         cache_getlen(int ix, int i);
101                   Return the length of the current object
102 
103        Notes      [0] `i' is the index of the entry in cache `ix'
104                   [1] `age' is a sequentially incremented value and
105                       does not correspond to date or time
106 
107     Locking functions:
108       int         cache_lock(int ix);
109                   Obtain the lock for cache `ix'.  If the cache does
110                   not exist then it will be created.  Generally, the
111                   lock should be obtained when referencing cache
112                   entries and must be held when a cache entry status
113                   may change from `busy' to `not busy' or vice versa.
114                   Likewise, the lock must be held when a cache entry
115                   changes from `empty' to `not empty' or vice versa.
116 
117       int         cache_unlock(int ix);
118                   Release the cache lock
119 
120     Search functions:
121       int         cache_lookup(int ix, U64 key, int *o);
122                   Search cache `ix' for entry matching `key'.
123                   If a non-NULL pointer `o' is provided, then the
124                   oldest or preferred cache entry index is returned
125                   that is available to be stolen.
126 
127       int         cache_scan (int ix, int (rtn)(), void *data);
128                   Scan a cache routine entry by entry calling routine
129                   `rtn'.  Parameters passed to the routine are
130                   `(int *answer, int ix, int i, void *data)'  where
131                   `ix' is the cache index, `i' is the cache entry
132                   index and `data' is the value passed to cache_scan.
133                   `*answer' is initialized to -1 and can be set by
134                   the scan subroutine.  This will be the value returned
135                   by cache_scan.  If the routine returns a non-zero
136                   value then the scan is terminated.
137 
138     Other functions:
139       int         cache_wait(int ix);
140                   Wait for a non-busy cache entry to become available.
141                   Typically called after `cache_lookup' was
142                   unsuccessful and `*o' is -1.
143 
144       int         cache_release(int ix, int i, int flag);
145                   Release the cache entry.  If flag is CACHE_FREEBUF
146                   then the object buffer is also freed.
147 
148       int         cache_cmd(int argc, char *argv[], char *cmdline);
149                   Interface with the cache command processor.  This
150                   interface is subject to change.
151 
152   -------------------------------------------------------------------*/
153 
154 #ifndef _HERCULES_CACHE_H
155 #define _HERCULES_CACHE_H 1
156 
157 #include "hercules.h"
158 
159 
160 #ifndef _CACHE_C_
161 #ifndef _HDASD_DLL_
162 #define CCH_DLL_IMPORT DLL_IMPORT
163 #else   /* _HDASD_DLL_ */
164 #define CCH_DLL_IMPORT extern
165 #endif  /* _HDASD_DLL_ */
166 #else
167 #define CCH_DLL_IMPORT DLL_EXPORT
168 #endif
169 
170 /*-------------------------------------------------------------------*/
171 /* Reserve cache indexes here                                        */
172 /*-------------------------------------------------------------------*/
173 #define  CACHE_MAX_INDEX              8 /* Max number caches [0..7]  */
174 
175 #define  CACHE_DEVBUF                 0 /* Device Buffer cache       */
176 #define  CACHE_L2                     1 /* L2 cache                  */
177 #define  CACHE_2                      2 /*      (available)          */
178 #define  CACHE_3                      3 /*      (available)          */
179 #define  CACHE_4                      4 /*      (available)          */
180 #define  CACHE_5                      5 /*      (available)          */
181 #define  CACHE_6                      6 /*      (available)          */
182 #define  CACHE_7                      7 /*      (available)          */
183 
184 #ifdef _CACHE_C_
185 /*-------------------------------------------------------------------*/
186 /* Cache entry                                                       */
187 /*-------------------------------------------------------------------*/
188 typedef struct _CACHE {                 /* Cache entry               */
189       U64       key;                    /* Key                       */
190       U32       flag;                   /* Flags                     */
191       int       len;                    /* Buffer length             */
192       void     *buf;                    /* Buffer address            */
193       int       value;                  /* Arbitrary value           */
194       U64       age;                    /* Age                       */
195     } CACHE;
196 
197 /*-------------------------------------------------------------------*/
198 /* Cache header                                                      */
199 /*-------------------------------------------------------------------*/
200 typedef struct _CACHEBLK {              /* Cache header              */
201       int       magic;                  /* Magic number              */
202       int       nbr;                    /* Number entries            */
203       int       busy;                   /* Number busy entries       */
204       int       empty;                  /* Number empty entries      */
205       int       waiters;                /* Number waiters            */
206       int       waits;                  /* Number times waited       */
207       long long size;                   /* Allocated buffer size     */
208       long long hits;                   /* Number lookup hits        */
209       long long fasthits;               /* Number fast lookup hits   */
210       long long misses;                 /* Number lookup misses      */
211       U64       age;                    /* Age counter               */
212       LOCK      lock;                   /* Lock                      */
213       COND      waitcond;               /* Wait for available entry  */
214       CACHE    *cache;                  /* Cache table address       */
215       time_t    atime;                  /* Time last adjustment      */
216       time_t    wtime;                  /* Time last wait            */
217       int       adjusts;                /* Number of adjustments     */
218     } CACHEBLK;
219 #endif
220 
221 /*-------------------------------------------------------------------*/
222 /* Flag definitions                                                  */
223 /*-------------------------------------------------------------------*/
224 #define CACHE_BUSY           0xFF000000 /* Busy bits                 */
225 #define CACHE_TYPE           0x000000FF /* Type bits                 */
226 
227 #define CACHE_FREEBUF                 1 /* Free buf on release       */
228 
229 #ifdef _CACHE_C_
230 #define CACHE_MAGIC          0x01CACE10 /* Magic number              */
231 #define CACHE_DEFAULT_NBR           229 /* Initial entries (prime)   */
232 //FIXME the line below increases the size for CACHE_L2.  Since each
233 //      cckd device always has an active l2 entry this number
234 //      actually limits the number of cckd devices that can be
235 //      attached.
236 //      This is a workaround to increase the max number of devices
237 #define CACHE_DEFAULT_L2_NBR       1031 /* Initial entries for L2    */
238 
239 #define CACHE_WAITTIME             1000 /* Wait time for entry(usec) */
240 
241 #define CACHE_ADJUST_INTERVAL        15 /* Adjustment interval (sec) */
242 #define CACHE_ADJUST_NUMBER         128 /* Uninhibited nbr entries   */
243 #define CACHE_ADJUST_BUSY1           70 /* Increase when this busy 1 */
244 #define CACHE_ADJUST_BUSY2           80 /* Increase when this busy 2 */
245 #define CACHE_ADJUST_RESIZE           8 /* Nbr entries adjusted      */
246 #define CACHE_ADJUST_EMPTY           16 /* Decrease this many empty  */
247 #define CACHE_ADJUST_HIT1            60 /* Increase hit% this low  1 */
248 #define CACHE_ADJUST_HIT2            50 /* Increase hit% this low  2 */
249 #define CACHE_ADJUST_BUSY3           20 /* Decrease not this busy    */
250 #define CACHE_ADJUST_HIT3            90 /*      and hit% this high   */
251 #define CACHE_ADJUST_SIZE  (8*1024*1024)/*      and size this high   */
252 #define CACHE_ADJUST_WAITTIME        10 /* Increase last wait  (sec) */
253 #endif
254 
255 /*-------------------------------------------------------------------*/
256 /* Functions                                                         */
257 /*-------------------------------------------------------------------*/
258 int         cache_nbr(int ix);
259 int         cache_busy(int ix);
260 int         cache_empty(int ix);
261 int         cache_waiters(int ix);
262 long long   cache_size(int ix);
263 long long   cache_hits(int ix);
264 long long   cache_misses(int ix);
265 int         cache_busy_percent(int ix);
266 int         cache_empty_percent(int ix);
267 int         cache_hit_percent(int ix);
268 int         cache_lookup(int ix, U64 key, int *o);
269 typedef int CACHE_SCAN_RTN (int *answer, int ix, int i, void *data);
270 int         cache_scan (int ix, CACHE_SCAN_RTN rtn, void *data);
271 int         cache_lock(int ix);
272 int         cache_unlock(int ix);
273 int         cache_wait(int ix);
274 U64         cache_getkey(int ix, int i);
275 U64         cache_setkey(int ix, int i, U64 key);
276 U32         cache_getflag(int ix, int i);
277 U32         cache_setflag(int ix, int i, U32 andbits, U32 orbits);
278 U64         cache_getage(int ix, int i);
279 U64         cache_setage(int ix, int i);
280 void       *cache_getbuf(int ix, int i, int len);
281 void       *cache_setbuf(int ix, int i, void *buf, int len);
282 int         cache_getlen(int ix, int i);
283 int         cache_getval(int ix, int i);
284 int         cache_setval(int ix, int i, int val);
285 int         cache_release(int ix, int i, int flag);
286 CCH_DLL_IMPORT int         cache_cmd(int argc, char *argv[], char *cmdline);
287 
288 #ifdef _CACHE_C_
289 static int  cache_create (int ix);
290 static int  cache_destroy (int ix);
291 static int  cache_check_ix(int ix);
292 static int  cache_check_cache(int ix);
293 static int  cache_check(int ix, int i);
294 static int  cache_isbusy(int ix, int i);
295 static int  cache_isempty(int ix, int i);
296 static int  cache_adjust(int ix, int n);
297 #if 0
298 static int  cache_resize (int ix, int n);
299 #endif
300 static void cache_allocbuf(int ix, int i, int len);
301 #endif
302 
303 /*-------------------------------------------------------------------*/
304 /* Specific cache definitions (until a better place is found)        */
305 /*-------------------------------------------------------------------*/
306 
307 /*-------------------------------------------------------------------*/
308 /* Device buffer definitions                                         */
309 /*-------------------------------------------------------------------*/
310 #define   CCKD_CACHE_ACTIVE  0x80000000 /* Active entry              */
311 #define   CCKD_CACHE_READING 0x40000000 /* Entry being read          */
312 #define   CCKD_CACHE_WRITING 0x20000000 /* Entry being written       */
313 #define   CCKD_CACHE_IOBUSY  (CCKD_CACHE_READING|CCKD_CACHE_WRITING)
314 #define   CCKD_CACHE_IOWAIT  0x10000000 /* Waiters for i/o           */
315 #define   CCKD_CACHE_UPDATED 0x08000000 /* Buffer has been updated   */
316 #define   CCKD_CACHE_WRITE   0x04000000 /* Entry pending write       */
317 #define   CCKD_CACHE_USED    0x00800000 /* Entry has been used       */
318 
319 #define   CKD_CACHE_ACTIVE   0x80000000 /* Active entry              */
320 #define   FBA_CACHE_ACTIVE   0x80000000 /* Active entry              */
321 #define   SHRD_CACHE_ACTIVE  0x80000000 /* Active entry              */
322 
323 #define   DEVBUF_TYPE_SHARED 0x00000080 /* Shared entry type         */
324 #define   DEVBUF_TYPE_COMP   0x00000040 /* CCKD/CFBA entry type      */
325 #define   DEVBUF_TYPE_CKD    0x00000002 /* CKD entry type            */
326 #define   DEVBUF_TYPE_FBA    0x00000001 /* FBA entry type            */
327 
328 #define   DEVBUF_TYPE_CCKD    (DEVBUF_TYPE_COMP|DEVBUF_TYPE_CKD)
329 #define   DEVBUF_TYPE_CFBA    (DEVBUF_TYPE_COMP|DEVBUF_TYPE_FBA)
330 #define   DEVBUF_TYPE_SCKD    (DEVBUF_TYPE_SHARED|DEVBUF_TYPE_CKD)
331 #define   DEVBUF_TYPE_SFBA    (DEVBUF_TYPE_SHARED|DEVBUF_TYPE_FBA)
332 
333 #define CCKD_CACHE_GETKEY(_ix, _devnum, _trk) \
334 do { \
335   (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \
336   (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \
337 } while (0)
338 #define CCKD_CACHE_SETKEY(_devnum, _trk) \
339   ((U64)(((U64)(_devnum) << 32) | (U64)(_trk)))
340 
341 #define CKD_CACHE_GETKEY(_ix, _devnum, _trk) \
342 { \
343   (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \
344   (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \
345 }
346 #define CKD_CACHE_SETKEY(_devnum, _trk) \
347   ((U64)(((U64)(_devnum) << 32) | (U64)(_trk)))
348 
349 #define FBA_CACHE_GETKEY(_ix, _devnum, _blkgrp) \
350 { \
351   (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \
352   (_blkgrp) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \
353 }
354 #define FBA_CACHE_SETKEY(_devnum, _blkgrp) \
355   ((U64)(((U64)(_devnum) << 32) | (U64)(_blkgrp)))
356 
357 #define SHRD_CACHE_GETKEY(_ix, _devnum, _trk) \
358 { \
359   (_devnum) = (U16)((cache_getkey(CACHE_DEVBUF,(_ix)) >> 32) & 0xFFFF); \
360   (_trk) = (U32)(cache_getkey(CACHE_DEVBUF,(_ix)) & 0xFFFFFFFF); \
361 }
362 #define SHRD_CACHE_SETKEY(_devnum, _trk) \
363   ((U64)(((U64)(_devnum) << 32) | (U64)(_trk)))
364 
365 /*-------------------------------------------------------------------*/
366 /* L2 definitions                                                    */
367 /*-------------------------------------------------------------------*/
368 #define   L2_CACHE_ACTIVE    0x80000000 /* Active entry              */
369 
370 #define L2_CACHE_GETKEY(_ix, _sfx, _devnum, _trk) \
371 do { \
372   (_sfx) = (U16)((cache_getkey(CACHE_L2,(_ix)) >> 48) & 0xFFFF); \
373   (_devnum) = (U16)((cache_getkey(CACHE_L2,(_ix)) >> 32) & 0xFFFF); \
374   (_trk) = (U32)(cache_getkey(CACHE_L2,(_ix)) & 0xFFFFFFFF); \
375 } while (0)
376 #define L2_CACHE_SETKEY(_sfx, _devnum, _trk) \
377   ((U64)(((U64)(_sfx) << 48) | ((U64)(_devnum) << 32) | (U64)(_trk)))
378 
379 #endif /* _HERCULES_CACHE_H */
380