Browse Source

Allow data blocks to be less than sizeof ( struct buffer_free_block ) in

size.  (The restriction on the size of free blocks remains.)
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
33dbdda28e
2 changed files with 67 additions and 111 deletions
  1. 64
    110
      src/core/buffer.c
  2. 3
    1
      src/include/buffer.h

+ 64
- 110
src/core/buffer.c View File

@@ -66,88 +66,33 @@ void init_buffer ( struct buffer *buffer ) {
66 66
 	DBG ( "BUFFER [%x,%x) initialised\n", buffer->start, buffer->end );
67 67
 }
68 68
 
69
-/**
70
- * Split a free block.
71
- *
72
- * @v desc		A descriptor for the free block
73
- * @v block		Start address of the block
74
- * @v split		Address at which to split the block
75
- * @ret None		-
76
- * @err None		-
77
- *
78
- * Split a free block into two separate free blocks.  If the split
79
- * point lies outside the block, no action is taken; this is not an
80
- * error.
81
- *
82
- * @b NOTE: It is the reponsibility of the caller to ensure that there
83
- * is enough room in each of the two portions for a free block
84
- * descriptor (a @c struct @c buffer_free_block, except in the case of
85
- * a tail block which requires only a one byte descriptor).  If the
86
- * caller fails to do this, data corruption will occur.
87
- *
88
- * In practice, this means that the granularity at which blocks are
89
- * split must be at least @c sizeof(struct @c buffer_free_block).
90
- *
91
- */
92
-static void split_free_block ( struct buffer_free_block *desc,
93
-			       physaddr_t block, physaddr_t split ) {
94
-	/* If split point is before start of block, do nothing */
95
-	if ( split <= block )
96
-		return;
97
-
98
-	/* If split point is after end of block, do nothing */
99
-	if ( split >= desc->end )
100
-		return;
101
-
102
-	DBG ( "BUFFER splitting [%x,%x) -> [%x,%x) [%x,%x)\n",
103
-	      block, desc->end, block, split, split, desc->end );
104
-
105
-	/* Create descriptor for new free block */
106
-	copy_to_phys ( split, &desc->tail, sizeof ( desc->tail ) );
107
-	if ( ! desc->tail )
108
-		copy_to_phys ( split, desc, sizeof ( *desc ) );
109
-
110
-	/* Update descriptor for old free block */
111
-	desc->tail = 0;
112
-	desc->next_free = split;
113
-	desc->end = split;
114
-	copy_to_phys ( block, desc, sizeof ( *desc ) );
115
-}
69
+static inline int next_free_block ( struct buffer_free_block *block,
70
+				    struct buffer *buffer ) {
71
+	/* Move to next block */
72
+	block->start = block->next;
116 73
 
117
-/**
118
- * Mark a free block as used.
119
- *
120
- * @v buffer		The buffer containing the block
121
- * @v desc		A descriptor for the free block
122
- * @v prev_block	Address of the previous block
123
- * @ret None		-
124
- * @err None		-
125
- *
126
- * Marks a free block as used, i.e. removes it from the free list.
127
- *
128
- */
129
-static inline void unfree_block ( struct buffer *buffer,
130
-				  struct buffer_free_block *desc,
131
-				  physaddr_t prev_block ) {
132
-	struct buffer_free_block prev_desc;
133
-	
134
-	/* If this is the first block, just update buffer->fill */
135
-	if ( ! prev_block ) {
136
-		DBG ( "BUFFER marking [%x,%x) as used\n",
137
-		      buffer->start + buffer->fill, desc->end );
138
-		buffer->fill = desc->next_free - buffer->start;
139
-		return;
140
-	}
74
+	/* If at end of buffer, return 0 */
75
+	if ( block->start >= buffer->end )
76
+		return 0;
141 77
 
142
-	/* Get descriptor for previous block (which cannot be a tail block) */
143
-	copy_from_phys ( &prev_desc, prev_block, sizeof ( prev_desc ) );
78
+	/* Set up ->next and ->end as for a tail block */
79
+	block->next = block->end = buffer->end;
144 80
 
145
-	DBG ( "BUFFER marking [%x,%x) as used\n",
146
-	      prev_desc.next_free, desc->end );
81
+	/* Read tail marker from block */
82
+	copy_from_phys ( &block->tail, block->start, sizeof ( block->tail ) );
147 83
 
148
-	/* Modify descriptor for previous block and write it back */
149
-	prev_desc.next_free = desc->next_free;
150
-	copy_to_phys ( prev_block, &prev_desc, sizeof ( prev_desc ) );
84
+	/* If not a tail block, read whole block descriptor from block */
85
+	if ( ! block->tail ) {
86
+		copy_from_phys ( block, block->start, sizeof ( *block ) );
87
+	}
88
+
89
+	return 1;
90
+}
91
+
92
+static inline void store_free_block ( struct buffer_free_block *block ) {
93
+	copy_to_phys ( block->start, block,
94
+		       ( block->tail ?
95
+			 sizeof ( block->tail ) : sizeof ( *block ) ) );
151 96
 }
152 97
 
153 98
 /**
@@ -188,8 +133,7 @@ static inline void unfree_block ( struct buffer *buffer,
188 133
  */
189 134
 int fill_buffer ( struct buffer *buffer, const void *data,
190 135
 		  off_t offset, size_t len ) {
191
-	struct buffer_free_block desc;
192
-	physaddr_t block, prev_block;
136
+	struct buffer_free_block block, before, after;
193 137
 	physaddr_t data_start, data_end;
194 138
 
195 139
 	/* Calculate start and end addresses of data */
@@ -206,38 +150,48 @@ int fill_buffer ( struct buffer *buffer, const void *data,
206 150
 		return 0;
207 151
 	}
208 152
 
209
-	/* Iterate through the buffer's free blocks */
210
-	prev_block = 0;
211
-	block = buffer->start + buffer->fill;
212
-	while ( block < buffer->end ) {
213
-		/* Read block descriptor */
214
-		desc.next_free = buffer->end;
215
-		desc.end = buffer->end;
216
-		copy_from_phys ( &desc.tail, block, sizeof ( desc.tail ) );
217
-		if ( ! desc.tail )
218
-			copy_from_phys ( &desc, block, sizeof ( desc ) );
219
-
220
-		/* Split block at data start and end markers */
221
-		split_free_block ( &desc, block, data_start );
222
-		split_free_block ( &desc, block, data_end );
223
-
224
-		/* Block is now either completely contained by or
225
-		 * completely outside the data area
226
-		 */
227
-		if ( ( block >= data_start ) && ( block < data_end ) ) {
228
-			/* Block is within the data area */
229
-			unfree_block ( buffer, &desc, prev_block );
230
-			copy_to_phys ( block, data + ( block - data_start ),
231
-				       desc.end - block );
232
-		} else {
233
-			/* Block is outside the data area */
234
-			prev_block = block;
235
-		}
236
-
237
-		/* Move to next free block */
238
-		block = desc.next_free;
153
+	/* Find 'before' and 'after' blocks, if any */
154
+	before.start = before.end = 0;
155
+	after.start = after.end = buffer->end;
156
+	block.next = buffer->start + buffer->fill;
157
+	while ( next_free_block ( &block, buffer ) ) {
158
+		if ( ( block.start < data_start ) &&
159
+		     ( block.start >= before.start ) )
160
+			memcpy ( &before, &block, sizeof ( before ) );
161
+		if ( ( block.end > data_end ) &&
162
+		     ( block.end <= after.end ) )
163
+			memcpy ( &after, &block, sizeof ( after ) );
164
+	}
165
+
166
+	/* Truncate 'before' and 'after' blocks around data. */
167
+	if ( data_start < before.end )
168
+		before.end = data_start;
169
+	if ( data_end > after.start )
170
+		after.start = data_end;
171
+
172
+	/* Link 'after' block to 'before' block */
173
+	before.next = after.start;
174
+
175
+	/* Write back 'before' block, if any */
176
+	if ( before.start ) {
177
+		before.tail = 0;
178
+		store_free_block ( &before );
179
+	} else {
180
+		buffer->fill = before.next - buffer->start;
239 181
 	}
240 182
 
183
+	/* Write back 'after' block, if any */
184
+	if ( after.start < buffer->end ) {
185
+		store_free_block ( &after );
186
+	}
187
+	
188
+	DBG ( "BUFFER [%x,%x) before [%x,%x) after [%x,%x)\n",
189
+	      buffer->start, buffer->end, before.start, before.end,
190
+	      after.start, after.end );
191
+	
192
+	/* Copy data into buffer */
193
+	copy_to_phys ( data_start, data, len );
194
+
241 195
 	DBG ( "BUFFER [%x,%x) full up to %x\n",
242 196
 	      buffer->start, buffer->end, buffer->start + buffer->fill );
243 197
 

+ 3
- 1
src/include/buffer.h View File

@@ -82,7 +82,9 @@ struct buffer {
82 82
  */
83 83
 struct buffer_free_block {
84 84
 	char		tail;		/**< Tail byte marker */
85
-	physaddr_t	next_free;	/**< Address of next free block */
85
+	char		reserved[3];	/**< Padding */
86
+	physaddr_t	start;		/**< Address of this free block */
87
+	physaddr_t	next;		/**< Address of next free block */
86 88
 	physaddr_t	end;		/**< End of this block */
87 89
 } __attribute__ (( packed ));
88 90
 

Loading…
Cancel
Save