1/******************************************************************************
2 *
3 * Module Name: utalloc - local memory allocation routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2007, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <acpi/acdebug.h>
46
47#define _COMPONENT          ACPI_UTILITIES
48ACPI_MODULE_NAME("utalloc")
49
50/*******************************************************************************
51 *
52 * FUNCTION:    acpi_ut_create_caches
53 *
54 * PARAMETERS:  None
55 *
56 * RETURN:      Status
57 *
58 * DESCRIPTION: Create all local caches
59 *
60 ******************************************************************************/
61acpi_status acpi_ut_create_caches(void)
62{
63	acpi_status status;
64
65	/* Object Caches, for frequently used objects */
66
67	status =
68	    acpi_os_create_cache("Acpi-Namespace",
69				 sizeof(struct acpi_namespace_node),
70				 ACPI_MAX_NAMESPACE_CACHE_DEPTH,
71				 &acpi_gbl_namespace_cache);
72	if (ACPI_FAILURE(status)) {
73		return (status);
74	}
75
76	status =
77	    acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state),
78				 ACPI_MAX_STATE_CACHE_DEPTH,
79				 &acpi_gbl_state_cache);
80	if (ACPI_FAILURE(status)) {
81		return (status);
82	}
83
84	status =
85	    acpi_os_create_cache("Acpi-Parse",
86				 sizeof(struct acpi_parse_obj_common),
87				 ACPI_MAX_PARSE_CACHE_DEPTH,
88				 &acpi_gbl_ps_node_cache);
89	if (ACPI_FAILURE(status)) {
90		return (status);
91	}
92
93	status =
94	    acpi_os_create_cache("Acpi-ParseExt",
95				 sizeof(struct acpi_parse_obj_named),
96				 ACPI_MAX_EXTPARSE_CACHE_DEPTH,
97				 &acpi_gbl_ps_node_ext_cache);
98	if (ACPI_FAILURE(status)) {
99		return (status);
100	}
101
102	status =
103	    acpi_os_create_cache("Acpi-Operand",
104				 sizeof(union acpi_operand_object),
105				 ACPI_MAX_OBJECT_CACHE_DEPTH,
106				 &acpi_gbl_operand_cache);
107	if (ACPI_FAILURE(status)) {
108		return (status);
109	}
110#ifdef ACPI_DBG_TRACK_ALLOCATIONS
111
112	/* Memory allocation lists */
113
114	status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list);
115	if (ACPI_FAILURE(status)) {
116		return (status);
117	}
118
119	status =
120	    acpi_ut_create_list("Acpi-Namespace",
121				sizeof(struct acpi_namespace_node),
122				&acpi_gbl_ns_node_list);
123	if (ACPI_FAILURE(status)) {
124		return (status);
125	}
126#endif
127
128	return (AE_OK);
129}
130
131/*******************************************************************************
132 *
133 * FUNCTION:    acpi_ut_delete_caches
134 *
135 * PARAMETERS:  None
136 *
137 * RETURN:      Status
138 *
139 * DESCRIPTION: Purge and delete all local caches
140 *
141 ******************************************************************************/
142
143acpi_status acpi_ut_delete_caches(void)
144{
145#ifdef ACPI_DBG_TRACK_ALLOCATIONS
146	char buffer[7];
147
148	if (acpi_gbl_display_final_mem_stats) {
149		ACPI_STRCPY(buffer, "MEMORY");
150		acpi_db_display_statistics(buffer);
151	}
152#endif
153
154	(void)acpi_os_delete_cache(acpi_gbl_namespace_cache);
155	acpi_gbl_namespace_cache = NULL;
156
157	(void)acpi_os_delete_cache(acpi_gbl_state_cache);
158	acpi_gbl_state_cache = NULL;
159
160	(void)acpi_os_delete_cache(acpi_gbl_operand_cache);
161	acpi_gbl_operand_cache = NULL;
162
163	(void)acpi_os_delete_cache(acpi_gbl_ps_node_cache);
164	acpi_gbl_ps_node_cache = NULL;
165
166	(void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
167	acpi_gbl_ps_node_ext_cache = NULL;
168
169#ifdef ACPI_DBG_TRACK_ALLOCATIONS
170
171	/* Debug only - display leftover memory allocation, if any */
172
173	acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
174
175	/* Free memory lists */
176
177	ACPI_FREE(acpi_gbl_global_list);
178	acpi_gbl_global_list = NULL;
179
180	ACPI_FREE(acpi_gbl_ns_node_list);
181	acpi_gbl_ns_node_list = NULL;
182#endif
183
184	return (AE_OK);
185}
186
187/*******************************************************************************
188 *
189 * FUNCTION:    acpi_ut_validate_buffer
190 *
191 * PARAMETERS:  Buffer              - Buffer descriptor to be validated
192 *
193 * RETURN:      Status
194 *
195 * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer
196 *
197 ******************************************************************************/
198
199acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
200{
201
202	/* Obviously, the structure pointer must be valid */
203
204	if (!buffer) {
205		return (AE_BAD_PARAMETER);
206	}
207
208	/* Special semantics for the length */
209
210	if ((buffer->length == ACPI_NO_BUFFER) ||
211	    (buffer->length == ACPI_ALLOCATE_BUFFER) ||
212	    (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) {
213		return (AE_OK);
214	}
215
216	/* Length is valid, the buffer pointer must be also */
217
218	if (!buffer->pointer) {
219		return (AE_BAD_PARAMETER);
220	}
221
222	return (AE_OK);
223}
224
225/*******************************************************************************
226 *
227 * FUNCTION:    acpi_ut_initialize_buffer
228 *
229 * PARAMETERS:  Buffer              - Buffer to be validated
230 *              required_length     - Length needed
231 *
232 * RETURN:      Status
233 *
234 * DESCRIPTION: Validate that the buffer is of the required length or
235 *              allocate a new buffer.  Returned buffer is always zeroed.
236 *
237 ******************************************************************************/
238
239acpi_status
240acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
241			  acpi_size required_length)
242{
243	acpi_status status = AE_OK;
244
245	switch (buffer->length) {
246	case ACPI_NO_BUFFER:
247
248		/* Set the exception and returned the required length */
249
250		status = AE_BUFFER_OVERFLOW;
251		break;
252
253	case ACPI_ALLOCATE_BUFFER:
254
255		/* Allocate a new buffer */
256
257		buffer->pointer = acpi_os_allocate(required_length);
258		if (!buffer->pointer) {
259			return (AE_NO_MEMORY);
260		}
261
262		/* Clear the buffer */
263
264		ACPI_MEMSET(buffer->pointer, 0, required_length);
265		break;
266
267	case ACPI_ALLOCATE_LOCAL_BUFFER:
268
269		/* Allocate a new buffer with local interface to allow tracking */
270
271		buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length);
272		if (!buffer->pointer) {
273			return (AE_NO_MEMORY);
274		}
275		break;
276
277	default:
278
279		/* Existing buffer: Validate the size of the buffer */
280
281		if (buffer->length < required_length) {
282			status = AE_BUFFER_OVERFLOW;
283			break;
284		}
285
286		/* Clear the buffer */
287
288		ACPI_MEMSET(buffer->pointer, 0, required_length);
289		break;
290	}
291
292	buffer->length = required_length;
293	return (status);
294}
295
296#ifdef NOT_USED_BY_LINUX
297/*******************************************************************************
298 *
299 * FUNCTION:    acpi_ut_allocate
300 *
301 * PARAMETERS:  Size                - Size of the allocation
302 *              Component           - Component type of caller
303 *              Module              - Source file name of caller
304 *              Line                - Line number of caller
305 *
306 * RETURN:      Address of the allocated memory on success, NULL on failure.
307 *
308 * DESCRIPTION: Subsystem equivalent of malloc.
309 *
310 ******************************************************************************/
311
312void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line)
313{
314	void *allocation;
315
316	ACPI_FUNCTION_TRACE_U32(ut_allocate, size);
317
318	/* Check for an inadvertent size of zero bytes */
319
320	if (!size) {
321		ACPI_WARNING((module, line,
322			      "Attempt to allocate zero bytes, allocating 1 byte"));
323		size = 1;
324	}
325
326	allocation = acpi_os_allocate(size);
327	if (!allocation) {
328
329		/* Report allocation error */
330
331		ACPI_WARNING((module, line,
332			      "Could not allocate size %X", (u32) size));
333
334		return_PTR(NULL);
335	}
336
337	return_PTR(allocation);
338}
339
340/*******************************************************************************
341 *
342 * FUNCTION:    acpi_ut_allocate_zeroed
343 *
344 * PARAMETERS:  Size                - Size of the allocation
345 *              Component           - Component type of caller
346 *              Module              - Source file name of caller
347 *              Line                - Line number of caller
348 *
349 * RETURN:      Address of the allocated memory on success, NULL on failure.
350 *
351 * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
352 *
353 ******************************************************************************/
354
355void *acpi_ut_allocate_zeroed(acpi_size size,
356			      u32 component, char *module, u32 line)
357{
358	void *allocation;
359
360	ACPI_FUNCTION_ENTRY();
361
362	allocation = acpi_ut_allocate(size, component, module, line);
363	if (allocation) {
364
365		/* Clear the memory block */
366
367		ACPI_MEMSET(allocation, 0, size);
368	}
369
370	return (allocation);
371}
372#endif
373