ソースを参照

First version of an external memory allocator (not tested)

tags/v0.9.3
Michael Brown 18年前
コミット
45ec9c907e
2個のファイルの変更176行の追加0行の削除
  1. 159
    0
      src/arch/i386/core/emalloc.c
  2. 17
    0
      src/include/gpxe/emalloc.h

+ 159
- 0
src/arch/i386/core/emalloc.c ファイルの表示

@@ -0,0 +1,159 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/**
20
+ * @file
21
+ *
22
+ * External memory allocation
23
+ *
24
+ */
25
+
26
+#include <gpxe/uaccess.h>
27
+#include <gpxe/hidemem.h>
28
+#include <gpxe/emalloc.h>
29
+
30
+/** Equivalent of NOWHERE for user pointers */
31
+#define UNOWHERE ( ~UNULL )
32
+
33
+/** Top of allocatable memory */
34
+#define TOP ( virt_to_user ( NULL ) )
35
+
36
+/** An external memory block */
37
+struct external_memory {
38
+	/** Size of this memory block (excluding this header) */
39
+	size_t size;
40
+	/** Block is currently in use */
41
+	int used;
42
+};
43
+
44
+/** Current lowest allocated block
45
+ *
46
+ * A value of UNULL indicates that no blocks are currently allocated.
47
+ */
48
+userptr_t bottom = UNULL;
49
+
50
+/**
51
+ * Collect free blocks
52
+ *
53
+ */
54
+static void ecollect_free ( void ) {
55
+	struct external_memory extmem;
56
+
57
+	/* Walk the free list and collect empty blocks */
58
+	while ( bottom != TOP ) {
59
+		copy_from_user ( &extmem, bottom, -sizeof ( extmem ),
60
+				 sizeof ( extmem ) );
61
+		if ( extmem.used )
62
+			break;
63
+		DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
64
+		      user_to_phys ( bottom, extmem.size ) );
65
+		bottom = userptr_add ( bottom,
66
+				       ( extmem.size + sizeof ( extmem ) ) );
67
+	}
68
+}
69
+
70
+/**
71
+ * Reallocate external memory
72
+ *
73
+ * @v old_ptr		Memory previously allocated by emalloc(), or UNULL
74
+ * @v new_size		Requested size
75
+ * @ret new_ptr		Allocated memory, or UNULL
76
+ *
77
+ * Calling realloc() with a new size of zero is a valid way to free a
78
+ * memory block.
79
+ */
80
+userptr_t erealloc ( userptr_t ptr, size_t new_size ) {
81
+	struct external_memory extmem;
82
+	userptr_t new = ptr;
83
+
84
+	/* Initialise external memory allocator if necessary */
85
+	if ( ! bottom  )
86
+		bottom = TOP;
87
+
88
+	/* Get block properties into extmem */
89
+	if ( ptr && ( ptr != UNOWHERE ) ) {
90
+		/* Determine old size */
91
+		copy_from_user ( &extmem, ptr, -sizeof ( extmem ),
92
+				 sizeof ( extmem ) );
93
+	} else {
94
+		/* Create a zero-length block */
95
+		ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
96
+		DBGC ( "EXTMEM allocating [%lx,%lx)\n",
97
+		       user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
98
+		extmem.size = 0;
99
+	}
100
+	extmem.used = ( new_size > 0 );
101
+
102
+	/* Expand/shrink block if possible */
103
+	if ( ptr == bottom ) {
104
+		/* Update block */
105
+		new = userptr_add ( ptr, - ( new_size - extmem.size ) );
106
+		DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n",
107
+		      user_to_phys ( ptr, 0 ),
108
+		      user_to_phys ( ptr, extmem.size ),
109
+		      user_to_phys ( new, 0 ),
110
+		      user_to_phys ( new, new_size ));
111
+		memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
112
+						 extmem.size : new_size ) );
113
+		extmem.size = new_size;
114
+		bottom = new;
115
+	} else {
116
+		/* Cannot expand; can only pretend to shrink */
117
+		if ( new_size > extmem.size ) {
118
+			/* Refuse to expand */
119
+			DBG ( "EXTMEM cannot expand [%lx,%lx)\n",
120
+			      user_to_phys ( ptr, 0 ),
121
+			      user_to_phys ( ptr, extmem.size ) );
122
+			return UNULL;
123
+		}
124
+	}
125
+
126
+	/* Write back block properties */
127
+	copy_to_user ( new, -sizeof ( extmem ), &extmem,
128
+		       sizeof ( extmem ) );
129
+
130
+	/* Collect any free blocks and update hidden memory region */
131
+	ecollect_free();
132
+	hide_region ( EXTMEM, user_to_phys ( bottom, -sizeof ( extmem ) ),
133
+		      user_to_phys ( TOP, 0 ) );
134
+
135
+	return ( new_size ? new : UNOWHERE );
136
+}
137
+
138
+/**
139
+ * Allocate external memory
140
+ *
141
+ * @v size		Requested size
142
+ * @ret ptr		Memory, or UNULL
143
+ *
144
+ * Memory is guaranteed to be aligned to a page boundary.
145
+ */
146
+userptr_t emalloc ( size_t size ) {
147
+	return erealloc ( UNULL, size );
148
+}
149
+
150
+/**
151
+ * Free external memory
152
+ *
153
+ * @v ptr		Memory allocated by emalloc(), or UNULL
154
+ *
155
+ * If @c ptr is UNULL, no action is taken.
156
+ */
157
+void efree ( userptr_t ptr ) {
158
+	erealloc ( ptr, 0 );
159
+}

+ 17
- 0
src/include/gpxe/emalloc.h ファイルの表示

@@ -0,0 +1,17 @@
1
+#ifndef _GPXE_EMALLOC_H
2
+#define _GPXE_EMALLOC_H
3
+
4
+/**
5
+ * @file
6
+ *
7
+ * External memory allocation
8
+ *
9
+ */
10
+
11
+#include <gpxe/uaccess.h>
12
+
13
+extern userptr_t emalloc ( size_t size );
14
+extern userptr_t erealloc ( userptr_t ptr, size_t new_size );
15
+extern void efree ( userptr_t ptr );
16
+
17
+#endif /* _GPXE_EMALLOC_H */

読み込み中…
キャンセル
保存