Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/libsaio/cache.c

1/*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * cache.c - A simple cache for file systems meta-data.
24 *
25 * Copyright (c) 2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30#include <sl.h>
31// #include <fs.h>
32
33struct CacheEntry
34{
35CICell ih;
36long time;
37long long offset;
38};
39typedef struct CacheEntry CacheEntry;
40
41#define kCacheSize (0x100000)
42#define kCacheMinBlockSize (0x200)
43#define kCacheMaxBlockSize (0x8000)
44#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
45
46static CICell gCacheIH;
47static long gCacheBlockSize;
48static long gCacheNumEntries;
49static long gCacheTime;
50
51#ifdef __i386__
52static CacheEntry *gCacheEntries;
53static char *gCacheBuffer;
54#else
55static CacheEntry gCacheEntries[kCacheMaxEntries];
56static char gCacheBuffer[kCacheSize];
57#endif
58
59#if CACHE_STATS
60unsigned long gCacheHits;
61unsigned long gCacheMisses;
62unsigned long gCacheEvicts;
63#endif
64
65void CacheReset()
66{
67 gCacheIH = NULL;
68}
69
70void CacheInit( CICell ih, long blockSize )
71{
72#ifdef __i386__
73 if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
74{
75 return;
76}
77#endif
78
79 if ((blockSize < kCacheMinBlockSize) || (blockSize > kCacheMaxBlockSize))
80{
81 return;
82}
83
84 gCacheBlockSize = blockSize;
85 gCacheNumEntries = kCacheSize / gCacheBlockSize;
86 gCacheTime = 0;
87
88#if CACHE_STATS
89 gCacheHits= 0;
90 gCacheMisses= 0;
91 gCacheEvicts= 0;
92#endif
93
94 gCacheIH = ih;
95
96#ifdef __i386__
97 if (!gCacheBuffer)
98{
99gCacheBuffer = (char *) malloc(kCacheSize);
100}
101
102 if (!gCacheEntries)
103{
104gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
105}
106
107 if (!gCacheBuffer || !gCacheEntries)
108 {
109 gCacheIH = 0; // invalidate cache
110 return;
111 }
112#endif
113
114 bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
115}
116
117long CacheRead(CICell ih, char * buffer, long long offset, long length, long cache)
118{
119 long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
120 CacheEntry *entry;
121
122 // See if the data can be cached.
123 if (cache && (gCacheIH == ih) && (length == gCacheBlockSize))
124{
125 // Look for the data in the cache.
126 for (cnt = 0; cnt < gCacheNumEntries; cnt++)
127{
128 entry = &gCacheEntries[cnt];
129
130 if ((entry->ih == ih) && (entry->offset == offset))
131{
132 entry->time = ++gCacheTime;
133 break;
134 }
135 }
136
137 // If the data was found copy it to the caller.
138 if (cnt != gCacheNumEntries)
139{
140 bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
141#if CACHE_STATS
142 gCacheHits++;
143#endif
144 return gCacheBlockSize;
145 }
146
147 // Could not find the data in the cache.
148 loadCache = 1;
149 }
150
151 // Read the data from the disk.
152 Seek(ih, offset);
153 Read(ih, (long)buffer, length);
154
155#if CACHE_STATS
156 if (cache)
157{
158gCacheMisses++;
159}
160#endif
161
162 // Put the data from the disk in the cache if needed.
163 if (loadCache)
164{
165 // Find a free entry.
166 oldestTime = gCacheTime;
167
168 for (cnt = 0; cnt < gCacheNumEntries; cnt++)
169{
170 entry = &gCacheEntries[cnt];
171
172 // Found a free entry.
173 if (entry->ih == 0)
174{
175break;
176}
177
178 if (entry->time < oldestTime)
179{
180 oldestTime = entry->time;
181 oldestEntry = cnt;
182 }
183 }
184
185 // If no free entry was found, use the oldest.
186 if (cnt == gCacheNumEntries)
187{
188 cnt = oldestEntry;
189#if CACHE_STATS
190 gCacheEvicts++;
191#endif
192 }
193
194 // Copy the data from disk to the new entry.
195 entry = &gCacheEntries[cnt];
196 entry->ih = ih;
197 entry->time = ++gCacheTime;
198 entry->offset = offset;
199 bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
200 }
201
202 return length;
203}
204

Archive Download this file

Revision: 2042