ウォンツテック

そでやまのーと

OSを作る


メモリ管理の実装大体完了。マクロを使って以前のよりすっきり書いた(つもり。。)
メモリ管理も書いたし、次は頓挫してたFDCドライバーかな。
とりあえず1セクタの読み書きを目指そう。

memory.h

#ifndef _MEMORY_H
#define _MEMORY_H

#include "types.h"
#include "bootmiddle.h"

#define MAX_MHOLES 8192
#define KERNEL_MEMBASE 0x100000

#define MIN_MEMSIZE 32

#define KFREE_OK 1
#define KFREE_FAIL 0

typedef struct _MemHole {
  u_int32_t	base;
  u_int32_t size;
  struct _MemHole*	prev;
  struct _MemHole*	next;
} MemHole;

MemHole memhole[MAX_MHOLES];

MemHole mfree_list;
MemHole	mhole_list;

void init_mem();
MemHole* kalloc(u_int32_t size);
int32_t kfree(MemHole* mem);
void sysPrintMem();

#define MHOLE_REMOVE(p) do {	\
	p->prev->next = p->next;	\
	p->next->prev = p->prev;	\
  } while(0)

#define MHOLES_REMOVE(to, from) do {	\
	to->prev->next = from->next;		\
	from->next->prev = to->prev;		\
  } while(0)

#define MHOLE_CLEAN(p) do {		\
	p->base = 0;				\
	p->size = 0;				\
  } while (0)

#define MHOLE_INSERT_HEAD(p, head) do {	\
	head.next->prev = p;				\
	p->next = head.next;				\
	head.next = p;						\
	p->prev = &head;					\
  } while(0)

#define MHOLE_INSERT_TAIL(p, head) do { \
	head.prev->next = p;				\
	p->prev = head.prev;				\
	head.prev = p;						\
	p->next = &head;					\
  } while(0)

#define MHOLE_INSERT_BEFORE(p, ep) do { \
	ep->prev->next = p;					\
	p->prev = ep->prev;					\
	ep->prev = p;						\
	p->next = ep;						\
  } while(0)

#define MHOLE_INSERT_AFTER(p, ep) do {	\
	ep->next->prev = p;					\
	p->next = ep->next;					\
	ep->next = p;						\
	p->prev = ep;						\
  } while(0)
	

#endif /* _MEMORY_H */

memory.c

/*
 *  @File		 memory.c
 *  @Brief		 manage the memory for kernel
 *  
 *  @Author		 Sodex
 *  @Revision	 0.1
 *  @License	 suspension
 *  @Date		 creae:	2007/04/25  update:	2007/04/25	
 *		
 *	Copyright (C) 2007 Sodex
 */

#include "memory.h"
#include "vga.h"

static void merge_hole(MemHole* memfrom, MemHole* memto);
static MemHole* newMhole();

void init_mem()
{
  int i;
  for (i = 0; i < MAX_MHOLES; ++i) {
	if (i == MAX_MHOLES - 1)
	  memhole[i].next = &mhole_list;
	else
	  memhole[i].next = &memhole[i+1];

	if (i == 0)
	  memhole[i].prev = &mhole_list;
	else
	  memhole[i].prev = &memhole[i-1];
  }
  mhole_list.next = &memhole[0];
  mhole_list.prev = &memhole[MAX_MHOLES-1];
  memhole[0].prev = &mhole_list;
  memhole[MAX_MHOLES-1].next = &mhole_list;

  mhole_list.base = 0;
  mhole_list.size = 0;
  mfree_list.base = 0;
  mfree_list.size = 0;

  //initial mfree_list setting
  mfree_list.next = &mfree_list;
  mfree_list.prev = &mfree_list;

  MemHole* mem = mhole_list.next;
  MHOLE_REMOVE(mem);
  MHOLE_INSERT_HEAD(mem, mfree_list);
  mfree_list.next->base = KERNEL_MEMBASE;
  mfree_list.next->size = MAXMEMSIZE - KERNEL_MEMBASE;
}

int32_t kfree(MemHole* mem)
{
  // We use the first-fit-algorithm for searching right base.
  MemHole* i;
  for (i = mfree_list.next; i != &mfree_list; i = i->next) {
	if (i->base > mem->base) {
	  if (mem->base + mem->size > i->base)
		return KFREE_FAIL;
	  MHOLE_INSERT_BEFORE(mem, i);
	}
  }

  /* Although mem->prev == &mfree_list, mfree_list's base + its size never
   *  equal this mem base, because mfree_list's base and size is always 0
   *  and all mem's base is not 0.
   * Likewise, if mem->next == &mfree_list, this mem's base + size never 
   *  equal mfree_list's base.
   */
  if (mem->prev->base + mem->prev->size == mem->base &&
		mem->base + mem->size == mem->next->base) {
	merge_hole(mem->prev, mem->next);
  } else if (mem->prev->base + mem->prev->size == mem->base) {
	merge_hole(mem->prev, mem);
  } else if (mem->base + mem->size == mem->next->base) {
	merge_hole(mem, mem->next);
  } else {
	return KFREE_FAIL;
  }
  return KFREE_OK;
}

static void merge_hole(MemHole* memfrom, MemHole* memto)
{
  MemHole *i, *j, *next;
  for (i = memfrom->next; i != memto->next; i = i->next) {
	memfrom->size += i->size;
  }

  i = memfrom->next;
  next = memto->next;
  while (i != next) {
	j = i->next;
	MHOLE_REMOVE(i);
	MHOLE_CLEAN(i);
	MHOLE_INSERT_HEAD(i, mhole_list);
	i = j;
  }
}

MemHole* kalloc(u_int32_t size)
{
  MemHole *i, *new;
  for (i = mfree_list.next; i != &mfree_list; i = i->next) {
	if (i->size > size) {
	  if (i->size - size > MIN_MEMSIZE) {
		new = newMhole();
		if (new == NULL)
		  sysPrints("newMhole() error\n");
		new->base = i->base;
		new->size = size;
		i->base += size;
		i->size -= size;
		return new;
	  } else {
		MHOLE_REMOVE(i);
		return i;
	  }
	} else if (i->size == size) {
	  MHOLE_REMOVE(i);
	  return i;
	}
  }
  return NULL;
}

static MemHole* newMhole()
{
  MemHole* ret;
  
  ret = mhole_list.next;
  MHOLE_REMOVE(ret);

  return ret;
}

void sysPrintMem()
{
  u_int8_t count = 0;
  MemHole* i;
  for (i = mfree_list.next; i != &mfree_list; i = i->next) {
	sysPrints("Memhole base = ");
	sysPrintBin32(i->base);
	sysPrintc(' ');
	sysPrints("Memhole size = ");
	sysPrintBin32(i->size);
	sysPrintc('\n');
	count++;
  }
  sysPrints("The num of mfree_list is ");
  sysPrintBin(count);
  sysPrints("\n");
}

kernel.c

メモリ管理テスト

#include "bootmiddle.h"
#include "kernel.h"
#include "descriptor.h"
#include "vga.h"
#include "memory.h"


void startKernel()
{
  init_setupgdt();
  init_setupidthandlers();
  init_setupidt();
  init_mem();
  sysScreenInitial();

  //for memory test
  sysPrintMem();
  MemHole *new1, *new2, *new3, *new4;
  new1 = kalloc(512);
  if (new1 == NULL)
	sysPrints("kalloc error\n");
  sysPrintMem();
  
  new2 = kalloc(256);
  if (new2 == NULL)
	sysPrints("kalloc error\n");
  sysPrintMem();

  new3 = kalloc(256);
  if (new3 == NULL)
	sysPrints("kalloc error\n");
  sysPrintMem();

  new4 = kalloc(1024);
  if (new4 == NULL)
	sysPrints("kalloc error\n");
  sysPrintMem();

  kfree(new2);
  sysPrintMem();

  kfree(new3);
  sysPrintMem();

  kfree(new4);
  sysPrintMem();

  for(;;);
}