1 #include "config.h"
2 #include <string.h>
3 #include <orbit/orbit.h>
4 #include "orb-core-private.h"
5 
6 /***
7     The argument {mem} is a chuck of memory described by {tc}, and its
8     contents is freed, but {mem} itself is not freed. That is, if {mem}
9     contains anything interesting (objrefs, pointers), they are freed.
10     A pointer to the end of {mem} is returned. This should always be
11     the same as {mem + ORBit_gather_alloc_info(tc)}. Also, any pointers
12     within {mem} are zeroed; thus it should be safe to call this
13     function multiple times on the same chunk of memory.
14 
15     This function is a modified version of ORBit_free_via_TypeCode().
16     Aside from the arguments, the bigest difference is that this
17     does not free the {tc} which is passed in. The old style led
18     to a lot of pointless dups, and also failed miserably when
19     arrays of things were allocated.
20 **/
21 static gpointer
ORBit_freekids_via_TypeCode_T(gpointer mem,CORBA_TypeCode tc)22 ORBit_freekids_via_TypeCode_T (gpointer       mem,
23 			       CORBA_TypeCode tc)
24 {
25 	int i;
26 	guchar *retval = NULL;
27 	CORBA_TypeCode subtc;
28 
29 /*  g_warning ("Freeing via tc '%s' at %p",
30     ORBit_tk_to_name (tc->kind), mem);*/
31 
32 	switch (tc->kind) {
33 	case CORBA_tk_any: {
34 		CORBA_any *pval = mem;
35 		if (pval->_release)
36 			ORBit_free_T (pval->_value);
37 		pval->_value = NULL;
38 		ORBit_RootObject_release_T (pval->_type);
39 		pval->_type = NULL;
40 		retval = (guchar *) (pval + 1);
41 		break;
42 	}
43 	case CORBA_tk_TypeCode:
44 	case CORBA_tk_objref: {
45 		CORBA_Object *pval = mem;
46 
47 		ORBit_RootObject_release_T (*pval);
48 		*pval = NULL;
49 		retval = ((guchar *)mem) + sizeof (*pval);
50 		break;
51 	}
52 	case CORBA_tk_Principal: {
53 		CORBA_Principal *pval = mem;
54 		if (pval->_release)
55 			ORBit_free_T (pval->_buffer);
56 		pval->_buffer = NULL;
57 		retval = (guchar *)(pval + 1);
58 		break;
59 	}
60 	case CORBA_tk_except:
61 	case CORBA_tk_struct:
62 		mem = ALIGN_ADDRESS (mem, tc->c_align);
63 		for (i = 0; i < tc->sub_parts; i++) {
64 			subtc = tc->subtypes [i];
65 			mem = ALIGN_ADDRESS (mem, subtc->c_align);
66 			mem = ORBit_freekids_via_TypeCode_T (mem, subtc);
67 		}
68 		mem = ALIGN_ADDRESS (mem, tc->c_align);
69 		retval = mem;
70 		break;
71 	case CORBA_tk_union: {
72 		int sz = 0;
73 		int al = 1;
74 		gconstpointer cmem;
75 
76 		cmem = ALIGN_ADDRESS (mem, MAX (tc->discriminator->c_align,
77 						tc->c_align));
78 		subtc = ORBit_get_union_tag (tc, &cmem, TRUE);
79 		for (i = 0; i < tc->sub_parts; i++) {
80 			al = MAX (al, tc->subtypes [i]->c_align);
81 			sz = MAX (sz, ORBit_gather_alloc_info (tc->subtypes [i]));
82 		}
83 		mem = ALIGN_ADDRESS (cmem, al);
84 		ORBit_freekids_via_TypeCode_T (mem, subtc);
85 		/* the end of the body (subtc) may not be the
86 		 * same as the end of the union */
87 		retval = ((guchar *)mem) + sz;
88 		break;
89 	}
90 	case CORBA_tk_wstring:
91 	case CORBA_tk_string: {
92 		CORBA_char **pval = mem;
93 		ORBit_free_T (*pval);
94 		*pval = NULL;
95 		retval = (guchar *)mem + sizeof (*pval);
96 		break;
97 	}
98 	case CORBA_tk_sequence: {
99 		CORBA_sequence_CORBA_octet *pval = mem;
100 		if (pval->_release)
101 			ORBit_free_T (pval->_buffer);
102 		pval->_buffer = NULL;
103 		retval = (guchar *)mem + sizeof(*pval);
104 		break;
105 	}
106 	case CORBA_tk_array:
107 		for (i = 0; i < tc->length; i++)
108 			mem = ORBit_freekids_via_TypeCode_T(
109 				mem, tc->subtypes[0]);
110 		retval = mem;
111 		break;
112 	case CORBA_tk_alias:
113 		retval = ORBit_freekids_via_TypeCode_T (
114 			mem, tc->subtypes[0]);
115 		break;
116 	default: {
117 		gulong length;
118 		length = ORBit_gather_alloc_info (tc);
119 		retval = (guchar *) ALIGN_ADDRESS (mem, tc->c_align) + length;
120 		break;
121 	}
122 	}
123 	return retval;
124 }
125 
126 gpointer
ORBit_freekids_via_TypeCode(CORBA_TypeCode tc,gpointer mem)127 ORBit_freekids_via_TypeCode (CORBA_TypeCode tc, gpointer mem)
128 {
129 	gpointer ret;
130 
131 	LINK_MUTEX_LOCK   (ORBit_RootObject_lifecycle_lock);
132 
133 	ret = ORBit_freekids_via_TypeCode_T (mem, tc);
134 
135 	LINK_MUTEX_UNLOCK (ORBit_RootObject_lifecycle_lock);
136 
137 	return ret;
138 }
139 
140 void
CORBA_free(gpointer mem)141 CORBA_free (gpointer mem)
142 {
143 	ORBit_free (mem);
144 }
145 
146 #define SHORT_PREFIX_LEN (MAX (sizeof (ORBitMemHow), \
147 			       ORBIT_ALIGNOF_CORBA_LONG_DOUBLE))
148 #define LONG_PREFIX_LEN  (sizeof (CORBA_long_double) > sizeof (ORBit_MemPrefix) ? \
149 			  ORBIT_ALIGNOF_CORBA_LONG_DOUBLE : \
150 			  MAX (sizeof (ORBit_MemPrefix), \
151 			       sizeof (CORBA_long_double) + \
152 			       ORBIT_ALIGNOF_CORBA_LONG_DOUBLE))
153 
154 void
ORBit_free_T(gpointer mem)155 ORBit_free_T (gpointer mem)
156 {
157 	int               i;
158 	guchar           *x;
159 	CORBA_TypeCode    tc;
160 	ORBitMemHow       how;
161 	ORBit_MemPrefix  *prefix;
162 	ORBit_Mem_free_fn free_fn;
163 
164 	if (!mem)
165 		return;
166 
167 	if ((gulong)mem & 0x1) {
168 		g_free ((guchar *)mem - 1);
169 		return;
170 	}
171 
172 	how = *(((ORBitMemHow *) mem) - 1);
173 
174 	switch (ORBIT_MEMHOW_HOW (how)) {
175 	case ORBIT_MEMHOW_TYPECODE:
176 		prefix = (ORBit_MemPrefix *)
177 			((guchar *) mem - LONG_PREFIX_LEN);
178 
179 		free_fn = (ORBit_Mem_free_fn)
180 			ORBit_freekids_via_TypeCode_T;
181 		tc      = prefix->u.tc;
182 		break;
183 
184 	case ORBIT_MEMHOW_FREEFNC:
185 		prefix = (ORBit_MemPrefix *)
186 			((guchar *) mem - LONG_PREFIX_LEN);
187 
188 		free_fn = prefix->u.free_fn;
189 		tc      = NULL;
190 		break;
191 	case ORBIT_MEMHOW_SIMPLE:
192 		g_free ((guchar *)mem - SHORT_PREFIX_LEN);
193 		return;
194 	case ORBIT_MEMHOW_NONE:
195 	default:
196 		return;
197 	}
198 
199 	how = ORBIT_MEMHOW_ELEMENTS (how);
200 
201 	for (i = 0, x = mem; i < how; i++)
202 		x = free_fn (x, tc);
203 
204 	g_free (prefix);
205 
206 	if (tc)
207 		ORBit_RootObject_release_T (tc);
208 }
209 
210 void
ORBit_free(gpointer mem)211 ORBit_free (gpointer mem)
212 {
213 	if (!mem)
214 		return;
215 
216 	LINK_MUTEX_LOCK   (ORBit_RootObject_lifecycle_lock);
217 
218 	ORBit_free_T (mem);
219 
220 	LINK_MUTEX_UNLOCK (ORBit_RootObject_lifecycle_lock);
221 }
222 
223 CORBA_char *
ORBit_alloc_string(size_t string_length)224 ORBit_alloc_string (size_t string_length)
225 {
226 	guchar *mem;
227 
228 	mem = g_malloc (string_length + 1);
229 
230 	return (CORBA_char *)(mem + 1);
231 }
232 
233 gpointer
ORBit_alloc_simple(size_t block_size)234 ORBit_alloc_simple (size_t block_size)
235 {
236 	guchar *mem, *prefix;
237 
238 	if (!block_size)
239 		return NULL;
240 
241 	prefix = g_malloc (SHORT_PREFIX_LEN + block_size);
242 
243 	mem = (guchar *) prefix + SHORT_PREFIX_LEN;
244 
245 	*((ORBitMemHow *)mem - 1) = ORBIT_MEMHOW_SIMPLE;
246 
247 	return mem;
248 }
249 
250 gpointer
ORBit_alloc_with_free_fn(size_t element_size,guint num_elements,ORBit_Mem_free_fn free_fn)251 ORBit_alloc_with_free_fn (size_t            element_size,
252 			  guint             num_elements,
253 			  ORBit_Mem_free_fn free_fn)
254 {
255 	guchar *mem;
256 	ORBit_MemPrefix *prefix;
257 
258 	if (!num_elements)
259 		return NULL;
260 
261 	prefix = g_malloc (LONG_PREFIX_LEN +
262 			   element_size * num_elements);
263 	prefix->u.free_fn = free_fn;
264 
265 	mem = (guchar *) prefix + LONG_PREFIX_LEN;
266 
267 	*((ORBitMemHow *)mem - 1) = ORBIT_MEMHOW_MAKE (
268 		ORBIT_MEMHOW_FREEFNC, num_elements);
269 
270 	return mem;
271 }
272 
273 gpointer
ORBit_alloc_tcval(CORBA_TypeCode tc,guint num_elements)274 ORBit_alloc_tcval (CORBA_TypeCode tc,
275 		   guint          num_elements)
276 {
277 	guchar *mem;
278 	guint   element_size;
279 	ORBit_MemPrefix *prefix;
280 
281 	if (!num_elements)
282 		return NULL;
283 
284 	if (!(element_size = ORBit_gather_alloc_info (tc)))
285 		return NULL;
286 
287 	prefix = g_malloc0 (LONG_PREFIX_LEN +
288 			    element_size * num_elements);
289 
290 	prefix->u.tc = ORBit_RootObject_duplicate (tc);
291 
292 	mem = (guchar *)prefix + LONG_PREFIX_LEN;
293 
294 	*((ORBitMemHow *)mem - 1) = ORBIT_MEMHOW_MAKE (
295 		ORBIT_MEMHOW_TYPECODE, num_elements);
296 
297 	return mem;
298 }
299 
300 gpointer
ORBit_realloc_tcval(gpointer old,CORBA_TypeCode tc,guint old_num_elements,guint num_elements)301 ORBit_realloc_tcval (gpointer       old,
302 		     CORBA_TypeCode tc,
303 		     guint          old_num_elements,
304 		     guint          num_elements)
305 {
306 	guint element_size;
307 	ORBit_MemPrefix *prefix;
308 	guchar *mem;
309 
310 	g_assert (num_elements > old_num_elements);
311 
312 	if (!num_elements)
313 		return NULL;
314 
315 	if (!old_num_elements && !old)
316 		return ORBit_alloc_tcval (tc, num_elements);
317 
318 	if (!(element_size = ORBit_gather_alloc_info (tc)))
319 		return NULL;
320 
321 	prefix = g_realloc ((guchar *) old - LONG_PREFIX_LEN,
322 			    LONG_PREFIX_LEN +
323 			    element_size * num_elements);
324 
325 	/* Initialize as yet unused memory to 'safe' values */
326 	memset ((guchar *) prefix + LONG_PREFIX_LEN +
327 		old_num_elements * element_size,
328 		0, (num_elements - old_num_elements) * element_size);
329 
330 	mem = (guchar *)prefix + LONG_PREFIX_LEN;
331 
332 	*((ORBitMemHow *)mem - 1) = ORBIT_MEMHOW_MAKE (
333 		ORBIT_MEMHOW_TYPECODE, num_elements);
334 
335 	return mem;
336 }
337 
338 CORBA_TypeCode
ORBit_alloc_get_tcval(gpointer mem)339 ORBit_alloc_get_tcval (gpointer mem)
340 {
341 	ORBitMemHow how;
342 	ORBit_MemPrefix *prefix;
343 
344 	if (!mem)
345 		return NULL;
346 
347 	if ((gulong)mem & 0x1)
348 		return TC_CORBA_string;
349 
350 	how = *(((ORBitMemHow *) mem) - 1);
351 
352 	if (ORBIT_MEMHOW_HOW (how) == ORBIT_MEMHOW_TYPECODE) {
353 		prefix = (ORBit_MemPrefix *)
354 		  ((guchar *) mem - LONG_PREFIX_LEN);
355 
356 		return ORBit_RootObject_duplicate (prefix->u.tc);
357 	} else
358 		g_error ("Can't determine type of %p (%u)", mem, how);
359 
360 	return NULL;
361 }
362 
363 gpointer
ORBit_alloc_by_tc(CORBA_TypeCode tc)364 ORBit_alloc_by_tc (CORBA_TypeCode tc)
365 {
366 	guchar *mem;
367 	guint   size;
368 	ORBit_MemPrefix *prefix;
369 
370 	if (!(size = ORBit_gather_alloc_info (tc)))
371 		return NULL;
372 
373 	prefix = g_malloc0 (LONG_PREFIX_LEN + size);
374 
375 	prefix->u.tc = ORBit_RootObject_duplicate (tc);
376 
377 	mem = (guchar *)prefix + LONG_PREFIX_LEN;
378 
379 	*((ORBitMemHow *)mem - 1) = ORBIT_MEMHOW_MAKE (
380 		ORBIT_MEMHOW_TYPECODE, 1);
381 
382 	return mem;
383 }
384