/branches/dynload/kernel/generic/include/mm/frame.h |
---|
57,15 → 57,14 |
/** Maximum number of zones in system. */ |
#define ZONES_MAX 16 |
/** If possible, merge with neighbouring zones. */ |
#define ZONE_JOIN 0x1 |
/** Convert the frame address to kernel va. */ |
#define FRAME_KA 0x1 |
/** Do not panic and do not sleep on failure. */ |
#define FRAME_ATOMIC 0x2 |
#define FRAME_ATOMIC 0x2 |
/** Do not start reclaiming when no free memory. */ |
#define FRAME_NO_RECLAIM 0x4 |
#define FRAME_NO_RECLAIM 0x4 |
/** Do not allocate above 4 GiB. */ |
#define FRAME_LOW_4_GiB 0x8 |
static inline uintptr_t PFN2ADDR(pfn_t frame) |
{ |
90,30 → 89,30 |
} |
#define IS_BUDDY_ORDER_OK(index, order) \ |
((~(((unative_t) -1) << (order)) & (index)) == 0) |
((~(((unative_t) -1) << (order)) & (index)) == 0) |
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \ |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0) |
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \ |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1) |
#define frame_alloc(order, flags) \ |
frame_alloc_generic(order, flags, NULL) |
frame_alloc_generic(order, flags, NULL) |
extern void frame_init(void); |
extern void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone); |
extern void frame_free(uintptr_t frame); |
extern void frame_reference_add(pfn_t pfn); |
extern void *frame_alloc_generic(uint8_t, int, unsigned int *); |
extern void frame_free(uintptr_t); |
extern void frame_reference_add(pfn_t); |
extern int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags); |
extern void *frame_get_parent(pfn_t frame, unsigned int hint); |
extern void frame_set_parent(pfn_t frame, void *data, unsigned int hint); |
extern void frame_mark_unavailable(pfn_t start, count_t count); |
extern uintptr_t zone_conf_size(count_t count); |
extern void zone_merge(unsigned int z1, unsigned int z2); |
extern int zone_create(pfn_t, count_t, pfn_t, int); |
extern void *frame_get_parent(pfn_t, unsigned int); |
extern void frame_set_parent(pfn_t, void *, unsigned int); |
extern void frame_mark_unavailable(pfn_t, count_t); |
extern uintptr_t zone_conf_size(count_t); |
extern void zone_merge(unsigned int, unsigned int); |
extern void zone_merge_all(void); |
extern uint64_t zone_total_size(void); |
121,7 → 120,7 |
* Console functions |
*/ |
extern void zone_print_list(void); |
extern void zone_print_one(unsigned int znum); |
extern void zone_print_one(unsigned int); |
#endif |
/branches/dynload/kernel/generic/include/mm/buddy.h |
---|
66,7 → 66,6 |
void (*mark_available)(struct buddy_system *, link_t *); |
/** Find parent of block that has given order */ |
link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t); |
void (* print_id)(struct buddy_system *, link_t *); |
} buddy_system_operations_t; |
typedef struct buddy_system { |
78,14 → 77,13 |
void *data; |
} buddy_system_t; |
extern void buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data); |
extern link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i); |
extern bool buddy_system_can_alloc(buddy_system_t *b, uint8_t order); |
extern void buddy_system_free(buddy_system_t *b, link_t *block); |
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size); |
extern size_t buddy_conf_size(int max_order); |
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block); |
extern void buddy_system_create(buddy_system_t *, uint8_t, |
buddy_system_operations_t *, void *); |
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t); |
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t); |
extern void buddy_system_free(buddy_system_t *, link_t *); |
extern size_t buddy_conf_size(int); |
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *); |
#endif |
/branches/dynload/kernel/generic/src/mm/buddy.c |
---|
35,8 → 35,7 |
* @brief Buddy allocator framework. |
* |
* This file contains buddy system allocator framework. |
* Specialized functions are needed for this abstract framework |
* to be useful. |
* Specialized functions are needed for this abstract framework to be useful. |
*/ |
#include <mm/buddy.h> |
46,7 → 45,7 |
#include <print.h> |
#include <macros.h> |
/** Return size needed for the buddy configuration data */ |
/** Return size needed for the buddy configuration data. */ |
size_t buddy_conf_size(int max_order) |
{ |
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t); |
53,21 → 52,20 |
} |
/** Create buddy system |
/** Create buddy system. |
* |
* Allocate memory for and initialize new buddy system. |
* |
* @param b Preallocated buddy system control data. |
* @param max_order The biggest allocable size will be 2^max_order. |
* @param op Operations for new buddy system. |
* @param data Pointer to be used by implementation. |
* @param b Preallocated buddy system control data. |
* @param max_order The biggest allocable size will be 2^max_order. |
* @param op Operations for new buddy system. |
* @param data Pointer to be used by implementation. |
* |
* @return New buddy system. |
* @return New buddy system. |
*/ |
void buddy_system_create(buddy_system_t *b, |
uint8_t max_order, |
buddy_system_operations_t *op, |
void *data) |
void |
buddy_system_create(buddy_system_t *b, uint8_t max_order, |
buddy_system_operations_t *op, void *data) |
{ |
int i; |
81,7 → 79,7 |
ASSERT(op->mark_busy); |
/* |
* Use memory after our own structure |
* Use memory after our own structure. |
*/ |
b->order = (link_t *) (&b[1]); |
93,14 → 91,15 |
b->data = data; |
} |
/** Check if buddy system can allocate block |
/** Check if buddy system can allocate block. |
* |
* @param b Buddy system pointer |
* @param i Size of the block (2^i) |
* @param b Buddy system pointer. |
* @param i Size of the block (2^i). |
* |
* @return True if block can be allocated |
* @return True if block can be allocated. |
*/ |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) { |
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) |
{ |
uint8_t k; |
/* |
107,12 → 106,13 |
* If requested block is greater then maximal block |
* we know immediatly that we cannot satisfy the request. |
*/ |
if (i > b->max_order) return false; |
if (i > b->max_order) |
return false; |
/* |
* Check if any bigger or equal order has free elements |
*/ |
for (k=i; k <= b->max_order; k++) { |
for (k = i; k <= b->max_order; k++) { |
if (!list_empty(&b->order[k])) { |
return true; |
} |
119,12 → 119,11 |
} |
return false; |
} |
/** Allocate PARTICULAR block from buddy system |
/** Allocate PARTICULAR block from buddy system. |
* |
* @ return Block of data or NULL if no such block was found |
* @return Block of data or NULL if no such block was found. |
*/ |
link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block) |
{ |
135,7 → 134,7 |
ASSERT(left); |
list_remove(left); |
while (1) { |
if (! b->op->get_order(b,left)) { |
if (!b->op->get_order(b, left)) { |
b->op->mark_busy(b, left); |
return left; |
} |
143,8 → 142,8 |
order = b->op->get_order(b, left); |
right = b->op->bisect(b, left); |
b->op->set_order(b, left, order-1); |
b->op->set_order(b, right, order-1); |
b->op->set_order(b, left, order - 1); |
b->op->set_order(b, right, order - 1); |
tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK); |
161,10 → 160,10 |
/** Allocate block from buddy system. |
* |
* @param b Buddy system pointer. |
* @param i Returned block will be 2^i big. |
* @param b Buddy system pointer. |
* @param i Returned block will be 2^i big. |
* |
* @return Block of data represented by link_t. |
* @return Block of data represented by link_t. |
*/ |
link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i) |
{ |
218,13 → 217,12 |
buddy_system_free(b, hlp); |
return res; |
} |
/** Return block to buddy system. |
* |
* @param b Buddy system pointer. |
* @param block Block to return. |
* @param b Buddy system pointer. |
* @param block Block to return. |
*/ |
void buddy_system_free(buddy_system_t *b, link_t *block) |
{ |
268,7 → 266,8 |
b->op->set_order(b, hlp, i + 1); |
/* |
* Recursively add the coalesced block to the list of order i + 1. |
* Recursively add the coalesced block to the list of |
* order i + 1. |
*/ |
buddy_system_free(b, hlp); |
return; |
279,46 → 278,7 |
* Insert block into the list of order i. |
*/ |
list_append(block, &b->order[i]); |
} |
/** Prints out structure of buddy system |
* |
* @param b Pointer to buddy system |
* @param elem_size Element size |
*/ |
void buddy_system_structure_print(buddy_system_t *b, size_t elem_size) { |
index_t i; |
count_t cnt, elem_count = 0, block_count = 0; |
link_t *cur; |
printf("Order\tBlocks\tSize \tBlock size\tElems per block\n"); |
printf("-----\t------\t--------\t----------\t---------------\n"); |
for (i = 0;i <= b->max_order; i++) { |
cnt = 0; |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) |
cnt++; |
} |
printf("#%" PRIi "\t%5" PRIc "\t%7" PRIc "K\t%8" PRIi "K\t%6u\t", |
i, cnt, SIZE2KB(cnt * (1 << i) * elem_size), SIZE2KB((1 << i) * elem_size), 1 << i); |
if (!list_empty(&b->order[i])) { |
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) { |
b->op->print_id(b, cur); |
printf(" "); |
} |
} |
printf("\n"); |
block_count += cnt; |
elem_count += (1 << i) * cnt; |
} |
printf("-----\t------\t--------\t----------\t---------------\n"); |
printf("Buddy system contains %" PRIc " free elements (%" PRIc " blocks)\n" , elem_count, block_count); |
} |
/** @} |
*/ |
/branches/dynload/kernel/generic/src/mm/frame.c |
---|
200,8 → 200,7 |
return i; |
} |
/** |
* Try to find a zone where can we find the frame. |
/** Try to find a zone where can we find the frame. |
* |
* Assume interrupts are disabled. |
* |
237,7 → 236,7 |
i++; |
if (i >= zones.count) |
i = 0; |
} while(i != hint); |
} while (i != hint); |
spinlock_unlock(&zones.lock); |
return NULL; |
254,15 → 253,20 |
* Assume interrupts are disabled. |
* |
* @param order Size (2^order) of free space we are trying to find. |
* @param flags Required flags of the target zone. |
* @param pzone Pointer to preferred zone or NULL, on return contains |
* zone number. |
*/ |
static zone_t *find_free_zone_and_lock(uint8_t order, unsigned int *pzone) |
static zone_t * |
find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone) |
{ |
unsigned int i; |
zone_t *z; |
unsigned int hint = pzone ? *pzone : 0; |
/* Mask off flags that are not applicable. */ |
flags &= FRAME_LOW_4_GiB; |
spinlock_lock(&zones.lock); |
if (hint >= zones.count) |
hint = 0; |
272,17 → 276,24 |
spinlock_lock(&z->lock); |
/* Check if the zone has 2^order frames area available */ |
if (zone_can_alloc(z, order)) { |
spinlock_unlock(&zones.lock); |
if (pzone) |
*pzone = i; |
return z; |
/* |
* Check whether the zone meets the search criteria. |
*/ |
if ((z->flags & flags) == flags) { |
/* |
* Check if the zone has 2^order frames area available. |
*/ |
if (zone_can_alloc(z, order)) { |
spinlock_unlock(&zones.lock); |
if (pzone) |
*pzone = i; |
return z; |
} |
} |
spinlock_unlock(&z->lock); |
if (++i >= zones.count) |
i = 0; |
} while(i != hint); |
} while (i != hint); |
spinlock_unlock(&zones.lock); |
return NULL; |
} |
318,18 → 329,6 |
return NULL; |
} |
static void zone_buddy_print_id(buddy_system_t *b, link_t *block) |
{ |
frame_t *frame; |
zone_t *zone; |
index_t index; |
frame = list_get_instance(block, frame_t, buddy_link); |
zone = (zone_t *) b->data; |
index = frame_index(zone, frame); |
printf("%" PRIi, index); |
} |
/** Buddy system find_buddy implementation. |
* |
* @param b Buddy system. |
469,8 → 468,7 |
.get_order = zone_buddy_get_order, |
.mark_busy = zone_buddy_mark_busy, |
.mark_available = zone_buddy_mark_available, |
.find_block = zone_buddy_find_block, |
.print_id = zone_buddy_print_id |
.find_block = zone_buddy_find_block |
}; |
/******************/ |
823,7 → 821,15 |
spinlock_initialize(&z->lock, "zone_lock"); |
z->base = start; |
z->count = count; |
/* Mask off flags that are calculated automatically. */ |
flags &= ~FRAME_LOW_4_GiB; |
/* Determine calculated flags. */ |
if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */ |
flags |= FRAME_LOW_4_GiB; |
z->flags = flags; |
z->free_count = count; |
z->busy_count = 0; |
995,7 → 1001,7 |
/* |
* First, find suitable frame zone. |
*/ |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, pzone); |
/* If no memory, reclaim some slab memory, |
if it does not help, reclaim all */ |
1002,11 → 1008,12 |
if (!zone && !(flags & FRAME_NO_RECLAIM)) { |
freed = slab_reclaim(0); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, pzone); |
if (!zone) { |
freed = slab_reclaim(SLAB_RECLAIM_ALL); |
if (freed) |
zone = find_free_zone_and_lock(order, pzone); |
zone = find_free_zone_and_lock(order, flags, |
pzone); |
} |
} |
if (!zone) { |
1214,9 → 1221,6 |
unsigned int i; |
ipl_t ipl; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
#ifdef __32_BITS__ |
printf("# base address free frames busy frames\n"); |
printf("-- ------------ ------------ ------------\n"); |
1227,26 → 1231,54 |
printf("-- -------------------- ------------ ------------\n"); |
#endif |
for (i = 0; i < zones.count; i++) { |
/* |
* Because printing may require allocation of memory, we may not hold |
* the frame allocator locks when printing zone statistics. Therefore, |
* we simply gather the statistics under the protection of the locks and |
* print the statistics when the locks have been released. |
* |
* When someone adds/removes zones while we are printing the statistics, |
* we may end up with inaccurate output (e.g. a zone being skipped from |
* the listing). |
*/ |
for (i = 0; ; i++) { |
uintptr_t base; |
count_t free_count; |
count_t busy_count; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
if (i >= zones.count) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
break; |
} |
zone = zones.info[i]; |
spinlock_lock(&zone->lock); |
base = PFN2ADDR(zone->base); |
free_count = zone->free_count; |
busy_count = zone->busy_count; |
spinlock_unlock(&zone->lock); |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
#ifdef __32_BITS__ |
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", |
i, PFN2ADDR(zone->base), zone->free_count, |
zone->busy_count); |
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#endif |
#ifdef __64_BITS__ |
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, |
PFN2ADDR(zone->base), zone->free_count, zone->busy_count); |
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base, |
free_count, busy_count); |
#endif |
spinlock_unlock(&zone->lock); |
} |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
} |
/** Prints zone details. |
1258,6 → 1290,10 |
zone_t *zone = NULL; |
ipl_t ipl; |
unsigned int i; |
uintptr_t base; |
count_t count; |
count_t busy_count; |
count_t free_count; |
ipl = interrupts_disable(); |
spinlock_lock(&zones.lock); |
1269,25 → 1305,28 |
} |
} |
if (!zone) { |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone not found.\n"); |
goto out; |
return; |
} |
spinlock_lock(&zone->lock); |
printf("Memory zone information\n"); |
printf("Zone base address: %p\n", PFN2ADDR(zone->base)); |
printf("Zone size: %" PRIc " frames (%" PRIs " KB)\n", zone->count, |
SIZE2KB(FRAMES2SIZE(zone->count))); |
printf("Allocated space: %" PRIc " frames (%" PRIs " KB)\n", |
zone->busy_count, SIZE2KB(FRAMES2SIZE(zone->busy_count))); |
printf("Available space: %" PRIc " frames (%" PRIs " KB)\n", |
zone->free_count, SIZE2KB(FRAMES2SIZE(zone->free_count))); |
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE); |
base = PFN2ADDR(zone->base); |
count = zone->count; |
busy_count = zone->busy_count; |
free_count = zone->free_count; |
spinlock_unlock(&zone->lock); |
out: |
spinlock_unlock(&zones.lock); |
interrupts_restore(ipl); |
printf("Zone base address: %p\n", base); |
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count, |
SIZE2KB(FRAMES2SIZE(count))); |
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n", |
busy_count, SIZE2KB(FRAMES2SIZE(busy_count))); |
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n", |
free_count, SIZE2KB(FRAMES2SIZE(free_count))); |
} |
/** @} |
/branches/dynload/kernel/arch/ppc32/src/asm.S |
---|
203,47 → 203,7 |
rfi |
memsetb: |
rlwimi r5, r5, 8, 16, 23 |
rlwimi r5, r5, 16, 0, 15 |
addi r14, r3, -4 |
cmplwi 0, r4, 4 |
blt 7f |
stwu r5, 4(r14) |
beqlr |
andi. r15, r14, 3 |
add r4, r15, r4 |
subf r14, r15, r14 |
srwi r15, r4, 2 |
mtctr r15 |
bdz 6f |
1: |
stwu r5, 4(r14) |
bdnz 1b |
6: |
andi. r4, r4, 3 |
7: |
cmpwi 0, r4, 0 |
beqlr |
mtctr r4 |
addi r6, r6, 3 |
8: |
stbu r5, 1(r14) |
bdnz 8b |
blr |
b _memsetb |
memcpy: |
memcpy_from_uspace: |
/branches/dynload/kernel/arch/ia32/src/smp/smp.c |
---|
155,7 → 155,7 |
* Prepare new GDT for CPU in question. |
*/ |
gdt_new = (struct descriptor *) malloc(GDT_ITEMS * |
sizeof(struct descriptor), FRAME_ATOMIC); |
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB); |
if (!gdt_new) |
panic("couldn't allocate memory for GDT\n"); |