Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2238