Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3210 → Rev 3211

/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");