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 *
5 * The contents of this file constitute Original Code as defined in and
6 * are subject to the Apple Public Source License Version 2.0 (the
7 * "License"). You may not use this file except in compliance with the
8 * License. Please obtain a copy of the License at
9 * http://www.apple.com/publicsource and read it before using this file.
10 *
11 * This Original Code and all software distributed under the License are
12 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
13 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
14 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
16 * License for the specific language governing rights and limitations
17 * under the License.
18 *
19 * cache.c - A simple cache for file systems meta-data.
20 *
21 * Copyright (c) 2000 Apple Computer, Inc.
22 *
23 * DRI: Josh de Cesare
24 */
25
26#include <sl.h>
27// #include <fs.h>
28
29struct CacheEntry
30{
31CICell ih;
32long time;
33long long offset;
34};
35typedef struct CacheEntry CacheEntry;
36
37#define kCacheSize (0x100000)
38#define kCacheMinBlockSize (0x200)
39#define kCacheMaxBlockSize (0x8000)
40#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
41
42static CICell gCacheIH;
43static long gCacheBlockSize;
44static long gCacheNumEntries;
45static long gCacheTime;
46
47#ifdef __i386__
48static CacheEntry *gCacheEntries;
49static char *gCacheBuffer;
50#else
51static CacheEntry gCacheEntries[kCacheMaxEntries];
52static char gCacheBuffer[kCacheSize];
53#endif
54
55#if CACHE_STATS
56unsigned long gCacheHits;
57unsigned long gCacheMisses;
58unsigned long gCacheEvicts;
59#endif
60
61void CacheReset()
62{
63gCacheIH = NULL;
64}
65
66void CacheInit( CICell ih, long blockSize )
67{
68#ifdef __i386__
69if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
70{
71return;
72}
73#endif
74
75if ((blockSize < kCacheMinBlockSize) || (blockSize > kCacheMaxBlockSize))
76{
77return;
78}
79
80gCacheBlockSize = blockSize;
81gCacheNumEntries = kCacheSize / gCacheBlockSize;
82gCacheTime = 0;
83
84#if CACHE_STATS
85gCacheHits= 0;
86gCacheMisses= 0;
87gCacheEvicts= 0;
88#endif
89
90 gCacheIH = ih;
91
92#ifdef __i386__
93if (!gCacheBuffer)
94{
95gCacheBuffer = (char *) malloc(kCacheSize);
96}
97
98if (!gCacheEntries)
99{
100gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
101}
102
103if (!gCacheBuffer || !gCacheEntries)
104{
105gCacheIH = 0; // invalidate cache
106return;
107}
108#endif
109
110bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
111}
112
113long CacheRead(CICell ih, char * buffer, long long offset, long length, long cache)
114{
115long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
116CacheEntry *entry;
117
118// See if the data can be cached.
119if (cache && (gCacheIH == ih) && (length == gCacheBlockSize))
120{
121// Look for the data in the cache.
122for (cnt = 0; cnt < gCacheNumEntries; cnt++)
123{
124entry = &gCacheEntries[cnt];
125
126if ((entry->ih == ih) && (entry->offset == offset))
127{
128entry->time = ++gCacheTime;
129break;
130}
131}
132
133// If the data was found copy it to the caller.
134if (cnt != gCacheNumEntries)
135{
136bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
137#if CACHE_STATS
138gCacheHits++;
139#endif
140return gCacheBlockSize;
141}
142
143// Could not find the data in the cache.
144loadCache = 1;
145}
146
147// Read the data from the disk.
148Seek(ih, offset);
149Read(ih, (long)buffer, length);
150
151#if CACHE_STATS
152if (cache)
153{
154gCacheMisses++;
155}
156#endif
157
158// Put the data from the disk in the cache if needed.
159if (loadCache)
160{
161// Find a free entry.
162oldestTime = gCacheTime;
163
164for (cnt = 0; cnt < gCacheNumEntries; cnt++)
165{
166entry = &gCacheEntries[cnt];
167
168// Found a free entry.
169if (entry->ih == 0)
170{
171break;
172}
173
174if (entry->time < oldestTime)
175{
176oldestTime = entry->time;
177oldestEntry = cnt;
178}
179}
180
181// If no free entry was found, use the oldest.
182if (cnt == gCacheNumEntries)
183{
184cnt = oldestEntry;
185#if CACHE_STATS
186gCacheEvicts++;
187#endif
188}
189
190// Copy the data from disk to the new entry.
191entry = &gCacheEntries[cnt];
192entry->ih = ih;
193entry->time = ++gCacheTime;
194entry->offset = offset;
195bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
196}
197
198return length;
199}
200

Archive Download this file

Revision: 2045