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