]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/cache.c
2 * Copyright (c) 2000-2003 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 2.0 (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
];
59 unsigned long gCacheHits
;
60 unsigned long gCacheMisses
;
61 unsigned long gCacheEvicts
;
64 void CacheInit( CICell ih
, long blockSize
)
67 if ((ih
== gCacheIH
) && (blockSize
== gCacheBlockSize
))
71 if ((blockSize
< kCacheMinBlockSize
) ||
72 (blockSize
>= kCacheMaxBlockSize
))
75 gCacheBlockSize
= blockSize
;
76 gCacheNumEntries
= kCacheSize
/ gCacheBlockSize
;
88 if (!gCacheBuffer
) gCacheBuffer
= (char *) malloc(kCacheSize
);
89 if (!gCacheEntries
) gCacheEntries
= (CacheEntry
*) malloc(kCacheMaxEntries
* sizeof(CacheEntry
));
90 if ( !gCacheBuffer
|| !gCacheEntries
)
92 gCacheIH
= 0; // invalidate cache
97 bzero(gCacheEntries
, kCacheMaxEntries
* sizeof(CacheEntry
));
100 long CacheRead( CICell ih
, char * buffer
, long long offset
,
101 long length
, long cache
)
103 long cnt
, oldestEntry
= 0, oldestTime
, loadCache
= 0;
106 // See if the data can be cached.
107 if (cache
&& (gCacheIH
== ih
) && (length
== gCacheBlockSize
)) {
108 // Look for the data in the cache.
109 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
110 entry
= &gCacheEntries
[cnt
];
111 if ((entry
->ih
== ih
) && (entry
->offset
== offset
)) {
112 entry
->time
= ++gCacheTime
;
117 // If the data was found copy it to the caller.
118 if (cnt
!= gCacheNumEntries
) {
119 bcopy(gCacheBuffer
+ cnt
* gCacheBlockSize
, buffer
, gCacheBlockSize
);
123 return gCacheBlockSize
;
126 // Could not find the data in the cache.
130 // Read the data from the disk.
132 Read(ih
, (long)buffer
, length
);
134 if (cache
) gCacheMisses
++;
137 // Put the data from the disk in the cache if needed.
139 // Find a free entry.
140 oldestTime
= gCacheTime
;
141 for (cnt
= 0; cnt
< gCacheNumEntries
; cnt
++) {
142 entry
= &gCacheEntries
[cnt
];
144 // Found a free entry.
145 if (entry
->ih
== 0) break;
147 if (entry
->time
< oldestTime
) {
148 oldestTime
= entry
->time
;
153 // If no free entry was found, use the oldest.
154 if (cnt
== gCacheNumEntries
) {
161 // Copy the data from disk to the new entry.
162 entry
= &gCacheEntries
[cnt
];
164 entry
->time
= ++gCacheTime
;
165 entry
->offset
= offset
;
166 bcopy(buffer
, gCacheBuffer
+ cnt
* gCacheBlockSize
, gCacheBlockSize
);