lib/mm/mm.c
errval_t mm_alloc_aligned(struct mm *mm, size_t size, size_t alignment, struct capref *retcap)
{

	struct slot_prealloc *sp = (struct slot_prealloc*) mm->slot_alloc_inst;
	if (sp->meta[0].free < 3 && sp->meta[1].free < 3 && !sp->refilling) {
		sp->refilling = true;
		errval_t err = mm->slot_refill(mm->slot_alloc_inst);
		sp->refilling = false;
		assert(err_is_ok(err));

	}

	// round the size to the nearest page size multiple
	if (size % BASE_PAGE_SIZE != 0) {
		size += BASE_PAGE_SIZE - (size % BASE_PAGE_SIZE);
	}

	struct mmnode *curr = mm->head;
	while(curr) {
		if (curr->type == NodeType_Free) {
			// offset into curr node to actually start at because of alignment
			size_t curr_offset = curr->base % alignment == 0 ? 0 : alignment - (curr->base % alignment);
			if (curr_offset + size <= curr->size) {
				size_t remaining = curr->size - size - curr_offset;
				errval_t err;
				if (slab_freecount(&mm->slabs) < 4 && ! mm->refillingslabs) {
					mm->refillingslabs = true;
					err = mm->slabs.refill_func(&mm->slabs);
					mm->refillingslabs = false;

					if (err_is_fail(err)) {
						return err;
					}
				}
				struct mmnode *new_node = (struct mmnode*) slab_alloc(&mm->slabs);

				assert(new_node != NULL);
				new_node->type = NodeType_Allocated;

				new_node->prev = curr->prev;
				if (curr->prev != NULL) {
					curr->prev->next = new_node;
				}
				new_node->next = curr;
				curr->prev = new_node;
				
				if (curr == mm->head) {
					mm->head = new_node;
				}

				err = mm->slot_alloc(mm->slot_alloc_inst, 1, &(new_node->cap.cap));
				if (err_is_fail(err)) {
			        return err;
			    }
				err = cap_retype(new_node->cap.cap, mm->initial_cap, (curr->base - mm->initial_base) + curr_offset, mm->objtype, size, 1);
				if (err_is_fail(err)) {
			        return err;
			    }

				new_node->base = curr->base + curr_offset;
				new_node->size = size;
				curr->base += size + curr_offset;
				curr->size = remaining;
				
				// remove curr if its size is 0
				if (curr->size == 0) {
					curr->prev->next = curr->next;
					curr->next->prev = curr->prev;
					slab_free(&mm->slabs, curr);
				}
				// add pre-offset node if curr_offset does not equal 0
				if (curr_offset > 0) {
					struct mmnode *offset_node = (struct mmnode*) slab_alloc(&mm->slabs);

					assert(offset_node != NULL);
					offset_node->type = NodeType_Free;

					offset_node->prev = new_node->prev;
					if (new_node->prev != NULL) {
						new_node->prev->next = offset_node;
					}
					offset_node->next = new_node;
					new_node->prev = offset_node;
				
					if (new_node == mm->head) {
						mm->head = offset_node;
					}
					
					offset_node->base = new_node->base - curr_offset;
					offset_node->size = curr_offset;
				}
				
				*retcap = new_node->cap.cap;
				break;
			}
		}
		curr = curr->next;
	}
	return SYS_ERR_OK;

}
/**
 * Allocate aligned physical memory.
 *
 * \param       mm        The memory manager.
 * \param       size      How much memory to allocate.
 * \param       alignment The alignment requirement of the base address for your memory.
 * \param[out]  retcap    Capability for the allocated region.
 */
Allocate aligned physical memory.
\param       mm        The memory manager.
\param       size      How much memory to allocate.
\param       alignment The alignment requirement of the base address for your memory.
\param[out]  retcap    Capability for the allocated region.
Allocate aligned physical memory . \ param mm The memory manager . \ param size How much memory to allocate . \ param alignment The alignment requirement of the base address for your memory . \ param [ out ] retcap Capability for the allocated region .
errval_t mm_alloc_aligned(struct mm *mm, size_t size, size_t alignment, struct capref *retcap)
{
	struct slot_prealloc *sp = (struct slot_prealloc*) mm->slot_alloc_inst;
	if (sp->meta[0].free < 3 && sp->meta[1].free < 3 && !sp->refilling) {
		sp->refilling = true;
		errval_t err = mm->slot_refill(mm->slot_alloc_inst);
		sp->refilling = false;
		assert(err_is_ok(err));
	}
	if (size % BASE_PAGE_SIZE != 0) {
		size += BASE_PAGE_SIZE - (size % BASE_PAGE_SIZE);
	}
	struct mmnode *curr = mm->head;
	while(curr) {
		if (curr->type == NodeType_Free) {
			size_t curr_offset = curr->base % alignment == 0 ? 0 : alignment - (curr->base % alignment);
			if (curr_offset + size <= curr->size) {
				size_t remaining = curr->size - size - curr_offset;
				errval_t err;
				if (slab_freecount(&mm->slabs) < 4 && ! mm->refillingslabs) {
					mm->refillingslabs = true;
					err = mm->slabs.refill_func(&mm->slabs);
					mm->refillingslabs = false;
					if (err_is_fail(err)) {
						return err;
					}
				}
				struct mmnode *new_node = (struct mmnode*) slab_alloc(&mm->slabs);
				assert(new_node != NULL);
				new_node->type = NodeType_Allocated;
				new_node->prev = curr->prev;
				if (curr->prev != NULL) {
					curr->prev->next = new_node;
				}
				new_node->next = curr;
				curr->prev = new_node;
				if (curr == mm->head) {
					mm->head = new_node;
				}
				err = mm->slot_alloc(mm->slot_alloc_inst, 1, &(new_node->cap.cap));
				if (err_is_fail(err)) {
			        return err;
			    }
				err = cap_retype(new_node->cap.cap, mm->initial_cap, (curr->base - mm->initial_base) + curr_offset, mm->objtype, size, 1);
				if (err_is_fail(err)) {
			        return err;
			    }
				new_node->base = curr->base + curr_offset;
				new_node->size = size;
				curr->base += size + curr_offset;
				curr->size = remaining;
				if (curr->size == 0) {
					curr->prev->next = curr->next;
					curr->next->prev = curr->prev;
					slab_free(&mm->slabs, curr);
				}
				if (curr_offset > 0) {
					struct mmnode *offset_node = (struct mmnode*) slab_alloc(&mm->slabs);
					assert(offset_node != NULL);
					offset_node->type = NodeType_Free;
					offset_node->prev = new_node->prev;
					if (new_node->prev != NULL) {
						new_node->prev->next = offset_node;
					}
					offset_node->next = new_node;
					new_node->prev = offset_node;
					if (new_node == mm->head) {
						mm->head = offset_node;
					}
					offset_node->base = new_node->base - curr_offset;
					offset_node->size = curr_offset;
				}
				*retcap = new_node->cap.cap;
				break;
			}
		}
		curr = curr->next;
	}
	return SYS_ERR_OK;
}
errval_t mm_alloc_aligned ( struct mm * mm , size_t size , size_t alignment , struct capref * retcap ) { struct slot_prealloc * sp = ( struct slot_prealloc * ) mm -> slot_alloc_inst ; if ( sp -> meta [ 0 ] . free < 3 && sp -> meta [ 1 ] . free < 3 && ! sp -> refilling ) { sp -> refilling = true ; errval_t err = mm -> slot_refill ( mm -> slot_alloc_inst ) ; sp -> refilling = false ; assert ( err_is_ok ( err ) ) ; } if ( size % BASE_PAGE_SIZE != 0 ) { size += BASE_PAGE_SIZE - ( size % BASE_PAGE_SIZE ) ; } struct mmnode * curr = mm -> head ; while ( curr ) { if ( curr -> type == NodeType_Free ) { size_t curr_offset = curr -> base % alignment == 0 ? 0 : alignment - ( curr -> base % alignment ) ; if ( curr_offset + size <= curr -> size ) { size_t remaining = curr -> size - size - curr_offset ; errval_t err ; if ( slab_freecount ( & mm -> slabs ) < 4 && ! mm -> refillingslabs ) { mm -> refillingslabs = true ; err = mm -> slabs . refill_func ( & mm -> slabs ) ; mm -> refillingslabs = false ; if ( err_is_fail ( err ) ) { return err ; } } struct mmnode * new_node = ( struct mmnode * ) slab_alloc ( & mm -> slabs ) ; assert ( new_node != NULL ) ; new_node -> type = NodeType_Allocated ; new_node -> prev = curr -> prev ; if ( curr -> prev != NULL ) { curr -> prev -> next = new_node ; } new_node -> next = curr ; curr -> prev = new_node ; if ( curr == mm -> head ) { mm -> head = new_node ; } err = mm -> slot_alloc ( mm -> slot_alloc_inst , 1 , & ( new_node -> cap . cap ) ) ; if ( err_is_fail ( err ) ) { return err ; } err = cap_retype ( new_node -> cap . cap , mm -> initial_cap , ( curr -> base - mm -> initial_base ) + curr_offset , mm -> objtype , size , 1 ) ; if ( err_is_fail ( err ) ) { return err ; } new_node -> base = curr -> base + curr_offset ; new_node -> size = size ; curr -> base += size + curr_offset ; curr -> size = remaining ; if ( curr -> size == 0 ) { curr -> prev -> next = curr -> next ; curr -> next -> prev = curr -> prev ; slab_free ( & mm -> slabs , curr ) ; } if ( curr_offset > 0 ) { struct mmnode * offset_node = ( struct mmnode * ) slab_alloc ( & mm -> slabs ) ; assert ( offset_node != NULL ) ; offset_node -> type = NodeType_Free ; offset_node -> prev = new_node -> prev ; if ( new_node -> prev != NULL ) { new_node -> prev -> next = offset_node ; } offset_node -> next = new_node ; new_node -> prev = offset_node ; if ( new_node == mm -> head ) { mm -> head = offset_node ; } offset_node -> base = new_node -> base - curr_offset ; offset_node -> size = curr_offset ; } * retcap = new_node -> cap . cap ; break ; } } curr = curr -> next ; } return SYS_ERR_OK ; }
Allocate aligned physical memory.
Allocate aligned physical memory .
// round the size to the nearest page size multiple // offset into curr node to actually start at because of alignment // remove curr if its size is 0 // add pre-offset node if curr_offset does not equal 0