Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of version 2 of the GNU General Public License as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it would be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | * | |
12 | * Further, this software is distributed without any warranty that it is | |
13 | * free of the rightful claim of any third person regarding infringement | |
14 | * or the like. Any license provided herein, whether implied or | |
15 | * otherwise, applies only to this software file. Patent licenses, if | |
16 | * any, provided herein do not apply to combinations of this program with | |
17 | * other software, or any other product whatsoever. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | |
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
22 | * | |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | |
24 | * Mountain View, CA 94043, or: | |
25 | * | |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | |
31 | * | |
32 | */ | |
33 | #include "xfs.h" | |
34 | ||
35 | /* | |
36 | * Source file used to associate/disassociate behaviors with virtualized | |
37 | * objects. See xfs_behavior.h for more information about behaviors, etc. | |
38 | * | |
39 | * The implementation is split between functions in this file and macros | |
40 | * in xfs_behavior.h. | |
41 | */ | |
42 | ||
43 | /* | |
44 | * Insert a new behavior descriptor into a behavior chain. | |
45 | * | |
46 | * The behavior chain is ordered based on the 'position' number which | |
47 | * lives in the first field of the ops vector (higher numbers first). | |
48 | * | |
49 | * Attemps to insert duplicate ops result in an EINVAL return code. | |
50 | * Otherwise, return 0 to indicate success. | |
51 | */ | |
52 | int | |
53 | bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) | |
54 | { | |
55 | bhv_desc_t *curdesc, *prev; | |
56 | int position; | |
57 | ||
58 | /* | |
59 | * Validate the position value of the new behavior. | |
60 | */ | |
61 | position = BHV_POSITION(bdp); | |
62 | ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); | |
63 | ||
64 | /* | |
65 | * Find location to insert behavior. Check for duplicates. | |
66 | */ | |
67 | prev = NULL; | |
68 | for (curdesc = bhp->bh_first; | |
69 | curdesc != NULL; | |
70 | curdesc = curdesc->bd_next) { | |
71 | ||
72 | /* Check for duplication. */ | |
73 | if (curdesc->bd_ops == bdp->bd_ops) { | |
74 | ASSERT(0); | |
75 | return EINVAL; | |
76 | } | |
77 | ||
78 | /* Find correct position */ | |
79 | if (position >= BHV_POSITION(curdesc)) { | |
80 | ASSERT(position != BHV_POSITION(curdesc)); | |
81 | break; /* found it */ | |
82 | } | |
83 | ||
84 | prev = curdesc; | |
85 | } | |
86 | ||
87 | if (prev == NULL) { | |
88 | /* insert at front of chain */ | |
89 | bdp->bd_next = bhp->bh_first; | |
90 | bhp->bh_first = bdp; | |
91 | } else { | |
92 | /* insert after prev */ | |
93 | bdp->bd_next = prev->bd_next; | |
94 | prev->bd_next = bdp; | |
95 | } | |
96 | ||
97 | return 0; | |
98 | } | |
99 | ||
100 | /* | |
101 | * Remove a behavior descriptor from a position in a behavior chain; | |
102 | * the postition is guaranteed not to be the first position. | |
103 | * Should only be called by the bhv_remove() macro. | |
104 | */ | |
105 | void | |
106 | bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) | |
107 | { | |
108 | bhv_desc_t *curdesc, *prev; | |
109 | ||
110 | ASSERT(bhp->bh_first != NULL); | |
111 | ASSERT(bhp->bh_first->bd_next != NULL); | |
112 | ||
113 | prev = bhp->bh_first; | |
114 | for (curdesc = bhp->bh_first->bd_next; | |
115 | curdesc != NULL; | |
116 | curdesc = curdesc->bd_next) { | |
117 | ||
118 | if (curdesc == bdp) | |
119 | break; /* found it */ | |
120 | prev = curdesc; | |
121 | } | |
122 | ||
123 | ASSERT(curdesc == bdp); | |
124 | prev->bd_next = bdp->bd_next; /* remove from after prev */ | |
125 | } | |
126 | ||
127 | /* | |
128 | * Look for a specific ops vector on the specified behavior chain. | |
129 | * Return the associated behavior descriptor. Or NULL, if not found. | |
130 | */ | |
131 | bhv_desc_t * | |
132 | bhv_lookup(bhv_head_t *bhp, void *ops) | |
133 | { | |
134 | bhv_desc_t *curdesc; | |
135 | ||
136 | for (curdesc = bhp->bh_first; | |
137 | curdesc != NULL; | |
138 | curdesc = curdesc->bd_next) { | |
139 | ||
140 | if (curdesc->bd_ops == ops) | |
141 | return curdesc; | |
142 | } | |
143 | ||
144 | return NULL; | |
145 | } | |
146 | ||
147 | /* | |
148 | * Looks for the first behavior within a specified range of positions. | |
149 | * Return the associated behavior descriptor. Or NULL, if none found. | |
150 | */ | |
151 | bhv_desc_t * | |
152 | bhv_lookup_range(bhv_head_t *bhp, int low, int high) | |
153 | { | |
154 | bhv_desc_t *curdesc; | |
155 | ||
156 | for (curdesc = bhp->bh_first; | |
157 | curdesc != NULL; | |
158 | curdesc = curdesc->bd_next) { | |
159 | ||
160 | int position = BHV_POSITION(curdesc); | |
161 | ||
162 | if (position <= high) { | |
163 | if (position >= low) | |
164 | return curdesc; | |
165 | return NULL; | |
166 | } | |
167 | } | |
168 | ||
169 | return NULL; | |
170 | } | |
171 | ||
172 | /* | |
173 | * Return the base behavior in the chain, or NULL if the chain | |
174 | * is empty. | |
175 | * | |
176 | * The caller has not read locked the behavior chain, so acquire the | |
177 | * lock before traversing the chain. | |
178 | */ | |
179 | bhv_desc_t * | |
180 | bhv_base(bhv_head_t *bhp) | |
181 | { | |
182 | bhv_desc_t *curdesc; | |
183 | ||
184 | for (curdesc = bhp->bh_first; | |
185 | curdesc != NULL; | |
186 | curdesc = curdesc->bd_next) { | |
187 | ||
188 | if (curdesc->bd_next == NULL) { | |
189 | return curdesc; | |
190 | } | |
191 | } | |
192 | ||
193 | return NULL; | |
194 | } | |
195 | ||
196 | void | |
197 | bhv_head_init( | |
198 | bhv_head_t *bhp, | |
199 | char *name) | |
200 | { | |
201 | bhp->bh_first = NULL; | |
202 | } | |
203 | ||
204 | void | |
205 | bhv_insert_initial( | |
206 | bhv_head_t *bhp, | |
207 | bhv_desc_t *bdp) | |
208 | { | |
209 | ASSERT(bhp->bh_first == NULL); | |
210 | (bhp)->bh_first = bdp; | |
211 | } | |
212 | ||
213 | void | |
214 | bhv_head_destroy( | |
215 | bhv_head_t *bhp) | |
216 | { | |
217 | ASSERT(bhp->bh_first == NULL); | |
218 | } |