Browse Source

[linux] Add umalloc

Add umalloc API.

Signed-off-by: Piotr Jaroszyński <p.jaroszynski@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Piotr Jaroszyński 14 years ago
parent
commit
6ec1c509e4

+ 1
- 0
src/config/defaults/linux.h View File

@@ -10,6 +10,7 @@
10 10
 #define CONSOLE_LINUX
11 11
 #define TIMER_LINUX
12 12
 #define UACCESS_LINUX
13
+#define UMALLOC_LINUX
13 14
 
14 15
 #define IMAGE_SCRIPT
15 16
 

+ 18
- 0
src/include/ipxe/linux/linux_umalloc.h View File

@@ -0,0 +1,18 @@
1
+#ifndef _IPXE_LINUX_UMALLOC_H
2
+#define _IPXE_LINUX_UMALLOC_H
3
+
4
+FILE_LICENCE(GPL2_OR_LATER);
5
+
6
+/** @file
7
+ *
8
+ * iPXE user memory allocation API for linux
9
+ *
10
+ */
11
+
12
+#ifdef UMALLOC_LINUX
13
+#define UMALLOC_PREFIX_linux
14
+#else
15
+#define UMALLOC_PREFIX_linux __linux_
16
+#endif
17
+
18
+#endif /* _IPXE_LINUX_UMALLOC_H */

+ 1
- 0
src/include/ipxe/umalloc.h View File

@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
26 26
 
27 27
 /* Include all architecture-independent I/O API headers */
28 28
 #include <ipxe/efi/efi_umalloc.h>
29
+#include <ipxe/linux/linux_umalloc.h>
29 30
 
30 31
 /* Include all architecture-dependent I/O API headers */
31 32
 #include <bits/umalloc.h>

+ 126
- 0
src/interface/linux/linux_umalloc.c View File

@@ -0,0 +1,126 @@
1
+/*
2
+ * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
+ */
18
+
19
+FILE_LICENCE(GPL2_OR_LATER);
20
+
21
+/** @file
22
+ *
23
+ * iPXE user memory allocation API for linux
24
+ *
25
+ */
26
+
27
+#include <assert.h>
28
+#include <ipxe/umalloc.h>
29
+
30
+#include <linux_api.h>
31
+
32
+/** Special address returned for empty allocations */
33
+#define NOWHERE ((void *)-1)
34
+
35
+/** Poison to make the metadata more unique */
36
+#define POISON 0xa5a5a5a5
37
+#define min(a,b) (((a)<(b))?(a):(b))
38
+
39
+/** Metadata stored at the beginning of all allocations */
40
+struct metadata
41
+{
42
+	unsigned poison;
43
+	size_t size;
44
+};
45
+
46
+#define SIZE_MD (sizeof(struct metadata))
47
+
48
+/** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */
49
+static void * linux_realloc(void *ptr, size_t size)
50
+{
51
+	struct metadata md = {0, 0};
52
+	struct metadata * mdptr = NULL;
53
+
54
+	DBG2("linux_realloc(%p, %zd)\n", ptr, size);
55
+
56
+	/* Check whether we have a valid pointer */
57
+	if (ptr != NULL && ptr != NOWHERE) {
58
+		mdptr = ptr - SIZE_MD;
59
+		md = *mdptr;
60
+
61
+		/* Check for poison in the metadata */
62
+		if (md.poison != POISON) {
63
+			DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON);
64
+			return NULL;
65
+		}
66
+	} else {
67
+		/* Handle NOWHERE as NULL */
68
+		ptr = NULL;
69
+	}
70
+
71
+	/*
72
+	 * At this point, ptr is either NULL or pointing to a region allocated by us.
73
+	 * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL.
74
+	 */
75
+
76
+	/* Handle deallocation or allocation of size 0 */
77
+	if (size == 0) {
78
+		if (mdptr) {
79
+			if (linux_munmap(mdptr, md.size))
80
+				DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno));
81
+		}
82
+		return NOWHERE;
83
+	}
84
+
85
+	if (ptr) {
86
+		/* ptr is pointing to an already allocated memory, mremap() it with new size */
87
+		mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE);
88
+		if (mdptr == MAP_FAILED) {
89
+			DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno));
90
+			return NULL;
91
+		}
92
+
93
+		ptr = ((void *)mdptr) + SIZE_MD;
94
+	} else {
95
+		/* allocate new memory with mmap() */
96
+		mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
97
+		if (mdptr == MAP_FAILED) {
98
+			DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno));
99
+			return NULL;
100
+		}
101
+		ptr = ((void *)mdptr) + SIZE_MD;
102
+	}
103
+
104
+	/* Update the metadata */
105
+	mdptr->poison = POISON;
106
+	mdptr->size = size;
107
+
108
+	return ptr;
109
+}
110
+
111
+/**
112
+ * Reallocate external memory
113
+ *
114
+ * @v old_ptr		Memory previously allocated by umalloc(), or UNULL
115
+ * @v new_size		Requested size
116
+ * @ret new_ptr		Allocated memory, or UNULL
117
+ *
118
+ * Calling realloc() with a new size of zero is a valid way to free a
119
+ * memory block.
120
+ */
121
+static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size)
122
+{
123
+	return (userptr_t)linux_realloc((void *)old_ptr, new_size);
124
+}
125
+
126
+PROVIDE_UMALLOC(linux, urealloc, linux_urealloc);

Loading…
Cancel
Save