pull-prototypes-to-head-20020821
[openafs.git] / src / afs / afs_axscache.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* statistics */
18 #include "afs/stds.h"
19 static struct axscache *afs_axsfreelist = NULL;
20 static struct xfreelist { struct xfreelist *next; } *xfreemallocs = 0;
21 static int afs_xaxscnt = 0;
22 afs_rwlock_t afs_xaxs;
23
24 /* takes an address of an access cache & uid, returns ptr */
25 /* PRECONDITION: first field has been checked and doesn't match! 
26  * INVARIANT:  isparent(i,j) ^ isparent(j,i)  (ie, they switch around)
27  */
28 struct axscache *afs_SlowFindAxs(struct axscache **cachep, afs_int32 id)
29 {
30     register struct axscache *i,*j;
31
32     j=(*cachep);
33     i=j->next;
34     while (i) {
35         if (i->uid == id) {
36             axs_Front(cachep,j,i);        /* maintain LRU queue */
37             return(i);
38         }
39
40         if ((j=i->next)) {   /* ASSIGNMENT HERE! */
41             if (j->uid == id) {
42                 axs_Front(cachep,i,j);
43                 return(j);
44             }
45         } else 
46             return ((struct axscache *) NULL);
47         i=j->next;
48     }
49     return ((struct axscache *) NULL);
50 }
51
52
53 #define NAXSs (1000 / sizeof(struct axscache))
54 struct axscache *axs_Alloc(void) 
55 {
56     register struct axscache *i, *j, *xsp;
57     struct axscache *h;
58     int k;
59
60     ObtainWriteLock(&afs_xaxs,174);
61     if ((h = afs_axsfreelist)) {
62         afs_axsfreelist = h->next;
63     } else {
64         h=i=j= (struct axscache *) afs_osi_Alloc(NAXSs * sizeof(struct axscache));
65         afs_xaxscnt++;
66         xsp = (struct axscache *)xfreemallocs;
67         xfreemallocs = (struct xfreelist *)h;
68         xfreemallocs->next = (struct xfreelist *)xsp;
69         for (k = 0; k < NAXSs-1; k++, i++) {
70             i->uid = -2;
71             i->axess = 0;
72             i->next = ++j;       /* need j because order of evaluation not defined */
73         }
74         i->uid = -2;
75         i->axess = 0;
76         i->next = NULL;
77         afs_axsfreelist = h->next;
78     }
79     ReleaseWriteLock(&afs_xaxs);
80     return(h);
81
82
83
84 #define axs_Free(axsp) { \
85  ObtainWriteLock(&afs_xaxs,175);             \
86  axsp->next = afs_axsfreelist;           \
87  afs_axsfreelist = axsp;                 \
88  ReleaseWriteLock(&afs_xaxs);            \
89 }
90
91
92 /* I optimize for speed on lookup, and don't give a RIP about delete.
93  */
94 void afs_RemoveAxs(struct axscache **headp, struct axscache *axsp)
95 {
96     struct axscache *i, *j;
97
98     if (*headp && axsp) {               /* is bullet-proofing really neccessary? */   
99         if (*headp == axsp) {           /* most common case, I think */
100             *headp = axsp->next;
101             axs_Free(axsp);
102             return;
103         }
104
105         i= *headp;
106         j=i->next; 
107     
108         while (j) {
109             if (j == axsp) {
110                 i->next = j->next;
111                 axs_Free(axsp);
112                 return;
113             }
114             if ((i = j->next)) {   /* ASSIGNMENT HERE! */
115                 j->next = i->next;
116                 axs_Free(axsp);
117                 return;
118             }
119         }
120     }  /* end of "if neither pointer is NULL" */
121
122     return;   /* !#@  FAILED to find it! */
123 }
124
125
126 /* 
127  * Takes an entire list of access cache structs and prepends them, lock, stock,
128  * and barrel, to the front of the freelist.
129  */
130 void afs_FreeAllAxs(struct axscache **headp)
131 {
132     struct axscache *i,*j;
133
134     i= *headp;
135     j=NULL;
136
137     while (i) {   /* chase down the list 'til we reach the end */
138         j=i->next;
139         if (!j) {
140             ObtainWriteLock (&afs_xaxs,176);
141             i->next = afs_axsfreelist;   /* tack on the freelist to the end */
142             afs_axsfreelist = *headp;
143             ReleaseWriteLock (&afs_xaxs);
144             *headp = NULL;
145             return;
146         }
147         i=j->next;
148     }
149
150     if (j) {    /* we ran off the end of the list... */
151         ObtainWriteLock (&afs_xaxs,177);
152         j->next = afs_axsfreelist;   /* tack on the freelist to the end */
153         afs_axsfreelist = *headp;
154         ReleaseWriteLock (&afs_xaxs);
155     }   
156     *headp = NULL;
157     return;
158 }
159    
160
161 /* doesn't appear to be used at all */
162 #if 0
163 static void shutdown_xscache(void) 
164 {
165     struct xfreelist *xp, *nxp;
166
167     RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
168     xp =  xfreemallocs;
169     while (xp) {
170         nxp = xp->next;
171         afs_osi_Free((char *)xp, NAXSs * sizeof(struct axscache));
172         xp = nxp;
173     }
174     afs_axsfreelist = NULL;
175     xfreemallocs = NULL;
176 }
177 #endif