1 | /* |
---|
2 | * h.c -- Handle allocation module |
---|
3 | * |
---|
4 | * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. |
---|
5 | * See the file "license.txt" for usage and redistribution license requirements |
---|
6 | * |
---|
7 | * $Id$ |
---|
8 | */ |
---|
9 | |
---|
10 | /******************************** Description *********************************/ |
---|
11 | |
---|
12 | /* |
---|
13 | * This module provides a simple API to allocate and free handles |
---|
14 | * It maintains a dynamic array of pointers. These usually point to |
---|
15 | * per-handle structures. |
---|
16 | */ |
---|
17 | |
---|
18 | /********************************* Includes ***********************************/ |
---|
19 | |
---|
20 | #ifdef UEMF |
---|
21 | #include "uemf.h" |
---|
22 | #else |
---|
23 | #include "basic/basicInternal.h" |
---|
24 | #endif |
---|
25 | |
---|
26 | /********************************** Defines ***********************************/ |
---|
27 | /* |
---|
28 | * The handle list stores the length of the list and the number of used |
---|
29 | * handles in the first two words. These are hidden from the caller by |
---|
30 | * returning a pointer to the third word to the caller |
---|
31 | */ |
---|
32 | |
---|
33 | #define H_LEN 0 /* First entry holds length of list */ |
---|
34 | #define H_USED 1 /* Second entry holds number of used */ |
---|
35 | #define H_OFFSET 2 /* Offset to real start of list */ |
---|
36 | |
---|
37 | #define H_INCR 16 /* Grow handle list in chunks this size */ |
---|
38 | |
---|
39 | /*********************************** Code *************************************/ |
---|
40 | /* |
---|
41 | * Allocate a new file handle. On the first call, the caller must set the |
---|
42 | * handle map to be a pointer to a null pointer. *map points to the second |
---|
43 | * element in the handle array. |
---|
44 | */ |
---|
45 | |
---|
46 | #ifdef B_STATS |
---|
47 | int HALLOC(B_ARGS_DEC, void ***map) |
---|
48 | #else |
---|
49 | int hAlloc(void ***map) |
---|
50 | #endif |
---|
51 | { |
---|
52 | int *mp; |
---|
53 | int handle, len, memsize, incr; |
---|
54 | |
---|
55 | a_assert(map); |
---|
56 | |
---|
57 | if (*map == NULL) { |
---|
58 | incr = H_INCR; |
---|
59 | memsize = (incr + H_OFFSET) * sizeof(void**); |
---|
60 | #ifdef B_STATS |
---|
61 | if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) { |
---|
62 | #else |
---|
63 | if ((mp = (int*) balloc(B_L, memsize)) == NULL) { |
---|
64 | #endif |
---|
65 | return -1; |
---|
66 | } |
---|
67 | memset(mp, 0, memsize); |
---|
68 | mp[H_LEN] = incr; |
---|
69 | mp[H_USED] = 0; |
---|
70 | *map = (void**) &mp[H_OFFSET]; |
---|
71 | } else { |
---|
72 | mp = &((*(int**)map)[-H_OFFSET]); |
---|
73 | } |
---|
74 | |
---|
75 | len = mp[H_LEN]; |
---|
76 | |
---|
77 | /* |
---|
78 | * Find the first null handle |
---|
79 | */ |
---|
80 | if (mp[H_USED] < mp[H_LEN]) { |
---|
81 | for (handle = 0; handle < len; handle++) { |
---|
82 | if (mp[handle+H_OFFSET] == 0) { |
---|
83 | mp[H_USED]++; |
---|
84 | return handle; |
---|
85 | } |
---|
86 | } |
---|
87 | } else { |
---|
88 | handle = len; |
---|
89 | } |
---|
90 | |
---|
91 | /* |
---|
92 | * No free handle so grow the handle list. Grow list in chunks of H_INCR. |
---|
93 | */ |
---|
94 | len += H_INCR; |
---|
95 | memsize = (len + H_OFFSET) * sizeof(void**); |
---|
96 | if ((mp = (int*) brealloc(B_L, (void*) mp, memsize)) == NULL) { |
---|
97 | return -1; |
---|
98 | } |
---|
99 | *map = (void**) &mp[H_OFFSET]; |
---|
100 | mp[H_LEN] = len; |
---|
101 | memset(&mp[H_OFFSET + len - H_INCR], 0, sizeof(int*) * H_INCR); |
---|
102 | mp[H_USED]++; |
---|
103 | return handle; |
---|
104 | } |
---|
105 | |
---|
106 | /******************************************************************************/ |
---|
107 | /* |
---|
108 | * Free a handle. This function returns the value of the largest |
---|
109 | * handle in use plus 1, to be saved as a max value. |
---|
110 | */ |
---|
111 | |
---|
112 | int hFree(void ***map, int handle) |
---|
113 | { |
---|
114 | int *mp; |
---|
115 | int len; |
---|
116 | |
---|
117 | a_assert(map); |
---|
118 | mp = &((*(int**)map)[-H_OFFSET]); |
---|
119 | a_assert(mp[H_LEN] >= H_INCR); |
---|
120 | |
---|
121 | a_assert(mp[handle + H_OFFSET]); |
---|
122 | a_assert(mp[H_USED]); |
---|
123 | mp[handle + H_OFFSET] = 0; |
---|
124 | if (--(mp[H_USED]) == 0) { |
---|
125 | bfree(B_L, (void*) mp); |
---|
126 | *map = NULL; |
---|
127 | } |
---|
128 | |
---|
129 | /* |
---|
130 | * Find the greatest handle number in use. |
---|
131 | */ |
---|
132 | if (*map == NULL) { |
---|
133 | handle = -1; |
---|
134 | } else { |
---|
135 | len = mp[H_LEN]; |
---|
136 | if (mp[H_USED] < mp[H_LEN]) { |
---|
137 | for (handle = len - 1; handle >= 0; handle--) { |
---|
138 | if (mp[handle + H_OFFSET]) |
---|
139 | break; |
---|
140 | } |
---|
141 | } else { |
---|
142 | handle = len; |
---|
143 | } |
---|
144 | } |
---|
145 | return handle + 1; |
---|
146 | } |
---|
147 | |
---|
148 | /******************************************************************************/ |
---|
149 | /* |
---|
150 | * Allocate an entry in the halloc array. |
---|
151 | */ |
---|
152 | |
---|
153 | #ifdef B_STATS |
---|
154 | int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size) |
---|
155 | #else |
---|
156 | int hAllocEntry(void ***list, int *max, int size) |
---|
157 | #endif |
---|
158 | { |
---|
159 | char_t *cp; |
---|
160 | int id; |
---|
161 | |
---|
162 | a_assert(list); |
---|
163 | a_assert(max); |
---|
164 | |
---|
165 | #ifdef B_STATS |
---|
166 | if ((id = HALLOC(B_ARGS, (void***) list)) < 0) { |
---|
167 | #else |
---|
168 | if ((id = hAlloc((void***) list)) < 0) { |
---|
169 | #endif |
---|
170 | return -1; |
---|
171 | } |
---|
172 | |
---|
173 | if (size > 0) { |
---|
174 | #ifdef B_STATS |
---|
175 | if ((cp = balloc(B_ARGS, size)) == NULL) { |
---|
176 | #else |
---|
177 | if ((cp = balloc(B_L, size)) == NULL) { |
---|
178 | #endif |
---|
179 | hFree(list, id); |
---|
180 | return -1; |
---|
181 | } |
---|
182 | a_assert(cp); |
---|
183 | memset(cp, 0, size); |
---|
184 | |
---|
185 | (*list)[id] = (void*) cp; |
---|
186 | } |
---|
187 | |
---|
188 | if (id >= *max) { |
---|
189 | *max = id + 1; |
---|
190 | } |
---|
191 | return id; |
---|
192 | } |
---|
193 | |
---|
194 | /******************************************************************************/ |
---|
195 | |
---|