]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/cache.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * cache.c - A simple cache for file systems meta-data.
25 * Copyright (c) 2000 Apple Computer, Inc.
38 typedef struct CacheEntry CacheEntry
;
40 #define kCacheSize (0x100000)
41 #define kCacheMinBlockSize (0x200)
42 #define kCacheMaxBlockSize (0x4000)
43 #define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
45 static CICell gCacheIH
;
46 static long gCacheBlockSize
;
47 static long gCacheNumEntries
;
48 static long gCacheTime
;
51 static CacheEntry
*gCacheEntries
;
52 static char *gCacheBuffer
;
54 static CacheEntry gCacheEntries
[kCacheMaxEntries
];
55 static char gCacheBuffer
[kCacheSize
];
58 unsigned long gCacheHits
;
59 unsigned long gCacheMisses
;
60 unsigned long gCacheEvicts
;
62 void CacheInit( CICell ih
, long blockSize
)
65 if ((ih
== gCacheIH
) && (blockSize
== gCacheBlockSize
))
69 if ((blockSize
< kCacheMinBlockSize
) ||
70 (blockSize
>= kCacheMaxBlockSize
))
73 gCacheBlockSize
= blockSize
;
74 gCacheNumEntries
= kCacheSize
/ gCacheBlockSize
;
84 if (!gCacheBuffer
) gCacheBuffer
= (char *) malloc(kCacheSize
);
85 if (!gCacheEntries
) gCacheEntries
= (CacheEntry
*) malloc(kCacheMaxEntries
* sizeof(CacheEntry
));
86 if ( !gCacheBuffer
|| !gCacheEntries
)
88 gCacheIH
= 0; // invalidate cache
93 bzero(gCacheEntries
, kCacheMaxEntries
* sizeof(CacheEntry
));
96 long CacheRead( CICell ih
, char * buffer
, long long offset
,
97 long length
, long cache
)
99 long cnt
, oldestEntry
= 0, oldestTime
, loadCache
= 0;
102 // See if the data can be cached.
103 if (cache
&& (gCacheIH
== ih
) && (length
== gCacheBlockSize
)) {
104 // Look for the data in the cache.
105 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
106 entry
= &gCacheEntries
[cnt
];
107 if ((entry
->ih
== ih
) && (entry
->offset
== offset
)) {
108 entry
->time
= ++gCacheTime
;
113 // If the data was found copy it to the caller.
114 if (cnt
!= gCacheNumEntries
) {
115 bcopy(gCacheBuffer
+ cnt
* gCacheBlockSize
, buffer
, gCacheBlockSize
);
117 return gCacheBlockSize
;
120 // Could not find the data in the cache.
124 // Read the data from the disk.
126 Read(ih
, (long)buffer
, length
);
127 if (cache
) gCacheMisses
++;
129 // Put the data from the disk in the cache if needed.
131 // Find a free entry.
132 oldestTime
= gCacheTime
;
133 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
134 entry
= &gCacheEntries
[cnt
];
136 // Found a free entry.
137 if (entry
->ih
== 0) break;
139 if (entry
->time
< oldestTime
) {
140 oldestTime
= entry
->time
;
145 // If no free entry was found, use the oldest.
146 if (cnt
== gCacheNumEntries
) {
151 // Copy the data from disk to the new entry.
152 entry
= &gCacheEntries
[cnt
];
154 entry
->time
= ++gCacheTime
;
155 entry
->offset
= offset
;
156 bcopy(buffer
, gCacheBuffer
+ cnt
* gCacheBlockSize
, gCacheBlockSize
);