Subversion Repositories Kolibri OS

Rev

Rev 4075 | Rev 5060 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4075 Rev 4104
Line 47... Line 47...
47
#include 
47
#include 
48
#include 
48
#include 
Line 49... Line 49...
49
 
49
 
Line 50... Line 50...
50
#define MM_UNUSED_TARGET 4
50
#define MM_UNUSED_TARGET 4
51
 
-
 
52
static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
51
 
53
{
-
 
54
	struct drm_mm_node *child;
-
 
55
 
-
 
56
	if (atomic)
-
 
57
		child = kzalloc(sizeof(*child), GFP_ATOMIC);
-
 
58
	else
-
 
59
		child = kzalloc(sizeof(*child), GFP_KERNEL);
52
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
60
 
-
 
61
	if (unlikely(child == NULL)) {
-
 
62
       spin_lock(&mm->unused_lock);
53
						unsigned long size,
63
		if (list_empty(&mm->unused_nodes))
-
 
64
			child = NULL;
-
 
65
		else {
-
 
66
			child =
54
						unsigned alignment,
67
			    list_entry(mm->unused_nodes.next,
-
 
68
				       struct drm_mm_node, node_list);
-
 
69
			list_del(&child->node_list);
-
 
70
			--mm->num_unused;
-
 
71
		}
-
 
72
       spin_unlock(&mm->unused_lock);
-
 
73
	}
-
 
74
	return child;
-
 
75
}
-
 
76
 
-
 
77
/* drm_mm_pre_get() - pre allocate drm_mm_node structure
-
 
78
 * drm_mm:	memory manager struct we are pre-allocating for
-
 
79
 *
-
 
80
 * Returns 0 on success or -ENOMEM if allocation fails.
55
						unsigned long color,
81
 */
-
 
82
int drm_mm_pre_get(struct drm_mm *mm)
56
						enum drm_mm_search_flags flags);
83
{
-
 
84
	struct drm_mm_node *node;
-
 
85
 
-
 
86
	spin_lock(&mm->unused_lock);
-
 
87
	while (mm->num_unused < MM_UNUSED_TARGET) {
-
 
88
		spin_unlock(&mm->unused_lock);
-
 
89
		node = kzalloc(sizeof(*node), GFP_KERNEL);
-
 
90
		spin_lock(&mm->unused_lock);
57
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
91
 
-
 
92
		if (unlikely(node == NULL)) {
58
						unsigned long size,
93
			int ret = (mm->num_unused < 2) ? -ENOMEM : 0;
59
						unsigned alignment,
94
			spin_unlock(&mm->unused_lock);
-
 
95
			return ret;
60
						unsigned long color,
96
		}
-
 
97
		++mm->num_unused;
-
 
98
		list_add_tail(&node->node_list, &mm->unused_nodes);
-
 
99
	}
-
 
100
	spin_unlock(&mm->unused_lock);
-
 
101
	return 0;
61
						unsigned long start,
Line 102... Line 62...
102
}
62
						unsigned long end,
103
EXPORT_SYMBOL(drm_mm_pre_get);
63
						enum drm_mm_search_flags flags);
104
 
64
 
105
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
65
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
Line 145... Line 105...
145
		list_add(&node->hole_stack, &mm->hole_stack);
105
		list_add(&node->hole_stack, &mm->hole_stack);
146
		node->hole_follows = 1;
106
		node->hole_follows = 1;
147
	}
107
	}
148
}
108
}
Line 149... Line 109...
149
 
109
 
150
struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
-
 
151
					unsigned long start,
-
 
152
					unsigned long size,
-
 
153
					bool atomic)
110
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
154
{
111
{
155
	struct drm_mm_node *hole, *node;
112
	struct drm_mm_node *hole;
156
	unsigned long end = start + size;
113
	unsigned long end = node->start + node->size;
157
	unsigned long hole_start;
114
	unsigned long hole_start;
Line -... Line 115...
-
 
115
	unsigned long hole_end;
-
 
116
 
-
 
117
	BUG_ON(node == NULL);
158
	unsigned long hole_end;
118
 
159
 
119
	/* Find the relevant hole to add our node to */
160
	drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
120
	drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
Line 161... Line -...
161
		if (hole_start > start || hole_end < end)
-
 
162
			continue;
-
 
163
 
-
 
164
		node = drm_mm_kmalloc(mm, atomic);
-
 
165
		if (unlikely(node == NULL))
-
 
166
			return NULL;
-
 
167
 
121
		if (hole_start > node->start || hole_end < end)
168
		node->start = start;
122
			continue;
Line 169... Line 123...
169
		node->size = size;
123
 
170
		node->mm = mm;
124
		node->mm = mm;
Line 171... Line 125...
171
		node->allocated = 1;
125
		node->allocated = 1;
172
 
126
 
173
		INIT_LIST_HEAD(&node->hole_stack);
127
		INIT_LIST_HEAD(&node->hole_stack);
174
		list_add(&node->node_list, &hole->node_list);
128
		list_add(&node->node_list, &hole->node_list);
Line 175... Line 129...
175
 
129
 
176
		if (start == hole_start) {
130
		if (node->start == hole_start) {
177
			hole->hole_follows = 0;
131
			hole->hole_follows = 0;
178
			list_del_init(&hole->hole_stack);
132
			list_del_init(&hole->hole_stack);
179
		}
133
		}
Line 180... Line 134...
180
 
134
 
181
		node->hole_follows = 0;
-
 
182
		if (end != hole_end) {
-
 
183
			list_add(&node->hole_stack, &mm->hole_stack);
-
 
184
			node->hole_follows = 1;
-
 
185
		}
135
		node->hole_follows = 0;
186
 
-
 
187
		return node;
-
 
188
	}
-
 
189
 
-
 
190
	WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size);
-
 
191
	return NULL;
-
 
192
}
-
 
193
EXPORT_SYMBOL(drm_mm_create_block);
-
 
194
 
-
 
195
struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
-
 
196
						 unsigned long size,
-
 
197
					     unsigned alignment,
-
 
198
					     unsigned long color,
-
 
Line 199... Line 136...
199
						 int atomic)
136
		if (end != hole_end) {
200
{
-
 
-
 
137
			list_add(&node->hole_stack, &mm->hole_stack);
201
	struct drm_mm_node *node;
138
			node->hole_follows = 1;
202
 
139
		}
203
	node = drm_mm_kmalloc(hole_node->mm, atomic);
140
 
Line 204... Line 141...
204
	if (unlikely(node == NULL))
141
		return 0;
205
		return NULL;
142
	}
206
 
143
 
207
	drm_mm_insert_helper(hole_node, node, size, alignment, color);
144
	WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
208
 
145
	     node->start, node->size);
209
	return node;
146
	return -ENOSPC;
210
}
147
}
211
EXPORT_SYMBOL(drm_mm_get_block_generic);
148
EXPORT_SYMBOL(drm_mm_reserve_node);
-
 
149
 
212
 
150
/**
213
/**
151
 * Search for free space and insert a preallocated memory node. Returns
Line 214... Line 152...
214
 * Search for free space and insert a preallocated memory node. Returns
152
 * -ENOSPC if no suitable free area is available. The preallocated memory node
215
 * -ENOSPC if no suitable free area is available. The preallocated memory node
153
 * must be cleared.
216
 * must be cleared.
154
 */
217
 */
155
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
Line 218... Line 156...
218
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
156
			       unsigned long size, unsigned alignment,
219
			       unsigned long size, unsigned alignment,
157
			       unsigned long color,
220
			       unsigned long color)
158
			       enum drm_mm_search_flags flags)
221
{
159
{
Line 222... Line -...
222
	struct drm_mm_node *hole_node;
-
 
223
 
-
 
224
	hole_node = drm_mm_search_free_generic(mm, size, alignment,
-
 
225
					       color, 0);
-
 
226
	if (!hole_node)
-
 
227
		return -ENOSPC;
-
 
228
 
-
 
229
	drm_mm_insert_helper(hole_node, node, size, alignment, color);
160
	struct drm_mm_node *hole_node;
230
	return 0;
161
 
231
}
162
	hole_node = drm_mm_search_free_generic(mm, size, alignment,
232
EXPORT_SYMBOL(drm_mm_insert_node_generic);
163
					       color, flags);
233
 
164
	if (!hole_node)
Line 288... Line 219...
288
		list_add(&node->hole_stack, &mm->hole_stack);
219
		list_add(&node->hole_stack, &mm->hole_stack);
289
		node->hole_follows = 1;
220
		node->hole_follows = 1;
290
	}
221
	}
291
}
222
}
Line 292... Line -...
292
 
-
 
293
struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
-
 
294
						unsigned long size,
-
 
295
						unsigned alignment,
-
 
296
						unsigned long color,
-
 
297
						unsigned long start,
-
 
298
						unsigned long end,
-
 
299
						int atomic)
-
 
300
{
-
 
301
	struct drm_mm_node *node;
-
 
302
 
-
 
303
	node = drm_mm_kmalloc(hole_node->mm, atomic);
-
 
304
	if (unlikely(node == NULL))
-
 
305
			return NULL;
-
 
306
 
-
 
307
	drm_mm_insert_helper_range(hole_node, node, size, alignment, color,
-
 
308
				   start, end);
-
 
309
 
-
 
310
	return node;
-
 
311
}
-
 
312
EXPORT_SYMBOL(drm_mm_get_block_range_generic);
-
 
313
 
223
 
314
/**
224
/**
315
 * Search for free space and insert a preallocated memory node. Returns
225
 * Search for free space and insert a preallocated memory node. Returns
316
 * -ENOSPC if no suitable free area is available. This is for range
226
 * -ENOSPC if no suitable free area is available. This is for range
317
 * restricted allocations. The preallocated memory node must be cleared.
227
 * restricted allocations. The preallocated memory node must be cleared.
318
 */
228
 */
319
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
229
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
320
					unsigned long size, unsigned alignment, unsigned long color,
230
					unsigned long size, unsigned alignment, unsigned long color,
-
 
231
					unsigned long start, unsigned long end,
321
				unsigned long start, unsigned long end)
232
					enum drm_mm_search_flags flags)
322
{
233
{
Line 323... Line 234...
323
	struct drm_mm_node *hole_node;
234
	struct drm_mm_node *hole_node;
324
 
235
 
325
	hole_node = drm_mm_search_free_in_range_generic(mm,
236
	hole_node = drm_mm_search_free_in_range_generic(mm,
326
							size, alignment, color,
237
							size, alignment, color,
327
							start, end, 0);
238
							start, end, flags);
Line 328... Line 239...
328
	if (!hole_node)
239
	if (!hole_node)
329
		return -ENOSPC;
240
		return -ENOSPC;
330
 
241
 
331
	drm_mm_insert_helper_range(hole_node, node,
242
	drm_mm_insert_helper_range(hole_node, node,
332
				   size, alignment, color,
243
				   size, alignment, color,
333
				   start, end);
244
				   start, end);
Line 334... Line -...
334
	return 0;
-
 
335
}
-
 
336
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
-
 
337
 
-
 
338
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
-
 
339
				unsigned long size, unsigned alignment,
-
 
340
				unsigned long start, unsigned long end)
-
 
341
{
-
 
342
	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
245
	return 0;
343
}
246
}
344
EXPORT_SYMBOL(drm_mm_insert_node_in_range);
247
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
345
 
248
 
346
/**
249
/**
347
 * Remove a memory node from the allocator.
250
 * Remove a memory node from the allocator.
348
 */
251
 */
Line -... Line 252...
-
 
252
void drm_mm_remove_node(struct drm_mm_node *node)
-
 
253
{
-
 
254
	struct drm_mm *mm = node->mm;
349
void drm_mm_remove_node(struct drm_mm_node *node)
255
	struct drm_mm_node *prev_node;
350
{
256
 
Line 351... Line 257...
351
	struct drm_mm *mm = node->mm;
257
	if (WARN_ON(!node->allocated))
352
	struct drm_mm_node *prev_node;
258
		return;
Line 375... Line 281...
375
	list_del(&node->node_list);
281
	list_del(&node->node_list);
376
	node->allocated = 0;
282
	node->allocated = 0;
377
}
283
}
378
EXPORT_SYMBOL(drm_mm_remove_node);
284
EXPORT_SYMBOL(drm_mm_remove_node);
Line 379... Line -...
379
 
-
 
380
/*
-
 
381
 * Remove a memory node from the allocator and free the allocated struct
-
 
382
 * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
-
 
383
 * drm_mm_get_block functions.
-
 
384
 */
-
 
385
void drm_mm_put_block(struct drm_mm_node *node)
-
 
386
{
-
 
387
 
-
 
388
	struct drm_mm *mm = node->mm;
-
 
389
 
-
 
390
    drm_mm_remove_node(node);
-
 
391
 
-
 
392
    spin_lock(&mm->unused_lock);
-
 
393
    if (mm->num_unused < MM_UNUSED_TARGET) {
-
 
394
    list_add(&node->node_list, &mm->unused_nodes);
-
 
395
        ++mm->num_unused;
-
 
396
    } else
-
 
397
    kfree(node);
-
 
398
    spin_unlock(&mm->unused_lock);
-
 
399
}
-
 
400
EXPORT_SYMBOL(drm_mm_put_block);
-
 
401
 
285
 
402
static int check_free_hole(unsigned long start, unsigned long end,
286
static int check_free_hole(unsigned long start, unsigned long end,
403
			   unsigned long size, unsigned alignment)
287
			   unsigned long size, unsigned alignment)
404
{
288
{
405
	if (end - start < size)
289
	if (end - start < size)
Line 412... Line 296...
412
	}
296
	}
Line 413... Line 297...
413
 
297
 
414
	return end >= start + size;
298
	return end >= start + size;
Line 415... Line 299...
415
}
299
}
416
 
300
 
417
struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
301
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
418
				       unsigned long size,
302
				       unsigned long size,
419
					       unsigned alignment,
303
					       unsigned alignment,
420
					       unsigned long color,
304
					       unsigned long color,
421
					       bool best_match)
305
						      enum drm_mm_search_flags flags)
422
{
306
{
423
	struct drm_mm_node *entry;
307
	struct drm_mm_node *entry;
424
	struct drm_mm_node *best;
308
	struct drm_mm_node *best;
Line 439... Line 323...
439
		}
323
		}
Line 440... Line 324...
440
 
324
 
441
		if (!check_free_hole(adj_start, adj_end, size, alignment))
325
		if (!check_free_hole(adj_start, adj_end, size, alignment))
Line 442... Line 326...
442
			continue;
326
			continue;
443
 
327
 
Line 444... Line 328...
444
			if (!best_match)
328
		if (!(flags & DRM_MM_SEARCH_BEST))
445
				return entry;
329
				return entry;
446
 
330
 
447
			if (entry->size < best_size) {
331
			if (entry->size < best_size) {
448
				best = entry;
332
				best = entry;
Line 449... Line 333...
449
				best_size = entry->size;
333
				best_size = entry->size;
450
			}
334
			}
451
		}
-
 
Line 452... Line 335...
452
 
335
		}
453
	return best;
336
 
454
}
337
	return best;
455
EXPORT_SYMBOL(drm_mm_search_free_generic);
338
}
456
 
339
 
457
struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
340
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
458
						unsigned long size,
341
						unsigned long size,
459
						unsigned alignment,
342
						unsigned alignment,
460
							unsigned long color,
343
							unsigned long color,
461
						unsigned long start,
344
						unsigned long start,
462
						unsigned long end,
345
						unsigned long end,
463
							bool best_match)
346
							enum drm_mm_search_flags flags)
Line 486... Line 369...
486
		}
369
		}
Line 487... Line 370...
487
 
370
 
488
		if (!check_free_hole(adj_start, adj_end, size, alignment))
371
		if (!check_free_hole(adj_start, adj_end, size, alignment))
Line 489... Line 372...
489
			continue;
372
			continue;
490
 
373
 
Line 491... Line 374...
491
			if (!best_match)
374
		if (!(flags & DRM_MM_SEARCH_BEST))
492
				return entry;
375
				return entry;
493
 
376
 
494
			if (entry->size < best_size) {
377
			if (entry->size < best_size) {
495
				best = entry;
378
				best = entry;
Line 496... Line 379...
496
				best_size = entry->size;
379
				best_size = entry->size;
497
			}
380
			}
498
		}
-
 
Line 499... Line 381...
499
 
381
		}
500
	return best;
382
 
501
}
383
	return best;
502
EXPORT_SYMBOL(drm_mm_search_free_in_range_generic);
384
}
Line 632... Line 514...
632
 * Nodes _must_ be removed in the exact same order from the scan list as they
514
 * Nodes _must_ be removed in the exact same order from the scan list as they
633
 * have been added, otherwise the internal state of the memory manager will be
515
 * have been added, otherwise the internal state of the memory manager will be
634
 * corrupted.
516
 * corrupted.
635
 *
517
 *
636
 * When the scan list is empty, the selected memory nodes can be freed. An
518
 * When the scan list is empty, the selected memory nodes can be freed. An
637
 * immediately following drm_mm_search_free with best_match = 0 will then return
519
 * immediately following drm_mm_search_free with !DRM_MM_SEARCH_BEST will then
638
 * the just freed block (because its at the top of the free_stack list).
520
 * return the just freed block (because its at the top of the free_stack list).
639
 *
521
 *
640
 * Returns one if this block should be evicted, zero otherwise. Will always
522
 * Returns one if this block should be evicted, zero otherwise. Will always
641
 * return zero when no hole has been found.
523
 * return zero when no hole has been found.
642
 */
524
 */
643
int drm_mm_scan_remove_block(struct drm_mm_node *node)
525
int drm_mm_scan_remove_block(struct drm_mm_node *node)
Line 670... Line 552...
670
EXPORT_SYMBOL(drm_mm_clean);
552
EXPORT_SYMBOL(drm_mm_clean);
Line 671... Line 553...
671
 
553
 
672
void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
554
void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
673
{
555
{
674
	INIT_LIST_HEAD(&mm->hole_stack);
-
 
675
	INIT_LIST_HEAD(&mm->unused_nodes);
-
 
676
	mm->num_unused = 0;
556
	INIT_LIST_HEAD(&mm->hole_stack);
677
	mm->scanned_blocks = 0;
-
 
Line 678... Line 557...
678
	spin_lock_init(&mm->unused_lock);
557
	mm->scanned_blocks = 0;
679
 
558
 
680
	/* Clever trick to avoid a special case in the free hole tracking. */
559
	/* Clever trick to avoid a special case in the free hole tracking. */
681
	INIT_LIST_HEAD(&mm->head_node.node_list);
560
	INIT_LIST_HEAD(&mm->head_node.node_list);
Line 693... Line 572...
693
}
572
}
694
EXPORT_SYMBOL(drm_mm_init);
573
EXPORT_SYMBOL(drm_mm_init);
Line 695... Line 574...
695
 
574
 
696
void drm_mm_takedown(struct drm_mm * mm)
575
void drm_mm_takedown(struct drm_mm * mm)
697
{
-
 
698
	struct drm_mm_node *entry, *next;
-
 
699
 
576
{
700
	if (WARN(!list_empty(&mm->head_node.node_list),
577
	WARN(!list_empty(&mm->head_node.node_list),
701
		 "Memory manager not clean. Delaying takedown\n")) {
-
 
702
		return;
-
 
703
	}
-
 
704
 
-
 
705
	spin_lock(&mm->unused_lock);
-
 
706
	list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
-
 
707
	list_del(&entry->node_list);
-
 
708
	kfree(entry);
-
 
709
		--mm->num_unused;
-
 
710
	}
-
 
711
	spin_unlock(&mm->unused_lock);
-
 
712
 
-
 
713
	BUG_ON(mm->num_unused != 0);
578
	     "Memory manager not clean during takedown.\n");
714
}
579
}
Line 715... Line 580...
715
EXPORT_SYMBOL(drm_mm_takedown);
580
EXPORT_SYMBOL(drm_mm_takedown);
716
 
581