]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/fileio/v2_0/src/inocache.cxx
Initial revision
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / src / inocache.cxx
1 //=============================================================================
2 //
3 //      inocache.cxx
4 //
5 //      Implementation of inode cache
6 //
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //=============================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     jlarmour
44 // Contributors:  
45 // Date:          2002-01-18
46 // Purpose:       
47 // Description:   
48 // Usage:
49 //              #include <cyg/fileio/inode.h>
50 //              ...
51 //              
52 //
53 //####DESCRIPTIONEND####
54 //
55 //=============================================================================
56
57 #include <pkgconf/system.h>
58 #include <cyg/infra/cyg_type.h>
59 #include <stdlib.h>
60 #include <cyg/fileio/inode.h>
61
62 #ifdef CYGPKG_KERNEL
63 # include <pkgconf/kernel.h>
64 # include <cyg/kernel/mutex.hxx>
65 # if 0
66 # define LOCK_ICACHE(_ic_)        \
67   CYG_MACRO_START                 \
68   (_ic_)->icmutex.lock();         \
69   CYG_MACRO_END
70
71 # define UNLOCK_ICACHE(_ic_)      \
72   CYG_MACRO_START                 \
73   (_ic_)->icmutex.unlock();       \
74   CYG_MACRO_END
75 # define LOCK_INO(_ic_,_ino_)     \
76   CYG_MACRO_START                 \
77   (_ic_)->icmutex.lock();         \
78   CYG_MACRO_END
79 # define UNLOCK_INO(_ic_,_ino_)   \
80   CYG_MACRO_START                 \
81   (_ic_)->icmutex.unlock();       \
82   CYG_MACRO_END
83 # endif
84 #endif
85
86 # define LOCK_ICACHE(_ic_)         CYG_EMPTY_STATEMENT
87 # define UNLOCK_ICACHE(_ic_)       CYG_EMPTY_STATEMENT
88 # define LOCK_INO(_ic_,_ino_)      CYG_EMPTY_STATEMENT
89 # define UNLOCK_INO(_ic_,_ino_)    CYG_EMPTY_STATEMENT
90
91 // Tried to make this implementation use tables, but the requirement to
92 // allow for extra space makes this difficult
93
94 __externC void
95 cyg_inodecache_destroy( cyg_inodecache *ic )
96 {
97     cyg_inode *tmp;
98     for ( tmp=ic->head; tmp != NULL; tmp=tmp->i_cache_next )
99         free(tmp);
100 #if CYGNUM_IO_FILEIO_MAX_INODE_CACHE_DEAD > 0
101     for ( tmp=ic->freeable; tmp != NULL; tmp=tmp->i_cache_next )
102         free(tmp);
103 #endif    
104 } // cyg_inodecache_destroy()
105
106 static __inline__ void
107 insert_in_list( cyg_inode **i, cyg_inode *ino )
108 {   
109     cyg_inode *here = *i;
110     if ( here == NULL ) {
111         ino->i_cache_prev = ino->i_cache_next = ino;
112     } else {
113         ino->i_cache_prev = here->i_cache_prev;
114         ino->i_cache_next = here;
115         here->i_cache_prev = ino;
116         ino->i_cache_prev->i_cache_next = ino;
117     }
118     // put at start, as this is more likely to come off sooner than later
119     *i = ino;
120 }
121
122 // Create an inode. Returns a negative error code on error.
123 __externC cyg_inode *
124 cyg_inode_create( cyg_inodecache *ic )
125 {
126     cyg_inode *ni;
127
128     ni = (cyg_inode *)malloc( sizeof(cyg_inode)+ic->privatespace );
129     if ( !ni )
130         return ni;
131     ni->i_count = 1;
132
133     LOCK_ICACHE(ic);
134     insert_in_list( &ic->head, ni );
135     UNLOCK_ICACHE(ic);
136     
137     return ni;
138 } // cyg_inode_create()
139
140 __externC cyg_inode *
141 cyg_inode_get( cyg_inodecache *ic, cyg_uint32 ino )
142 {
143     cyg_inode *head = ic->head;
144     // first try the (live) cache
145     if (head) { 
146         cyg_inode *tmp=head;
147         while (1) {
148             if ( tmp->i_ino == ino ) {
149                 tmp->i_count++;
150                 return tmp;
151             }
152             tmp = tmp->i_cache_next;
153             if ( tmp == head )
154                 break;
155         }
156     }
157 #if CYGNUM_IO_FILEIO_MAX_INODE_CACHE_DEAD > 0
158     // now try the cache of dead inodes
159     head = ic->freeable;
160     if (head) { 
161         cyg_inode *tmp=head;
162         while (1) {
163             if ( tmp->i_ino == ino ) {
164                 tmp->i_count++;
165                 LOCK_ICACHE(ic);
166                 ic->freeablelistlen--;
167                 if ( ic->freeablelistlen ) {
168                     tmp->i_cache_prev->i_cache_next = tmp->i_cache_next;
169                     tmp->i_cache_next->i_cache_prev = tmp->i_cache_prev;
170                 } else
171                     ic->freeable = NULL;
172                 insert_in_list( &ic->head, tmp );
173                 UNLOCK_ICACHE(ic);
174                 return tmp;
175             }
176             tmp = tmp->i_cache_next;
177             if ( tmp == head )
178                 break;
179         }
180     }
181 #endif
182     // not found so make it
183     return cyg_inode_create( ic );
184     
185 } // cyg_inode_get()
186
187 __externC void
188 cyg_inode_put( cyg_inodecache *ic, cyg_inode *ino )
189 {
190     if ( --ino->i_count == 0 )
191     {
192         LOCK_ICACHE(ic);
193         if ( ino->i_cache_next == ino ) {
194             ic->head = NULL;
195         } else {
196             ino->i_cache_prev->i_cache_next = ino->i_cache_next;
197             ino->i_cache_next->i_cache_prev = ino->i_cache_prev;
198         }
199 #if CYGNUM_IO_FILEIO_MAX_INODE_CACHE_DEAD > 0
200         ic->freeablelistlen++;
201         insert_in_list( &ic->freeable, ino );
202         if ( ic->freeablelistlen > CYGNUM_IO_FILEIO_MAX_INODE_CACHE_DEAD ) {
203             cyg_inode *prev = ino->i_cache_prev;
204             prev->i_cache_prev->i_cache_next = ino;
205             ino->i_cache_prev = prev->i_cache_prev;
206             ic->freecallback(prev);
207             free(prev);
208         }
209 #else
210         ic->freecallback(ino);
211         free(ino);
212 #endif
213     }
214 } // cyg_inode_put()
215
216 // EOF inode.h