]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/ia64/libuwx/src/uwx_scoreboard.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / ia64 / libuwx / src / uwx_scoreboard.c
1 /*
2 Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
10 conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #ifndef _KERNEL
26 #include <stdlib.h>
27 #endif
28
29 #include "uwx_env.h"
30 #include "uwx_scoreboard.h"
31 #include "uwx_trace.h"
32
33 #ifdef _KERNEL
34 static unsigned short uwx_allocated;
35 static struct uwx_scoreboard uwx_scoreboard[sizeof(uwx_allocated) << 3];
36
37 static void
38 free(struct uwx_scoreboard *p)
39 {
40         int idx = p - uwx_scoreboard;
41         uwx_allocated &= ~(1 << idx);
42 }
43
44 static struct uwx_scoreboard *
45 malloc(size_t sz)
46 {
47         int idx;
48         if (sz != sizeof(struct uwx_scoreboard))
49                 return (NULL);
50         for (idx = 0; idx < (sizeof(uwx_allocated) << 3); idx++) {
51                 if ((uwx_allocated & (1 << idx)) == 0) {
52                         uwx_allocated |= 1 << idx;
53                         return (uwx_scoreboard + idx);
54                 }
55         }
56         return (NULL);
57 }
58 #endif
59
60
61 void uwx_prealloc_scoreboard(struct uwx_env *env, struct uwx_scoreboard *sb)
62 {
63     sb->id = env->nscoreboards++;
64     sb->nextused = env->used_scoreboards;
65     sb->prealloc = 1;
66     env->used_scoreboards = sb;
67     TRACE_B_PREALLOC(sb->id)
68 }
69
70 struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
71 {
72     struct uwx_scoreboard *sb;
73     int i;
74
75     if (env->free_scoreboards != 0) {
76         sb = env->free_scoreboards;
77         env->free_scoreboards = sb->nextfree;
78         TRACE_B_REUSE(sb->id)
79     }
80     else {
81         if (env->allocate_cb == 0)
82             sb = (struct uwx_scoreboard *)
83                         malloc(sizeof(struct uwx_scoreboard));
84         else
85             sb = (struct uwx_scoreboard *)
86                         (*env->allocate_cb)(sizeof(struct uwx_scoreboard));
87         if (sb == 0)
88             return 0;
89         sb->id = env->nscoreboards++;
90         sb->nextused = env->used_scoreboards;
91         sb->prealloc = 0;
92         env->used_scoreboards = sb;
93         TRACE_B_ALLOC(sb->id)
94     }
95
96     sb->nextstack = 0;
97     sb->nextlabel = 0;
98     for (i = 0; i < env->nsbreg; i++)
99         sb->rstate[i] = UWX_DISP_NONE;
100     sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0));
101     sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
102     sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_AR_PFS);
103     sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_AR_UNAT);
104     sb->label = 0;
105     return sb;
106 }
107
108 static
109 void uwx_reclaim_scoreboards(struct uwx_env *env)
110 {
111     struct uwx_scoreboard *sb;
112
113     env->free_scoreboards = 0;
114     for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) {
115         sb->nextfree = env->free_scoreboards;
116         env->free_scoreboards = sb;
117     }
118     env->labeled_scoreboards = 0;
119 }
120
121 struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env)
122 {
123     struct uwx_scoreboard *sb;
124
125     uwx_reclaim_scoreboards(env);
126     sb = uwx_alloc_scoreboard(env);
127     return sb;
128 }
129
130 struct uwx_scoreboard *uwx_new_scoreboard(
131     struct uwx_env *env,
132     struct uwx_scoreboard *prevsb)
133 {
134     int i;
135     struct uwx_scoreboard *sb;
136
137     sb = uwx_alloc_scoreboard(env);
138     if (sb == 0)
139         return 0;
140     sb->nextstack = prevsb;
141     for (i = 0; i < env->nsbreg; i++)
142         sb->rstate[i] = prevsb->rstate[i];
143     return sb;
144 }
145
146 struct uwx_scoreboard *uwx_pop_scoreboards(
147     struct uwx_env *env,
148     struct uwx_scoreboard *sb,
149     int ecount)
150 {
151     struct uwx_scoreboard *next;
152
153     while (ecount > 0) {
154         next = sb->nextstack;
155         TRACE_B_POP(sb->id)
156         sb->nextstack = 0;
157         sb->nextfree = env->free_scoreboards;
158         env->free_scoreboards = sb;
159         sb = next;
160         if (sb == 0)
161             return 0;
162         ecount--;
163     }
164     return sb;
165 }
166
167 int uwx_label_scoreboard(
168     struct uwx_env *env,
169     struct uwx_scoreboard *sb,
170     int label)
171 {
172     struct uwx_scoreboard *new;
173     struct uwx_scoreboard *back;
174     struct uwx_scoreboard *next;
175     int i;
176
177     TRACE_B_LABEL(label)
178
179     /* Copy the current stack, storing reverse links */
180     /* in the "nextstack" field. */
181
182     back = 0;
183     new = 0;
184     while (sb != 0) {
185         TRACE_B_LABEL_COPY(sb->id)
186         new = uwx_alloc_scoreboard(env);
187         if (new == 0)
188             return UWX_ERR_NOMEM;
189         new->nextstack = back;
190         for (i = 0; i < env->nsbreg; i++)
191             new->rstate[i] = sb->rstate[i];
192         sb = sb->nextstack;
193         back = new;
194     }
195
196     /* The "new" pointer now points to the bottom of the new stack, */
197     /* and the "nextstack" links lead towards the top. */
198     /* Now go back down the stack, reversing the stack links to their */
199     /* proper direction. */
200
201     back = 0;
202     while (new != 0) {
203         next = new->nextstack;
204         new->nextstack = back;
205         TRACE_B_LABEL_REVERSE(back, new)
206         back = new;
207         new = next;
208     }
209
210     /* The "back" pointer now points to the top of the stack. */
211
212     back->label = label;
213     back->nextlabel = env->labeled_scoreboards;
214     env->labeled_scoreboards = back;
215     return UWX_OK;
216 }
217
218 int uwx_copy_scoreboard(
219     struct uwx_env *env,
220     struct uwx_scoreboard *sb,
221     int label)
222 {
223     struct uwx_scoreboard *next;
224     struct uwx_scoreboard *next2;
225     struct uwx_scoreboard *lsb;
226     struct uwx_scoreboard *new;
227     struct uwx_scoreboard *back;
228     int i;
229
230     TRACE_B_COPY(label, sb->id)
231
232     /* Free the existing stack. */
233
234     next = sb->nextstack;
235     while (next != 0) {
236         TRACE_B_COPY_FREE(next->id)
237         next2 = next->nextstack;
238         next->nextstack = 0;
239         next->nextfree = env->free_scoreboards;
240         env->free_scoreboards = next;
241         next = next2;
242     }
243
244     /* Find the scoreboard with the requested label. */
245
246     for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) {
247         if (lsb->label == label)
248             break;
249     }
250
251     if (lsb == 0)
252         return UWX_ERR_UNDEFLABEL;
253
254     TRACE_B_COPY_FOUND(lsb->id)
255
256     /* Copy the labeled scoreboard. */
257
258     sb->nextstack = 0;
259     sb->nextlabel = 0;
260     for (i = 0; i < env->nsbreg; i++)
261         sb->rstate[i] = lsb->rstate[i];
262     sb->label = 0;
263
264     /* Now copy its stack, storing reverse links in the nextstack field. */
265
266     back = sb;
267     new = 0;
268     for (next = lsb->nextstack; next != 0; next = next->nextstack) {
269         TRACE_B_COPY_COPY(next->id)
270         new = uwx_alloc_scoreboard(env);
271         if (new == 0)
272             return UWX_ERR_NOMEM;
273         new->nextstack = back;
274         for (i = 0; i < env->nsbreg; i++)
275             new->rstate[i] = next->rstate[i];
276         back = new;
277     }
278
279     /* The "new" pointer now points to the bottom of the new stack, */
280     /* and the "nextstack" links lead towards the top. */
281     /* Now go back down the stack, reversing the nextstack links to their */
282     /* proper direction. */
283
284     back = 0;
285     while (new != 0) {
286         next = new->nextstack;
287         new->nextstack = back;
288         TRACE_B_COPY_REVERSE(back, new)
289         back = new;
290         new = next;
291     }
292
293     return UWX_OK;
294 }
295
296 void uwx_free_scoreboards(struct uwx_env *env)
297 {
298     struct uwx_scoreboard *sb;
299     struct uwx_scoreboard *next;
300
301     for (sb = env->used_scoreboards; sb != 0; sb = next) {
302         TRACE_B_FREE(sb->id)
303         next = sb->nextused;
304         if (!sb->prealloc) {
305             if (env->free_cb == 0)
306                 free((void *)sb);
307             else
308                 (*env->free_cb)((void *)sb);
309         }
310     }
311     env->free_scoreboards = 0;
312     env->used_scoreboards = 0;
313     env->labeled_scoreboards = 0;
314 }
315