]>
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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * cache.c - A simple cache for file systems meta-data.
28 * Copyright (c) 2000 Apple Computer, Inc.
41 typedef struct CacheEntry CacheEntry
;
43 #define kCacheSize (0x100000)
44 #define kCacheMinBlockSize (0x200)
45 #define kCacheMaxBlockSize (0x4000)
46 #define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
48 static CICell gCacheIH
;
49 static long gCacheBlockSize
;
50 static long gCacheNumEntries
;
51 static long gCacheTime
;
54 static CacheEntry
*gCacheEntries
;
55 static char *gCacheBuffer
;
57 static CacheEntry gCacheEntries
[kCacheMaxEntries
];
58 static char gCacheBuffer
[kCacheSize
];
62 unsigned long gCacheHits
;
63 unsigned long gCacheMisses
;
64 unsigned long gCacheEvicts
;
67 void CacheInit( CICell ih
, long blockSize
)
70 if ((ih
== gCacheIH
) && (blockSize
== gCacheBlockSize
))
74 if ((blockSize
< kCacheMinBlockSize
) ||
75 (blockSize
>= kCacheMaxBlockSize
))
78 gCacheBlockSize
= blockSize
;
79 gCacheNumEntries
= kCacheSize
/ gCacheBlockSize
;
91 if (!gCacheBuffer
) gCacheBuffer
= (char *) malloc(kCacheSize
);
92 if (!gCacheEntries
) gCacheEntries
= (CacheEntry
*) malloc(kCacheMaxEntries
* sizeof(CacheEntry
));
93 if ( !gCacheBuffer
|| !gCacheEntries
)
95 gCacheIH
= 0; // invalidate cache
100 bzero(gCacheEntries
, kCacheMaxEntries
* sizeof(CacheEntry
));
103 long CacheRead( CICell ih
, char * buffer
, long long offset
,
104 long length
, long cache
)
106 long cnt
, oldestEntry
= 0, oldestTime
, loadCache
= 0;
109 // See if the data can be cached.
110 if (cache
&& (gCacheIH
== ih
) && (length
== gCacheBlockSize
)) {
111 // Look for the data in the cache.
112 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
113 entry
= &gCacheEntries
[cnt
];
114 if ((entry
->ih
== ih
) && (entry
->offset
== offset
)) {
115 entry
->time
= ++gCacheTime
;
120 // If the data was found copy it to the caller.
121 if (cnt
!= gCacheNumEntries
) {
122 bcopy(gCacheBuffer
+ cnt
* gCacheBlockSize
, buffer
, gCacheBlockSize
);
126 return gCacheBlockSize
;
129 // Could not find the data in the cache.
133 // Read the data from the disk.
135 Read(ih
, (long)buffer
, length
);
137 if (cache
) gCacheMisses
++;
140 // Put the data from the disk in the cache if needed.
142 // Find a free entry.
143 oldestTime
= gCacheTime
;
144 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
145 entry
= &gCacheEntries
[cnt
];
147 // Found a free entry.
148 if (entry
->ih
== 0) break;
150 if (entry
->time
< oldestTime
) {
151 oldestTime
= entry
->time
;
156 // If no free entry was found, use the oldest.
157 if (cnt
== gCacheNumEntries
) {
164 // Copy the data from disk to the new entry.
165 entry
= &gCacheEntries
[cnt
];
167 entry
->time
= ++gCacheTime
;
168 entry
->offset
= offset
;
169 bcopy(buffer
, gCacheBuffer
+ cnt
* gCacheBlockSize
, gCacheBlockSize
);