Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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
32struct CacheEntry {
33 CICell ih;
34 long time;
35 long long offset;
36};
37typedef struct CacheEntry 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{
65 gCacheIH = NULL;
66}
67
68void CacheInit( CICell ih, long blockSize )
69{
70#ifdef __i386__
71 if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
72 return;
73#endif
74
75 if ((blockSize < kCacheMinBlockSize) ||
76 (blockSize > kCacheMaxBlockSize))
77 return;
78
79 gCacheBlockSize = blockSize;
80 gCacheNumEntries = kCacheSize / gCacheBlockSize;
81 gCacheTime = 0;
82
83#if CACHE_STATS
84 gCacheHits = 0;
85 gCacheMisses = 0;
86 gCacheEvicts = 0;
87#endif
88
89 gCacheIH = ih;
90
91#ifdef __i386__
92 if (!gCacheBuffer) gCacheBuffer = (char *) malloc(kCacheSize);
93 if (!gCacheEntries) gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
94 if ( !gCacheBuffer || !gCacheEntries )
95 {
96 gCacheIH = 0; // invalidate cache
97 return;
98 }
99#endif
100
101 bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
102}
103
104long CacheRead( CICell ih, char * buffer, long long offset,
105 long length, long cache )
106{
107 long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
108 CacheEntry *entry;
109
110 // See if the data can be cached.
111 if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) {
112 // Look for the data in the cache.
113 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
114 entry = &gCacheEntries[cnt];
115 if ((entry->ih == ih) && (entry->offset == offset)) {
116 entry->time = ++gCacheTime;
117 break;
118 }
119 }
120
121 // If the data was found copy it to the caller.
122 if (cnt != gCacheNumEntries) {
123 bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
124#if CACHE_STATS
125 gCacheHits++;
126#endif
127 return gCacheBlockSize;
128 }
129
130 // Could not find the data in the cache.
131 loadCache = 1;
132 }
133
134 // Read the data from the disk.
135 Seek(ih, offset);
136 Read(ih, (long)buffer, length);
137#if CACHE_STATS
138 if (cache) gCacheMisses++;
139#endif
140
141 // Put the data from the disk in the cache if needed.
142 if (loadCache) {
143 // Find a free entry.
144 oldestTime = gCacheTime;
145 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
146 entry = &gCacheEntries[cnt];
147
148 // Found a free entry.
149 if (entry->ih == 0) break;
150
151 if (entry->time < oldestTime) {
152 oldestTime = entry->time;
153 oldestEntry = cnt;
154 }
155 }
156
157 // If no free entry was found, use the oldest.
158 if (cnt == gCacheNumEntries) {
159 cnt = oldestEntry;
160#if CACHE_STATS
161 gCacheEvicts++;
162#endif
163 }
164
165 // Copy the data from disk to the new entry.
166 entry = &gCacheEntries[cnt];
167 entry->ih = ih;
168 entry->time = ++gCacheTime;
169 entry->offset = offset;
170 bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
171 }
172
173 return length;
174}
175

Archive Download this file

Revision: 2057