From 68726f76fd97c88a588cbf4f7ce186ccea972892 Mon Sep 17 00:00:00 2001 From: KoderuNoKo <4trung9kien123@gmail.com> Date: Wed, 8 May 2024 08:31:31 +0700 Subject: [PATCH 1/2] origin source The original source code --- Makefile | 51 +++ include/bitops.h | 37 ++ include/common.h | 93 +++++ include/cpu.h | 13 + include/loader.h | 9 + include/mem.h | 32 ++ include/mm.h | 167 ++++++++ include/os-cfg.h | 16 + include/os-mm.h | 85 ++++ include/queue.h | 21 + include/sched.h | 28 ++ include/timer.h | 28 ++ input/os_0_mlq_paging | 4 + input/os_1_mlq_paging | 10 + input/os_1_mlq_paging_small_1K | 10 + input/os_1_mlq_paging_small_4K | 10 + input/os_1_singleCPU_mlq | 9 + input/os_1_singleCPU_mlq_paging | 10 + input/os_1_tlbsz_singleCPU_mlq | 10 + input/proc/m0s | 7 + input/proc/m1s | 7 + input/proc/p0s | 11 + input/proc/p1s | 12 + input/proc/p2s | 14 + input/proc/p3s | 18 + input/proc/s0 | 16 + input/proc/s1 | 8 + input/proc/s2 | 14 + input/proc/s3 | 18 + input/proc/s4 | 30 ++ input/sched | 4 + input/sched_0 | 3 + input/sched_1 | 5 + output/os_0_mlq_paging.output | 78 ++++ output/os_1_mlq_paging.output | 173 ++++++++ output/os_1_mlq_paging_small_1K.output | 171 ++++++++ output/os_1_mlq_paging_small_4K.output | 172 ++++++++ output/os_1_singleCPU_mlq.output | 185 +++++++++ output/os_1_singleCPU_mlq_paging.output | 185 +++++++++ output/sched.output | 42 ++ output/sched_0.output | 68 +++ output/sched_1.output | 132 ++++++ src/cpu-tlb.c | 144 +++++++ src/cpu-tlbcache.c | 119 ++++++ src/cpu.c | 104 +++++ src/loader.c | 91 ++++ src/mem.c | 173 ++++++++ src/mm-memphy.c | 199 +++++++++ src/mm-vm.c | 526 ++++++++++++++++++++++++ src/mm.c | 347 ++++++++++++++++ src/os.c | 309 ++++++++++++++ src/paging.c | 18 + src/queue.c | 20 + src/sched.c | 99 +++++ src/timer.c | 136 ++++++ 55 files changed, 4301 insertions(+) create mode 100644 Makefile create mode 100644 include/bitops.h create mode 100644 include/common.h create mode 100644 include/cpu.h create mode 100644 include/loader.h create mode 100644 include/mem.h create mode 100644 include/mm.h create mode 100644 include/os-cfg.h create mode 100644 include/os-mm.h create mode 100644 include/queue.h create mode 100644 include/sched.h create mode 100644 include/timer.h create mode 100644 input/os_0_mlq_paging create mode 100644 input/os_1_mlq_paging create mode 100644 input/os_1_mlq_paging_small_1K create mode 100644 input/os_1_mlq_paging_small_4K create mode 100644 input/os_1_singleCPU_mlq create mode 100644 input/os_1_singleCPU_mlq_paging create mode 100644 input/os_1_tlbsz_singleCPU_mlq create mode 100644 input/proc/m0s create mode 100644 input/proc/m1s create mode 100644 input/proc/p0s create mode 100644 input/proc/p1s create mode 100644 input/proc/p2s create mode 100644 input/proc/p3s create mode 100644 input/proc/s0 create mode 100644 input/proc/s1 create mode 100644 input/proc/s2 create mode 100644 input/proc/s3 create mode 100644 input/proc/s4 create mode 100644 input/sched create mode 100644 input/sched_0 create mode 100644 input/sched_1 create mode 100644 output/os_0_mlq_paging.output create mode 100644 output/os_1_mlq_paging.output create mode 100644 output/os_1_mlq_paging_small_1K.output create mode 100644 output/os_1_mlq_paging_small_4K.output create mode 100644 output/os_1_singleCPU_mlq.output create mode 100644 output/os_1_singleCPU_mlq_paging.output create mode 100644 output/sched.output create mode 100644 output/sched_0.output create mode 100644 output/sched_1.output create mode 100644 src/cpu-tlb.c create mode 100644 src/cpu-tlbcache.c create mode 100644 src/cpu.c create mode 100644 src/loader.c create mode 100644 src/mem.c create mode 100644 src/mm-memphy.c create mode 100644 src/mm-vm.c create mode 100644 src/mm.c create mode 100644 src/os.c create mode 100644 src/paging.c create mode 100644 src/queue.c create mode 100644 src/sched.c create mode 100644 src/timer.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5e189c0 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ + +INC = -Iinclude +LIB = -lpthread + +SRC = src +OBJ = obj +INCLUDE = include + +CC = gcc +DEBUG = -g +CFLAGS = -Wall -c $(DEBUG) +LFLAGS = -Wall $(DEBUG) + +vpath %.c $(SRC) +vpath %.h $(INCLUDE) + +MAKE = $(CC) $(INC) + +# Object files needed by modules +MEM_OBJ = $(addprefix $(OBJ)/, paging.o mem.o cpu.o loader.o) +TLB_OBJ = $(addprefix $(OBJ)/, cpu-tlb.o cpu-tlbcache.o) +OS_OBJ = $(addprefix $(OBJ)/, cpu.o cpu-tlb.o cpu-tlbcache.o mem.o loader.o queue.o os.o sched.o timer.o mm-vm.o mm.o mm-memphy.o) +SCHED_OBJ = $(addprefix $(OBJ)/, cpu.o loader.o) +HEADER = $(wildcard $(INCLUDE)/*.h) + +all: os +#mem sched os + +# Just compile memory management modules +mem: $(MEM_OBJ) $(TLB_OBJ) + $(MAKE) $(LFLAGS) $(MEM_OBJ) $(TLB_OBJ) -o mem $(LIB) + +# Just compile scheduler +sched: $(SCHED_OBJ) + $(MAKE) $(LFLAGS) $(MEM_OBJ) -o sched $(LIB) + +# Compile the whole OS simulation +os: $(OS_OBJ) + $(MAKE) $(LFLAGS) $(OS_OBJ) -o os $(LIB) + +$(OBJ)/%.o: %.c ${HEADER} $(OBJ) + $(MAKE) $(CFLAGS) $< -o $@ + +# Prepare objectives container +$(OBJ): + mkdir -p $(OBJ) + +clean: + rm -f $(OBJ)/*.o os sched mem + rm -r $(OBJ) + diff --git a/include/bitops.h b/include/bitops.h new file mode 100644 index 0000000..0cc9413 --- /dev/null +++ b/include/bitops.h @@ -0,0 +1,37 @@ +#ifdef CONFIG_64BIT +#define BITS_PER_LONG 64 +#else +#define BITS_PER_LONG 32 +#endif /* CONFIG_64BIT */ + +#define BITS_PER_BYTE 8 +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + +#define BIT(nr) (1U << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) + +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) + +#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK(h, l) \ + (((~0U) << (l)) & (~0U >> (BITS_PER_LONG - (h) - 1))) + +#define NBITS2(n) ((n&2)?1:0) +#define NBITS4(n) ((n&(0xC))?(2+NBITS2(n>>2)):(NBITS2(n))) +#define NBITS8(n) ((n&0xF0)?(4+NBITS4(n>>4)):(NBITS4(n))) +#define NBITS16(n) ((n&0xFF00)?(8+NBITS8(n>>8)):(NBITS8(n))) +#define NBITS32(n) ((n&0xFFFF0000)?(16+NBITS16(n>>16)):(NBITS16(n))) +#define NBITS(n) (n==0?0:NBITS32(n)) + +#define EXTRACT_NBITS(nr, h, l) ((nr&GENMASK(h,l)) >> l) diff --git a/include/common.h b/include/common.h new file mode 100644 index 0000000..8df8770 --- /dev/null +++ b/include/common.h @@ -0,0 +1,93 @@ +#ifndef COMMON_H +#define COMMON_H + +/* Define structs and routine could be used by every source files */ + +#include + +#ifndef OSCFG_H +#include "os-cfg.h" +#endif + +#ifndef OSMM_H +#include "os-mm.h" +#endif + +#define ADDRESS_SIZE 20 +#define OFFSET_LEN 10 +#define FIRST_LV_LEN 5 +#define SECOND_LV_LEN 5 +#define SEGMENT_LEN FIRST_LV_LEN +#define PAGE_LEN SECOND_LV_LEN + +#define NUM_PAGES (1 << (ADDRESS_SIZE - OFFSET_LEN)) +#define PAGE_SIZE (1 << OFFSET_LEN) + +enum ins_opcode_t { + CALC, // Just perform calculation, only use CPU + ALLOC, // Allocate memory + FREE, // Deallocated a memory block + READ, // Write data to a byte on memory + WRITE // Read data from a byte on memory +}; + +/* instructions executed by the CPU */ +struct inst_t { + enum ins_opcode_t opcode; + uint32_t arg_0; // Argument lists for instructions + uint32_t arg_1; + uint32_t arg_2; +}; + +struct code_seg_t { + struct inst_t * text; + uint32_t size; +}; + +struct trans_table_t { + /* A row in the page table of the second layer */ + struct { + addr_t v_index; // The index of virtual address + addr_t p_index; // The index of physical address + } table[1 << SECOND_LV_LEN]; + int size; +}; + +/* Mapping virtual addresses and physical ones */ +struct page_table_t { + /* Translation table for the first layer */ + struct { + addr_t v_index; // Virtual index + struct trans_table_t * next_lv; + } table[1 << FIRST_LV_LEN]; + int size; // Number of row in the first layer +}; + +/* PCB, describe information about a process */ +struct pcb_t { + uint32_t pid; // PID + uint32_t priority; // Default priority, this legacy (FIXED) value depend on process itself + struct code_seg_t * code; // Code segment + addr_t regs[10]; // Registers, store address of allocated regions + uint32_t pc; // Program pointer, point to the next instruction +#ifdef MLQ_SCHED + // Priority on execution (if supported), on-fly aka. changeable + // and this vale overwrites the default priority when it existed + uint32_t prio; +#endif +#ifdef CPU_TLB + struct memphy_struct *tlb; +#endif +#ifdef MM_PAGING + struct mm_struct *mm; + struct memphy_struct *mram; + struct memphy_struct **mswp; + struct memphy_struct *active_mswp; +#endif + struct page_table_t * page_table; // Page table + uint32_t bp; // Break pointer + +}; + +#endif + diff --git a/include/cpu.h b/include/cpu.h new file mode 100644 index 0000000..0b95b07 --- /dev/null +++ b/include/cpu.h @@ -0,0 +1,13 @@ + +#ifndef CPU_H +#define CPU_H + +#include "common.h" + +/* Execute an instruction of a process. Return 0 + * if the instruction is executed successfully. + * Otherwise, return 1. */ +int run(struct pcb_t * proc); + +#endif + diff --git a/include/loader.h b/include/loader.h new file mode 100644 index 0000000..8fedc07 --- /dev/null +++ b/include/loader.h @@ -0,0 +1,9 @@ +#ifndef LOADER_H +#define LOADER_H + +#include "common.h" + +struct pcb_t * load(const char * path); + +#endif + diff --git a/include/mem.h b/include/mem.h new file mode 100644 index 0000000..3c2f5a3 --- /dev/null +++ b/include/mem.h @@ -0,0 +1,32 @@ +#ifndef MEM_H +#define MEM_H + +#include "common.h" + +#define RAM_SIZE (1 << ADDRESS_SIZE) + +/* Init related parameters, must be called before being used */ +void init_mem(void); + +/* Allocate [size] bytes for process [proc] and return its virtual address. + * If we cannot allocate new memory region for this process, return 0 */ +addr_t alloc_mem(uint32_t size, struct pcb_t * proc); + +/* Free a memory block having the first byte at [address] used by + * process [proc]. Return 0 if [address] is valid. Otherwise, return 1 */ +int free_mem(addr_t address, struct pcb_t * proc); + +/* Read 1 byte memory pointed by [address] used by process [proc] and + * save it to [data]. + * If the given [address] is valid, return 0. Otherwise, return 1 */ +int read_mem(addr_t address, struct pcb_t * proc, BYTE * data); + +/* Write [data] to 1 byte on the memory pointed by [address] of process + * [proc]. If given [address] is valid, return 0. Otherwise, return 1 */ +int write_mem(addr_t address, struct pcb_t * proc, BYTE data); + +void dump(void); + +#endif + + diff --git a/include/mm.h b/include/mm.h new file mode 100644 index 0000000..464a88a --- /dev/null +++ b/include/mm.h @@ -0,0 +1,167 @@ +#ifndef MM_H + +#include "bitops.h" +#include "common.h" + +/* CPU Bus definition */ +#define PAGING_CPU_BUS_WIDTH 22 /* 22bit bus - MAX SPACE 4MB */ +#define PAGING_PAGESZ 256 /* 256B or 8-bits PAGE NUMBER */ +#define PAGING_MEMRAMSZ BIT(10) /* 1MB */ +#define PAGING_PAGE_ALIGNSZ(sz) (DIV_ROUND_UP(sz,PAGING_PAGESZ)*PAGING_PAGESZ) + +#define PAGING_MEMSWPSZ BIT(14) /* 16MB */ +#define PAGING_SWPFPN_OFFSET 5 +#define PAGING_MAX_PGN (DIV_ROUND_UP(BIT(PAGING_CPU_BUS_WIDTH),PAGING_PAGESZ)) + +#define PAGING_SBRK_INIT_SZ PAGING_PAGESZ +/* PTE BIT */ +#define PAGING_PTE_PRESENT_MASK BIT(31) +#define PAGING_PTE_SWAPPED_MASK BIT(30) +#define PAGING_PTE_RESERVE_MASK BIT(29) +#define PAGING_PTE_DIRTY_MASK BIT(28) +#define PAGING_PTE_EMPTY01_MASK BIT(14) +#define PAGING_PTE_EMPTY02_MASK BIT(13) + +/* PTE BIT PRESENT */ +#define PAGING_PTE_SET_PRESENT(pte) (pte=pte|PAGING_PTE_PRESENT_MASK) +#define PAGING_PAGE_PRESENT(pte) (pte&PAGING_PTE_PRESENT_MASK) + +/* USRNUM */ +#define PAGING_PTE_USRNUM_LOBIT 15 +#define PAGING_PTE_USRNUM_HIBIT 27 +/* FPN */ +#define PAGING_PTE_FPN_LOBIT 0 +#define PAGING_PTE_FPN_HIBIT 12 +/* SWPTYP */ +#define PAGING_PTE_SWPTYP_LOBIT 0 +#define PAGING_PTE_SWPTYP_HIBIT 4 +/* SWPOFF */ +#define PAGING_PTE_SWPOFF_LOBIT 5 +#define PAGING_PTE_SWPOFF_HIBIT 25 + +/* PTE masks */ +#define PAGING_PTE_USRNUM_MASK GENMASK(PAGING_PTE_USRNUM_HIBIT,PAGING_PTE_USRNUM_LOBIT) +#define PAGING_PTE_FPN_MASK GENMASK(PAGING_PTE_FPN_HIBIT,PAGING_PTE_FPN_LOBIT) +#define PAGING_PTE_SWPTYP_MASK GENMASK(PAGING_PTE_SWPTYP_HIBIT,PAGING_PTE_SWPTYP_LOBIT) +#define PAGING_PTE_SWPOFF_MASK GENMASK(PAGING_PTE_SWPOFF_HIBIT,PAGING_PTE_SWPOFF_LOBIT) + +/* OFFSET */ +#define PAGING_ADDR_OFFST_LOBIT 0 +#define PAGING_ADDR_OFFST_HIBIT (NBITS(PAGING_PAGESZ) - 1) + +/* PAGE Num */ +#define PAGING_ADDR_PGN_LOBIT NBITS(PAGING_PAGESZ) +#define PAGING_ADDR_PGN_HIBIT (PAGING_CPU_BUS_WIDTH - 1) + +/* Frame PHY Num */ +#define PAGING_ADDR_FPN_LOBIT NBITS(PAGING_PAGESZ) +#define PAGING_ADDR_FPN_HIBIT (NBITS(PAGING_MEMRAMSZ) - 1) + +/* SWAPFPN */ +#define PAGING_SWP_LOBIT NBITS(PAGING_PAGESZ) +#define PAGING_SWP_HIBIT (NBITS(PAGING_MEMSWPSZ) - 1) +#define PAGING_SWP(pte) ((pte&PAGING_SWP_MASK) >> PAGING_SWPFPN_OFFSET) + +/* Value operators */ +#define SETBIT(v,mask) (v=v|mask) +#define CLRBIT(v,mask) (v=v&~mask) + +#define SETVAL(v,value,mask,offst) (v=(v&~mask)|((value<>offst) + +/* Other masks */ +#define PAGING_OFFST_MASK GENMASK(PAGING_ADDR_OFFST_HIBIT,PAGING_ADDR_OFFST_LOBIT) +#define PAGING_PGN_MASK GENMASK(PAGING_ADDR_PGN_HIBIT,PAGING_ADDR_PGN_LOBIT) +#define PAGING_FPN_MASK GENMASK(PAGING_ADDR_FPN_HIBIT,PAGING_ADDR_FPN_LOBIT) +#define PAGING_SWP_MASK GENMASK(PAGING_SWP_HIBIT,PAGING_SWP_LOBIT) + +/* Extract OFFSET */ +//#define PAGING_OFFST(x) ((x&PAGING_OFFST_MASK) >> PAGING_ADDR_OFFST_LOBIT) +#define PAGING_OFFST(x) GETVAL(x,PAGING_OFFST_MASK,PAGING_ADDR_OFFST_LOBIT) +/* Extract Page Number*/ +#define PAGING_PGN(x) GETVAL(x,PAGING_PGN_MASK,PAGING_ADDR_PGN_LOBIT) +/* Extract FramePHY Number*/ +#define PAGING_FPN(x) GETVAL(x,PAGING_FPN_MASK,PAGING_ADDR_FPN_LOBIT) +/* Extract SWAPFPN */ +#define PAGING_PGN(x) GETVAL(x,PAGING_PGN_MASK,PAGING_ADDR_PGN_LOBIT) +/* Extract SWAPTYPE */ +#define PAGING_FPN(x) GETVAL(x,PAGING_FPN_MASK,PAGING_ADDR_FPN_LOBIT) + +/* Memory range operator */ +#define INCLUDE(x1,x2,y1,y2) (((y1-x1)*(x2-y2)>=0)?1:0) +#define OVERLAP(x1,x2,y1,y2) (((y2-x1)*(x2-y1)>=0)?1:0) + +/* VM region prototypes */ +struct vm_rg_struct * init_vm_rg(int rg_start, int rg_endi); +int enlist_vm_rg_node(struct vm_rg_struct **rglist, struct vm_rg_struct* rgnode); +int enlist_pgn_node(struct pgn_t **pgnlist, int pgn); +int vmap_page_range(struct pcb_t *caller, int addr, int pgnum, + struct framephy_struct *frames, struct vm_rg_struct *ret_rg); +int vm_map_ram(struct pcb_t *caller, int astart, int send, int mapstart, int incpgnum, struct vm_rg_struct *ret_rg); +int alloc_pages_range(struct pcb_t *caller, int incpgnum, struct framephy_struct **frm_lst); +int __swap_cp_page(struct memphy_struct *mpsrc, int srcfpn, + struct memphy_struct *mpdst, int dstfpn) ; +int pte_set_fpn(uint32_t *pte, int fpn); +int pte_set_swap(uint32_t *pte, int swptyp, int swpoff); +int init_pte(uint32_t *pte, + int pre, // present + int fpn, // FPN + int drt, // dirty + int swp, // swap + int swptyp, // swap type + int swpoff); //swap offset +int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr); +int __free(struct pcb_t *caller, int vmaid, int rgid); +int __read(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE *data); +int __write(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE value); +int init_mm(struct mm_struct *mm, struct pcb_t *caller); + +/* CPUTLB prototypes */ +int tlb_change_all_page_tables_of(struct pcb_t *proc, struct memphy_struct * mp); +int tlb_flush_tlb_of(struct pcb_t *proc, struct memphy_struct * mp); +int tlballoc(struct pcb_t *proc, uint32_t size, uint32_t reg_index); +int tlbfree_data(struct pcb_t *proc, uint32_t reg_index); +int tlbread(struct pcb_t * proc, uint32_t source, uint32_t offset, uint32_t destination) ; +int tlbwrite(struct pcb_t * proc, BYTE data, uint32_t destination, uint32_t offset); +int init_tlbmemphy(struct memphy_struct *mp, int max_size); +int TLBMEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value); +int TLBMEMPHY_write(struct memphy_struct * mp, int addr, BYTE data); +int TLBMEMPHY_dump(struct memphy_struct * mp); + +/* VM prototypes */ +int pgalloc(struct pcb_t *proc, uint32_t size, uint32_t reg_index); +int pgfree_data(struct pcb_t *proc, uint32_t reg_index); +int pgread( + struct pcb_t * proc, // Process executing the instruction + uint32_t source, // Index of source register + uint32_t offset, // Source address = [source] + [offset] + uint32_t destination); +int pgwrite( + struct pcb_t * proc, // Process executing the instruction + BYTE data, // Data to be wrttien into memory + uint32_t destination, // Index of destination register + uint32_t offset); +/* Local VM prototypes */ +struct vm_rg_struct * get_symrg_byid(struct mm_struct* mm, int rgid); +int validate_overlap_vm_area(struct pcb_t *caller, int vmaid, int vmastart, int vmaend); +int get_free_vmrg_area(struct pcb_t *caller, int vmaid, int size, struct vm_rg_struct *newrg); +int inc_vma_limit(struct pcb_t *caller, int vmaid, int inc_sz); +int find_victim_page(struct mm_struct* mm, int *pgn); +struct vm_area_struct *get_vma_by_num(struct mm_struct *mm, int vmaid); + +/* MEM/PHY protypes */ +int MEMPHY_get_freefp(struct memphy_struct *mp, int *fpn); +int MEMPHY_put_freefp(struct memphy_struct *mp, int fpn); +int MEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value); +int MEMPHY_write(struct memphy_struct * mp, int addr, BYTE data); +int MEMPHY_dump(struct memphy_struct * mp); +int init_memphy(struct memphy_struct *mp, int max_size, int randomflg); +/* DEBUG */ +int print_list_fp(struct framephy_struct *fp); +int print_list_rg(struct vm_rg_struct *rg); +int print_list_vma(struct vm_area_struct *rg); + + +int print_list_pgn(struct pgn_t *ip); +int print_pgtbl(struct pcb_t *ip, uint32_t start, uint32_t end); +#endif diff --git a/include/os-cfg.h b/include/os-cfg.h new file mode 100644 index 0000000..18770ea --- /dev/null +++ b/include/os-cfg.h @@ -0,0 +1,16 @@ +#ifndef OSCFG_H +#define OSCFG_H + +#define MLQ_SCHED 1 +#define MAX_PRIO 140 + +#define CPU_TLB +#define CPUTLB_FIXED_TLBSZ +#define MM_PAGING +//#define MM_FIXED_MEMSZ +//#define VMDBG 1 +//#define MMDBG 1 +#define IODUMP 1 +#define PAGETBL_DUMP 1 + +#endif diff --git a/include/os-mm.h b/include/os-mm.h new file mode 100644 index 0000000..80a25aa --- /dev/null +++ b/include/os-mm.h @@ -0,0 +1,85 @@ +#ifndef OSMM_H +#define OSMM_H + +#define MM_PAGING +#define PAGING_MAX_MMSWP 4 /* max number of supported swapped space */ +#define PAGING_MAX_SYMTBL_SZ 30 + +typedef char BYTE; +typedef uint32_t addr_t; +//typedef unsigned int uint32_t; + +struct pgn_t{ + int pgn; + struct pgn_t *pg_next; +}; + +/* + * Memory region struct + */ +struct vm_rg_struct { + unsigned long rg_start; + unsigned long rg_end; + + struct vm_rg_struct *rg_next; +}; + +/* + * Memory area struct + */ +struct vm_area_struct { + unsigned long vm_id; + unsigned long vm_start; + unsigned long vm_end; + + unsigned long sbrk; +/* + * Derived field + * unsigned long vm_limit = vm_end - vm_start + */ + struct mm_struct *vm_mm; + struct vm_rg_struct *vm_freerg_list; + struct vm_area_struct *vm_next; +}; + +/* + * Memory management struct + */ +struct mm_struct { + uint32_t *pgd; + + struct vm_area_struct *mmap; + + /* Currently we support a fixed number of symbol */ + struct vm_rg_struct symrgtbl[PAGING_MAX_SYMTBL_SZ]; + + /* list of free page */ + struct pgn_t *fifo_pgn; +}; + +/* + * FRAME/MEM PHY struct + */ +struct framephy_struct { + int fpn; + struct framephy_struct *fp_next; + + /* Resereed for tracking allocated framed */ + struct mm_struct* owner; +}; + +struct memphy_struct { + /* Basic field of data and size */ + BYTE *storage; + int maxsz; + + /* Sequential device fields */ + int rdmflg; + int cursor; + + /* Management structure */ + struct framephy_struct *free_fp_list; + struct framephy_struct *used_fp_list; +}; + +#endif diff --git a/include/queue.h b/include/queue.h new file mode 100644 index 0000000..a3a833b --- /dev/null +++ b/include/queue.h @@ -0,0 +1,21 @@ + +#ifndef QUEUE_H +#define QUEUE_H + +#include "common.h" + +#define MAX_QUEUE_SIZE 10 + +struct queue_t { + struct pcb_t * proc[MAX_QUEUE_SIZE]; + int size; +}; + +void enqueue(struct queue_t * q, struct pcb_t * proc); + +struct pcb_t * dequeue(struct queue_t * q); + +int empty(struct queue_t * q); + +#endif + diff --git a/include/sched.h b/include/sched.h new file mode 100644 index 0000000..108270d --- /dev/null +++ b/include/sched.h @@ -0,0 +1,28 @@ +#ifndef QUEUE_H +#define QUEUE_H + +#include "common.h" + +#ifndef MLQ_SCHED +#define MLQ_SCHED +#endif + +#define MAX_PRIO 139 + +int queue_empty(void); + +void init_scheduler(void); +void finish_scheduler(void); + +/* Get the next process from ready queue */ +struct pcb_t * get_proc(void); + +/* Put a process back to run queue */ +void put_proc(struct pcb_t * proc); + +/* Add a new process to ready queue */ +void add_proc(struct pcb_t * proc); + +#endif + + diff --git a/include/timer.h b/include/timer.h new file mode 100644 index 0000000..e480b66 --- /dev/null +++ b/include/timer.h @@ -0,0 +1,28 @@ +#ifndef TIMER_H +#define TIMER_H + +#include +#include + +struct timer_id_t { + int done; + int fsh; + pthread_cond_t event_cond; + pthread_mutex_t event_lock; + pthread_cond_t timer_cond; + pthread_mutex_t timer_lock; +}; + +void start_timer(); + +void stop_timer(); + +struct timer_id_t * attach_event(); + +void detach_event(struct timer_id_t * event); + +void next_slot(struct timer_id_t* timer_id); + +uint64_t current_time(); + +#endif diff --git a/input/os_0_mlq_paging b/input/os_0_mlq_paging new file mode 100644 index 0000000..bb66762 --- /dev/null +++ b/input/os_0_mlq_paging @@ -0,0 +1,4 @@ +6 2 4 +1048576 16777216 0 0 0 +0 p0s 0 +2 p1s 15 diff --git a/input/os_1_mlq_paging b/input/os_1_mlq_paging new file mode 100644 index 0000000..bc48a56 --- /dev/null +++ b/input/os_1_mlq_paging @@ -0,0 +1,10 @@ +2 4 8 +1048576 16777216 0 0 0 +1 p0s 130 +2 s3 39 +4 m1s 15 +6 s2 120 +7 m0s 120 +9 p1s 15 +11 s0 38 +16 s1 0 diff --git a/input/os_1_mlq_paging_small_1K b/input/os_1_mlq_paging_small_1K new file mode 100644 index 0000000..8e67bab --- /dev/null +++ b/input/os_1_mlq_paging_small_1K @@ -0,0 +1,10 @@ +2 4 8 +2048 16777216 0 0 0 +1 p0s 130 +2 s3 39 +4 m1s 15 +6 s2 120 +7 m0s 120 +9 p1s 15 +11 s0 38 +16 s1 0 diff --git a/input/os_1_mlq_paging_small_4K b/input/os_1_mlq_paging_small_4K new file mode 100644 index 0000000..ec1fe2e --- /dev/null +++ b/input/os_1_mlq_paging_small_4K @@ -0,0 +1,10 @@ +2 4 8 +4096 16777216 0 0 0 +1 p0s 130 +2 s3 39 +4 m1s 15 +6 s2 120 +7 m0s 120 +9 p1s 15 +11 s0 38 +16 s1 0 diff --git a/input/os_1_singleCPU_mlq b/input/os_1_singleCPU_mlq new file mode 100644 index 0000000..98efc7e --- /dev/null +++ b/input/os_1_singleCPU_mlq @@ -0,0 +1,9 @@ +2 1 8 +1 s4 4 +2 s3 3 +4 m1s 2 +6 s2 3 +7 m0s 3 +9 p1s 2 +11 s0 1 +16 s1 0 diff --git a/input/os_1_singleCPU_mlq_paging b/input/os_1_singleCPU_mlq_paging new file mode 100644 index 0000000..7f00229 --- /dev/null +++ b/input/os_1_singleCPU_mlq_paging @@ -0,0 +1,10 @@ +2 1 8 +1048576 16777216 0 0 0 +1 s4 4 +2 s3 3 +4 m1s 2 +6 s2 3 +7 m0s 3 +9 p1s 2 +11 s0 1 +16 s1 0 diff --git a/input/os_1_tlbsz_singleCPU_mlq b/input/os_1_tlbsz_singleCPU_mlq new file mode 100644 index 0000000..e6ca7b8 --- /dev/null +++ b/input/os_1_tlbsz_singleCPU_mlq @@ -0,0 +1,10 @@ +2 1 8 +40000 +1 s4 4 +2 s3 3 +4 m1s 2 +6 s2 3 +7 m0s 3 +9 p1s 2 +11 s0 1 +16 s1 0 diff --git a/input/proc/m0s b/input/proc/m0s new file mode 100644 index 0000000..170bc31 --- /dev/null +++ b/input/proc/m0s @@ -0,0 +1,7 @@ +1 7 +alloc 300 0 +alloc 100 1 +free 0 +alloc 100 2 +write 102 1 20 +write 1 2 1000 diff --git a/input/proc/m1s b/input/proc/m1s new file mode 100644 index 0000000..62e7ff8 --- /dev/null +++ b/input/proc/m1s @@ -0,0 +1,7 @@ +1 8 +alloc 300 0 +alloc 100 1 +free 0 +alloc 100 2 +free 2 +free 1 diff --git a/input/proc/p0s b/input/proc/p0s new file mode 100644 index 0000000..c0af334 --- /dev/null +++ b/input/proc/p0s @@ -0,0 +1,11 @@ +1 10 +calc +alloc 300 0 +alloc 300 4 +free 0 +alloc 100 1 +write 100 1 20 +read 1 20 20 +write 103 3 20 +read 3 20 20 +free 4 diff --git a/input/proc/p1s b/input/proc/p1s new file mode 100644 index 0000000..79c5fba --- /dev/null +++ b/input/proc/p1s @@ -0,0 +1,12 @@ +1 10 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/p2s b/input/proc/p2s new file mode 100644 index 0000000..ca3391d --- /dev/null +++ b/input/proc/p2s @@ -0,0 +1,14 @@ +20 12 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/p3s b/input/proc/p3s new file mode 100644 index 0000000..bbf1f81 --- /dev/null +++ b/input/proc/p3s @@ -0,0 +1,18 @@ +7 11 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/s0 b/input/proc/s0 new file mode 100644 index 0000000..6186100 --- /dev/null +++ b/input/proc/s0 @@ -0,0 +1,16 @@ +12 15 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/s1 b/input/proc/s1 new file mode 100644 index 0000000..b9e4291 --- /dev/null +++ b/input/proc/s1 @@ -0,0 +1,8 @@ +20 7 +alloc 300 0 +calc +calc +calc +calc +calc +calc diff --git a/input/proc/s2 b/input/proc/s2 new file mode 100644 index 0000000..ca3391d --- /dev/null +++ b/input/proc/s2 @@ -0,0 +1,14 @@ +20 12 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/s3 b/input/proc/s3 new file mode 100644 index 0000000..bbf1f81 --- /dev/null +++ b/input/proc/s3 @@ -0,0 +1,18 @@ +7 11 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/proc/s4 b/input/proc/s4 new file mode 100644 index 0000000..4be85e2 --- /dev/null +++ b/input/proc/s4 @@ -0,0 +1,30 @@ +20 7 +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc +calc diff --git a/input/sched b/input/sched new file mode 100644 index 0000000..9250326 --- /dev/null +++ b/input/sched @@ -0,0 +1,4 @@ +4 2 3 +0 p1 +1 p2 +2 p3 diff --git a/input/sched_0 b/input/sched_0 new file mode 100644 index 0000000..930cea3 --- /dev/null +++ b/input/sched_0 @@ -0,0 +1,3 @@ +2 1 2 +0 s0 +4 s1 diff --git a/input/sched_1 b/input/sched_1 new file mode 100644 index 0000000..c7fac37 --- /dev/null +++ b/input/sched_1 @@ -0,0 +1,5 @@ +2 1 4 +0 s0 +4 s1 +6 s2 +7 s3 diff --git a/output/os_0_mlq_paging.output b/output/os_0_mlq_paging.output new file mode 100644 index 0000000..87d78bc --- /dev/null +++ b/output/os_0_mlq_paging.output @@ -0,0 +1,78 @@ +Time slot 0 +ld_routine + Loaded a process at input/proc/p0s, PID: 1 PRIO: 0 + CPU 0: Dispatched process 1 +Time slot 1 +Time slot 2 + Loaded a process at input/proc/p1s, PID: 2 PRIO: 15 +Time slot 3 + Loaded a process at input/proc/p1s, PID: 3 PRIO: 0 +Time slot 4 + CPU 1: Dispatched process 2 + Loaded a process at input/proc/p1s, PID: 4 PRIO: 0 +Time slot 5 +write region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 6 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 1 +read region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 7 +write region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 8 +read region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 9 +write region=3 offset=20 value=103 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 10 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 4 + CPU 0: Processed 1 has finished + CPU 0: Dispatched process 3 +Time slot 11 +Time slot 12 +Time slot 13 +Time slot 14 +Time slot 15 +Time slot 16 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 2 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 17 +Time slot 18 +Time slot 19 +Time slot 20 + CPU 0: Processed 3 has finished + CPU 0: Dispatched process 4 + CPU 1: Processed 2 has finished + CPU 1 stopped +Time slot 21 +Time slot 22 +Time slot 23 +Time slot 24 + CPU 0: Processed 4 has finished + CPU 0 stopped diff --git a/output/os_1_mlq_paging.output b/output/os_1_mlq_paging.output new file mode 100644 index 0000000..2f675f0 --- /dev/null +++ b/output/os_1_mlq_paging.output @@ -0,0 +1,173 @@ +Time slot 0 +ld_routine +Time slot 1 + Loaded a process at input/proc/p0s, PID: 1 PRIO: 130 +Time slot 2 + CPU 1: Dispatched process 1 + Loaded a process at input/proc/s3, PID: 2 PRIO: 39 +Time slot 3 + CPU 0: Dispatched process 2 +Time slot 4 + CPU 1: Put process 1 to run queue + Loaded a process at input/proc/m1s, PID: 3 PRIO: 15 + CPU 3: Dispatched process 1 +Time slot 5 + CPU 2: Dispatched process 3 + CPU 0: Put process 2 to run queue +Time slot 6 + CPU 0: Dispatched process 2 + Loaded a process at input/proc/s2, PID: 4 PRIO: 120 + CPU 3: Put process 1 to run queue +Time slot 7 + CPU 1: Dispatched process 4 + CPU 2: Put process 3 to run queue + CPU 2: Dispatched process 1 + Loaded a process at input/proc/m0s, PID: 5 PRIO: 120 + CPU 3: Dispatched process 3 +Time slot 8 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 5 +write region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 9 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 2 + CPU 2: Put process 1 to run queue + CPU 2: Dispatched process 4 + Loaded a process at input/proc/p1s, PID: 6 PRIO: 15 + CPU 3: Put process 3 to run queue + CPU 3: Dispatched process 1 +read region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 10 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 3 +write region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 11 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 6 + CPU 2: Put process 4 to run queue + CPU 2: Dispatched process 2 + Loaded a process at input/proc/s0, PID: 7 PRIO: 38 + CPU 3: Put process 1 to run queue + CPU 3: Dispatched process 4 +Time slot 12 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 5 +Time slot 13 + CPU 2: Put process 2 to run queue + CPU 2: Dispatched process 1 +read region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 6 + CPU 3: Put process 4 to run queue + CPU 3: Dispatched process 3 +Time slot 14 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 7 +write region=3 offset=20 value=103 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 15 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 2 + CPU 2: Processed 1 has finished + CPU 2: Dispatched process 4 + CPU 3: Processed 3 has finished + CPU 3: Dispatched process 5 +write region=1 offset=20 value=102 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 +Time slot 16 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 + Loaded a process at input/proc/s1, PID: 8 PRIO: 0 +write region=2 offset=1000 value=1 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 +Time slot 17 + CPU 2: Put process 4 to run queue + CPU 2: Dispatched process 7 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 4 + CPU 3: Put process 5 to run queue + CPU 3: Dispatched process 8 +Time slot 18 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 2 +Time slot 19 + CPU 2: Put process 7 to run queue + CPU 2: Dispatched process 5 +write region=0 offset=0 value=0 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: c0000000 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 6 + CPU 0: Processed 2 has finished + CPU 0: Dispatched process 7 + CPU 3: Put process 8 to run queue + CPU 3: Dispatched process 4 +Time slot 20 + CPU 2: Processed 5 has finished + CPU 2: Dispatched process 8 +Time slot 21 + CPU 1: Put process 6 to run queue + CPU 1 stopped + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 + CPU 3: Processed 4 has finished + CPU 3: Dispatched process 7 +Time slot 22 + CPU 2: Put process 8 to run queue + CPU 2 stopped +Time slot 23 + CPU 0: Processed 6 has finished + CPU 0: Dispatched process 8 + CPU 3: Put process 7 to run queue + CPU 3 stopped +Time slot 24 +Time slot 25 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 26 +Time slot 27 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 8 +Time slot 28 + CPU 0: Processed 8 has finished + CPU 0: Dispatched process 7 +Time slot 29 +Time slot 30 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 31 +Time slot 32 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 33 + CPU 0: Processed 7 has finished + CPU 0 stopped diff --git a/output/os_1_mlq_paging_small_1K.output b/output/os_1_mlq_paging_small_1K.output new file mode 100644 index 0000000..cb2fb07 --- /dev/null +++ b/output/os_1_mlq_paging_small_1K.output @@ -0,0 +1,171 @@ +Time slot 0 +ld_routine +Time slot 1 + Loaded a process at input/proc/p0s, PID: 1 PRIO: 130 + CPU 1: Dispatched process 1 +Time slot 2 + Loaded a process at input/proc/s3, PID: 2 PRIO: 39 +Time slot 3 + CPU 2: Dispatched process 2 + CPU 1: Put process 1 to run queue + CPU 3: Dispatched process 1 +Time slot 4 + Loaded a process at input/proc/m1s, PID: 3 PRIO: 15 +Time slot 5 + CPU 2: Put process 2 to run queue + CPU 0: Dispatched process 3 + CPU 1: Dispatched process 2 + CPU 3: Put process 1 to run queue +Time slot 6 + CPU 2: Dispatched process 1 + Loaded a process at input/proc/s2, PID: 4 PRIO: 120 +Time slot 7 +write region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 4 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 2 + Loaded a process at input/proc/m0s, PID: 5 PRIO: 120 + CPU 3: Dispatched process 3 +Time slot 8 + CPU 2: Put process 1 to run queue + CPU 2: Dispatched process 5 +Time slot 9 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 1 +read region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 4 + Loaded a process at input/proc/p1s, PID: 6 PRIO: 15 + CPU 3: Put process 3 to run queue + CPU 3: Dispatched process 2 +Time slot 10 + CPU 2: Put process 5 to run queue + CPU 2: Dispatched process 3 +write region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 11 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 6 + CPU 1: Put process 1 to run queue + CPU 1: Dispatched process 4 + Loaded a process at input/proc/s0, PID: 7 PRIO: 38 + CPU 3: Put process 2 to run queue + CPU 3: Dispatched process 5 +Time slot 12 + CPU 2: Put process 3 to run queue + CPU 2: Dispatched process 1 +read region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 13 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 3 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 7 +write region=3 offset=20 value=103 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 3: Put process 5 to run queue + CPU 3: Dispatched process 2 +Time slot 14 + CPU 2: Processed 1 has finished + CPU 2: Dispatched process 4 +Time slot 15 + CPU 1: Processed 3 has finished + CPU 1: Dispatched process 5 +write region=1 offset=20 value=102 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 + CPU 3: Put process 2 to run queue + CPU 3: Dispatched process 7 +Time slot 16 +write region=2 offset=1000 value=1 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 + CPU 2: Put process 4 to run queue + CPU 2: Dispatched process 2 + Loaded a process at input/proc/s1, PID: 8 PRIO: 0 +Time slot 17 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 4 + CPU 1: Put process 5 to run queue + CPU 1: Dispatched process 8 + CPU 2: Processed 2 has finished + CPU 2: Dispatched process 6 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 5 +write region=0 offset=0 value=0 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: c0000000 +Time slot 18 + CPU 3: Processed 5 has finished + CPU 3: Dispatched process 7 +Time slot 19 + CPU 2: Put process 6 to run queue + CPU 2 stopped + CPU 1: Put process 8 to run queue + CPU 1: Dispatched process 6 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 8 +Time slot 20 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 4 +Time slot 21 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 7 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 6 +Time slot 22 + CPU 3: Processed 4 has finished + CPU 3: Dispatched process 8 +Time slot 23 + CPU 1: Put process 7 to run queue + CPU 1 stopped + CPU 0: Processed 6 has finished + CPU 0: Dispatched process 7 +Time slot 24 + CPU 3: Put process 8 to run queue + CPU 3 stopped +Time slot 25 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 8 +Time slot 26 + CPU 0: Processed 8 has finished + CPU 0: Dispatched process 7 +Time slot 27 +Time slot 28 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 29 +Time slot 30 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 31 + CPU 0: Processed 7 has finished + CPU 0 stopped diff --git a/output/os_1_mlq_paging_small_4K.output b/output/os_1_mlq_paging_small_4K.output new file mode 100644 index 0000000..25afa10 --- /dev/null +++ b/output/os_1_mlq_paging_small_4K.output @@ -0,0 +1,172 @@ +Time slot 0 +ld_routine +Time slot 1 + Loaded a process at input/proc/p0s, PID: 1 PRIO: 130 + CPU 1: Dispatched process 1 +Time slot 2 + Loaded a process at input/proc/s3, PID: 2 PRIO: 39 +Time slot 3 + CPU 2: Dispatched process 2 + CPU 1: Put process 1 to run queue + CPU 3: Dispatched process 1 +Time slot 4 + Loaded a process at input/proc/m1s, PID: 3 PRIO: 15 +Time slot 5 + CPU 2: Put process 2 to run queue + CPU 0: Dispatched process 3 + CPU 1: Dispatched process 2 + CPU 3: Put process 1 to run queue +Time slot 6 + CPU 2: Dispatched process 1 + Loaded a process at input/proc/s2, PID: 4 PRIO: 120 +Time slot 7 +write region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 4 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 2 + Loaded a process at input/proc/m0s, PID: 5 PRIO: 120 + CPU 3: Dispatched process 3 +Time slot 8 + CPU 2: Put process 1 to run queue + CPU 2: Dispatched process 5 +Time slot 9 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 1 +read region=1 offset=20 value=100 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 4 + Loaded a process at input/proc/p1s, PID: 6 PRIO: 15 + CPU 3: Put process 3 to run queue + CPU 3: Dispatched process 2 +Time slot 10 + CPU 2: Put process 5 to run queue + CPU 2: Dispatched process 3 +write region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 11 + CPU 1: Put process 1 to run queue + CPU 1: Dispatched process 6 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 + Loaded a process at input/proc/s0, PID: 7 PRIO: 38 + CPU 3: Put process 2 to run queue + CPU 3: Dispatched process 5 +Time slot 12 + CPU 2: Put process 3 to run queue + CPU 2: Dispatched process 1 +read region=2 offset=20 value=102 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 +Time slot 13 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 6 +write region=3 offset=20 value=103 +print_pgtbl: 0 - 1024 +00000000: 80000001 +00000004: 80000000 +00000008: 80000003 +00000012: 80000002 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 3 + CPU 3: Put process 5 to run queue + CPU 3: Dispatched process 7 +Time slot 14 + CPU 2: Processed 1 has finished + CPU 2: Dispatched process 2 +Time slot 15 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 4 + CPU 0: Processed 3 has finished + CPU 0: Dispatched process 5 +write region=1 offset=20 value=102 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 6 +Time slot 16 + CPU 2: Put process 2 to run queue + CPU 2: Dispatched process 7 +write region=2 offset=1000 value=1 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: 80000006 + Loaded a process at input/proc/s1, PID: 8 PRIO: 0 +Time slot 17 + CPU 1: Put process 4 to run queue + CPU 1: Dispatched process 2 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 4 + CPU 3: Put process 6 to run queue + CPU 3: Dispatched process 5 +write region=0 offset=0 value=0 +print_pgtbl: 0 - 512 +00000000: 80000007 +00000004: c0000000 +Time slot 18 + CPU 2: Put process 7 to run queue + CPU 2: Dispatched process 8 + CPU 1: Processed 2 has finished + CPU 1: Dispatched process 6 + CPU 3: Processed 5 has finished + CPU 3: Dispatched process 7 +Time slot 19 + CPU 0: Put process 4 to run queue + CPU 0 stopped +Time slot 20 + CPU 2: Put process 8 to run queue + CPU 2: Dispatched process 4 + CPU 1: Put process 6 to run queue + CPU 1: Dispatched process 8 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 6 +Time slot 21 +Time slot 22 + CPU 2: Processed 4 has finished + CPU 2: Dispatched process 7 + CPU 1: Put process 8 to run queue + CPU 1 stopped + CPU 3: Processed 6 has finished + CPU 3: Dispatched process 8 +Time slot 23 +Time slot 24 + CPU 2: Put process 7 to run queue + CPU 2 stopped + CPU 3: Put process 8 to run queue + CPU 3: Dispatched process 7 +Time slot 25 +Time slot 26 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 8 +Time slot 27 + CPU 3: Processed 8 has finished + CPU 3: Dispatched process 7 +Time slot 28 +Time slot 29 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 7 +Time slot 30 +Time slot 31 + CPU 3: Put process 7 to run queue + CPU 3: Dispatched process 7 +Time slot 32 + CPU 3: Processed 7 has finished + CPU 3 stopped diff --git a/output/os_1_singleCPU_mlq.output b/output/os_1_singleCPU_mlq.output new file mode 100644 index 0000000..65a13db --- /dev/null +++ b/output/os_1_singleCPU_mlq.output @@ -0,0 +1,185 @@ +Time slot 0 +ld_routine +Time slot 1 + Loaded a process at input/proc/s4, PID: 1 PRIO: 4 +Time slot 2 + Loaded a process at input/proc/s3, PID: 2 PRIO: 3 +Time slot 3 + CPU 0: Dispatched process 1 +Time slot 4 + Loaded a process at input/proc/m1s, PID: 3 PRIO: 2 +Time slot 5 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 6 + Loaded a process at input/proc/s2, PID: 4 PRIO: 3 +Time slot 7 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 + Loaded a process at input/proc/m0s, PID: 5 PRIO: 3 +Time slot 8 +Time slot 9 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 3 + Loaded a process at input/proc/p1s, PID: 6 PRIO: 2 +Time slot 10 +Time slot 11 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 4 + Loaded a process at input/proc/s0, PID: 7 PRIO: 1 +Time slot 12 +Time slot 13 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 14 +Time slot 15 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 16 + Loaded a process at input/proc/s1, PID: 8 PRIO: 0 +Time slot 17 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 18 +Time slot 19 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 20 +Time slot 21 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 22 +Time slot 23 + CPU 0: Processed 4 has finished + CPU 0: Dispatched process 2 +Time slot 24 +Time slot 25 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 26 +Time slot 27 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 28 +Time slot 29 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 30 +Time slot 31 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 32 + CPU 0: Processed 2 has finished + CPU 0: Dispatched process 5 +Time slot 33 +Time slot 34 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 1 +Time slot 35 +Time slot 36 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 8 +Time slot 37 +Time slot 38 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 39 +Time slot 40 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 3 +Time slot 41 +Time slot 42 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 43 +Time slot 44 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 45 +Time slot 46 + CPU 0: Processed 3 has finished + CPU 0: Dispatched process 6 +Time slot 47 +Time slot 48 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +Time slot 49 +Time slot 50 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 1 +Time slot 51 + CPU 0: Processed 1 has finished + CPU 0: Dispatched process 8 +Time slot 52 +Time slot 53 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 54 +Time slot 55 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 56 +Time slot 57 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +write region=1 offset=20 value=102 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: 80000002 +Time slot 58 +write region=2 offset=1000 value=1 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: 80000002 +Time slot 59 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 8 +Time slot 60 +Time slot 61 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 62 +Time slot 63 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 64 +Time slot 65 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +write region=0 offset=0 value=0 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: c0000000 +Time slot 66 + CPU 0: Processed 5 has finished + CPU 0: Dispatched process 8 +Time slot 67 + CPU 0: Processed 8 has finished + CPU 0: Dispatched process 7 +Time slot 68 +Time slot 69 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 70 +Time slot 71 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 7 +Time slot 72 +Time slot 73 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 74 +Time slot 75 + CPU 0: Processed 6 has finished + CPU 0: Dispatched process 7 +Time slot 76 +Time slot 77 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 78 +Time slot 79 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 80 + CPU 0: Processed 7 has finished + CPU 0 stopped diff --git a/output/os_1_singleCPU_mlq_paging.output b/output/os_1_singleCPU_mlq_paging.output new file mode 100644 index 0000000..65a13db --- /dev/null +++ b/output/os_1_singleCPU_mlq_paging.output @@ -0,0 +1,185 @@ +Time slot 0 +ld_routine +Time slot 1 + Loaded a process at input/proc/s4, PID: 1 PRIO: 4 +Time slot 2 + Loaded a process at input/proc/s3, PID: 2 PRIO: 3 +Time slot 3 + CPU 0: Dispatched process 1 +Time slot 4 + Loaded a process at input/proc/m1s, PID: 3 PRIO: 2 +Time slot 5 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 6 + Loaded a process at input/proc/s2, PID: 4 PRIO: 3 +Time slot 7 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 + Loaded a process at input/proc/m0s, PID: 5 PRIO: 3 +Time slot 8 +Time slot 9 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 3 + Loaded a process at input/proc/p1s, PID: 6 PRIO: 2 +Time slot 10 +Time slot 11 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 4 + Loaded a process at input/proc/s0, PID: 7 PRIO: 1 +Time slot 12 +Time slot 13 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 14 +Time slot 15 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 16 + Loaded a process at input/proc/s1, PID: 8 PRIO: 0 +Time slot 17 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 18 +Time slot 19 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 20 +Time slot 21 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 22 +Time slot 23 + CPU 0: Processed 4 has finished + CPU 0: Dispatched process 2 +Time slot 24 +Time slot 25 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 26 +Time slot 27 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 28 +Time slot 29 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 30 +Time slot 31 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 32 + CPU 0: Processed 2 has finished + CPU 0: Dispatched process 5 +Time slot 33 +Time slot 34 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 1 +Time slot 35 +Time slot 36 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 8 +Time slot 37 +Time slot 38 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 39 +Time slot 40 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 3 +Time slot 41 +Time slot 42 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 43 +Time slot 44 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 45 +Time slot 46 + CPU 0: Processed 3 has finished + CPU 0: Dispatched process 6 +Time slot 47 +Time slot 48 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +Time slot 49 +Time slot 50 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 1 +Time slot 51 + CPU 0: Processed 1 has finished + CPU 0: Dispatched process 8 +Time slot 52 +Time slot 53 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 54 +Time slot 55 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 56 +Time slot 57 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +write region=1 offset=20 value=102 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: 80000002 +Time slot 58 +write region=2 offset=1000 value=1 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: 80000002 +Time slot 59 + CPU 0: Put process 5 to run queue + CPU 0: Dispatched process 8 +Time slot 60 +Time slot 61 + CPU 0: Put process 8 to run queue + CPU 0: Dispatched process 7 +Time slot 62 +Time slot 63 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 64 +Time slot 65 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 5 +write region=0 offset=0 value=0 +print_pgtbl: 0 - 512 +00000000: 80000003 +00000004: c0000000 +Time slot 66 + CPU 0: Processed 5 has finished + CPU 0: Dispatched process 8 +Time slot 67 + CPU 0: Processed 8 has finished + CPU 0: Dispatched process 7 +Time slot 68 +Time slot 69 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 70 +Time slot 71 + CPU 0: Put process 6 to run queue + CPU 0: Dispatched process 7 +Time slot 72 +Time slot 73 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 6 +Time slot 74 +Time slot 75 + CPU 0: Processed 6 has finished + CPU 0: Dispatched process 7 +Time slot 76 +Time slot 77 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 78 +Time slot 79 + CPU 0: Put process 7 to run queue + CPU 0: Dispatched process 7 +Time slot 80 + CPU 0: Processed 7 has finished + CPU 0 stopped diff --git a/output/sched.output b/output/sched.output new file mode 100644 index 0000000..edfe4cf --- /dev/null +++ b/output/sched.output @@ -0,0 +1,42 @@ +Time slot 0 +ld_routine + Loaded a process at input/proc/p1s, PID: 1 PRIO: 1 + CPU 1: Dispatched process 1 +Time slot 1 + Loaded a process at input/proc/p1s, PID: 2 PRIO: 0 +Time slot 2 + Loaded a process at input/proc/p1s, PID: 3 PRIO: 0 +Time slot 3 + CPU 0: Dispatched process 3 +Time slot 4 + CPU 1: Put process 1 to run queue + CPU 1: Dispatched process 2 +Time slot 5 +Time slot 6 +Time slot 7 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 1 +Time slot 8 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 2 +Time slot 9 +Time slot 10 +Time slot 11 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 3 +Time slot 12 + CPU 1: Put process 2 to run queue + CPU 1: Dispatched process 1 +Time slot 13 +Time slot 14 + CPU 1: Processed 1 has finished + CPU 1: Dispatched process 2 +Time slot 15 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 16 + CPU 1: Processed 2 has finished + CPU 1 stopped +Time slot 17 + CPU 0: Processed 3 has finished + CPU 0 stopped diff --git a/output/sched_0.output b/output/sched_0.output new file mode 100644 index 0000000..0676714 --- /dev/null +++ b/output/sched_0.output @@ -0,0 +1,68 @@ +Time slot 0 +ld_routine + Loaded a process at input/proc/s0, PID: 1 PRIO: 4 +Time slot 1 + CPU 0: Dispatched process 1 + Loaded a process at input/proc/s0, PID: 2 PRIO: 0 +Time slot 2 +Time slot 3 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 1 +Time slot 4 +Time slot 5 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 6 +Time slot 7 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 8 +Time slot 9 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 10 +Time slot 11 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 12 +Time slot 13 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 14 +Time slot 15 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 16 +Time slot 17 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 18 +Time slot 19 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 20 +Time slot 21 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 22 +Time slot 23 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 24 +Time slot 25 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 26 +Time slot 27 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 28 + CPU 0: Processed 1 has finished + CPU 0: Dispatched process 2 +Time slot 29 +Time slot 30 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 31 + CPU 0: Processed 2 has finished + CPU 0 stopped diff --git a/output/sched_1.output b/output/sched_1.output new file mode 100644 index 0000000..9c338f7 --- /dev/null +++ b/output/sched_1.output @@ -0,0 +1,132 @@ +Time slot 0 +ld_routine + Loaded a process at input/proc/s0, PID: 1 PRIO: 4 +Time slot 1 + CPU 0: Dispatched process 1 + Loaded a process at input/proc/s0, PID: 2 PRIO: 0 +Time slot 2 + Loaded a process at input/proc/s0, PID: 3 PRIO: 0 +Time slot 3 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 1 + Loaded a process at input/proc/s0, PID: 4 PRIO: 0 +Time slot 4 +Time slot 5 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 4 +Time slot 6 +Time slot 7 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 8 +Time slot 9 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 10 +Time slot 11 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 12 +Time slot 13 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 14 +Time slot 15 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 16 +Time slot 17 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 18 +Time slot 19 + CPU 0: Put process 4 to run queue + CPU 0: Dispatched process 4 +Time slot 20 + CPU 0: Processed 4 has finished + CPU 0: Dispatched process 3 +Time slot 21 +Time slot 22 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 23 +Time slot 24 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 25 +Time slot 26 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 27 +Time slot 28 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 29 +Time slot 30 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 31 +Time slot 32 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 33 +Time slot 34 + CPU 0: Put process 3 to run queue + CPU 0: Dispatched process 3 +Time slot 35 + CPU 0: Processed 3 has finished + CPU 0: Dispatched process 2 +Time slot 36 +Time slot 37 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 38 +Time slot 39 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 40 +Time slot 41 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 42 +Time slot 43 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 44 +Time slot 45 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 46 +Time slot 47 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 48 +Time slot 49 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 50 +Time slot 51 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 52 +Time slot 53 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 54 +Time slot 55 + CPU 0: Put process 1 to run queue + CPU 0: Dispatched process 2 +Time slot 56 +Time slot 57 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 1 +Time slot 58 + CPU 0: Processed 1 has finished + CPU 0: Dispatched process 2 +Time slot 59 +Time slot 60 + CPU 0: Put process 2 to run queue + CPU 0: Dispatched process 2 +Time slot 61 + CPU 0: Processed 2 has finished + CPU 0 stopped diff --git a/src/cpu-tlb.c b/src/cpu-tlb.c new file mode 100644 index 0000000..e5fe767 --- /dev/null +++ b/src/cpu-tlb.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2024 pdnguyen of the HCMC University of Technology + */ +/* + * Source Code License Grant: Authors hereby grants to Licensee + * a personal to use and modify the Licensed Source Code for + * the sole purpose of studying during attending the course CO2018. + */ +//#ifdef CPU_TLB +/* + * CPU TLB + * TLB module cpu/cpu-tlb.c + */ + +#include "mm.h" +#include +#include + +int tlb_change_all_page_tables_of(struct pcb_t *proc, struct memphy_struct * mp) +{ + /* TODO update all page table directory info + * in flush or wipe TLB (if needed) + */ + + return 0; +} + +int tlb_flush_tlb_of(struct pcb_t *proc, struct memphy_struct * mp) +{ + /* TODO flush tlb cached*/ + + return 0; +} + +/*tlballoc - CPU TLB-based allocate a region memory + *@proc: Process executing the instruction + *@size: allocated size + *@reg_index: memory region ID (used to identify variable in symbole table) + */ +int tlballoc(struct pcb_t *proc, uint32_t size, uint32_t reg_index) +{ + int addr, val; + + /* By default using vmaid = 0 */ + val = __alloc(proc, 0, reg_index, size, &addr); + + /* TODO update TLB CACHED frame num of the new allocated page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + + return val; +} + +/*pgfree - CPU TLB-based free a region memory + *@proc: Process executing the instruction + *@size: allocated size + *@reg_index: memory region ID (used to identify variable in symbole table) + */ +int tlbfree_data(struct pcb_t *proc, uint32_t reg_index) +{ + __free(proc, 0, reg_index); + + /* TODO update TLB CACHED frame num of freed page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + + return 0; +} + + +/*tlbread - CPU TLB-based read a region memory + *@proc: Process executing the instruction + *@source: index of source register + *@offset: source address = [source] + [offset] + *@destination: destination storage + */ +int tlbread(struct pcb_t * proc, uint32_t source, + uint32_t offset, uint32_t destination) +{ + BYTE data, frmnum = -1; + + /* TODO retrieve TLB CACHED frame num of accessing page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + /* frmnum is return value of tlb_cache_read/write value*/ + +#ifdef IODUMP + if (frmnum >= 0) + printf("TLB hit at read region=%d offset=%d\n", + source, offset); + else + printf("TLB miss at read region=%d offset=%d\n", + source, offset); +#ifdef PAGETBL_DUMP + print_pgtbl(proc, 0, -1); //print max TBL +#endif + MEMPHY_dump(proc->mram); +#endif + + int val = __read(proc, 0, source, offset, &data); + + destination = (uint32_t) data; + + /* TODO update TLB CACHED with frame num of recent accessing page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + + return val; +} + +/*tlbwrite - CPU TLB-based write a region memory + *@proc: Process executing the instruction + *@data: data to be wrttien into memory + *@destination: index of destination register + *@offset: destination address = [destination] + [offset] + */ +int tlbwrite(struct pcb_t * proc, BYTE data, + uint32_t destination, uint32_t offset) +{ + int val; + BYTE frmnum = -1; + + /* TODO retrieve TLB CACHED frame num of accessing page(s))*/ + /* by using tlb_cache_read()/tlb_cache_write() + frmnum is return value of tlb_cache_read/write value*/ + +#ifdef IODUMP + if (frmnum >= 0) + printf("TLB hit at write region=%d offset=%d value=%d\n", + destination, offset, data); + else + printf("TLB miss at write region=%d offset=%d value=%d\n", + destination, offset, data); +#ifdef PAGETBL_DUMP + print_pgtbl(proc, 0, -1); //print max TBL +#endif + MEMPHY_dump(proc->mram); +#endif + + val = __write(proc, 0, destination, offset, data); + + /* TODO update TLB CACHED with frame num of recent accessing page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + + return val; +} + +//#endif diff --git a/src/cpu-tlbcache.c b/src/cpu-tlbcache.c new file mode 100644 index 0000000..a7a929e --- /dev/null +++ b/src/cpu-tlbcache.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2024 pdnguyen of the HCMC University of Technology + */ +/* + * Source Code License Grant: Authors hereby grants to Licensee + * a personal to use and modify the Licensed Source Code for + * the sole purpose of studying during attending the course CO2018. + */ +//#ifdef MM_TLB +/* + * Memory physical based TLB Cache + * TLB cache module tlb/tlbcache.c + * + * TLB cache is physically memory phy + * supports random access + * and runs at high speed + */ + + +#include "mm.h" +#include + +#define init_tlbcache(mp,sz,...) init_memphy(mp, sz, (1, ##__VA_ARGS__)) + +/* + * tlb_cache_read read TLB cache device + * @mp: memphy struct + * @pid: process id + * @pgnum: page number + * @value: obtained value + */ +int tlb_cache_read(struct memphy_struct * mp, int pid, int pgnum, BYTE value) +{ + /* TODO: the identify info is mapped to + * cache line by employing: + * direct mapped, associated mapping etc. + */ + return 0; +} + +/* + * tlb_cache_write write TLB cache device + * @mp: memphy struct + * @pid: process id + * @pgnum: page number + * @value: obtained value + */ +int tlb_cache_write(struct memphy_struct *mp, int pid, int pgnum, BYTE value) +{ + /* TODO: the identify info is mapped to + * cache line by employing: + * direct mapped, associated mapping etc. + */ + return 0; +} + +/* + * TLBMEMPHY_read natively supports MEMPHY device interfaces + * @mp: memphy struct + * @addr: address + * @value: obtained value + */ +int TLBMEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value) +{ + if (mp == NULL) + return -1; + + /* TLB cached is random access by native */ + *value = mp->storage[addr]; + + return 0; +} + + +/* + * TLBMEMPHY_write natively supports MEMPHY device interfaces + * @mp: memphy struct + * @addr: address + * @data: written data + */ +int TLBMEMPHY_write(struct memphy_struct * mp, int addr, BYTE data) +{ + if (mp == NULL) + return -1; + + /* TLB cached is random access by native */ + mp->storage[addr] = data; + + return 0; +} + +/* + * TLBMEMPHY_format natively supports MEMPHY device interfaces + * @mp: memphy struct + */ +int TLBMEMPHY_dump(struct memphy_struct * mp) +{ + /*TODO dump memphy contnt mp->storage + * for tracing the memory content + */ + + return 0; +} + + +/* + * Init TLBMEMPHY struct + */ +int init_tlbmemphy(struct memphy_struct *mp, int max_size) +{ + mp->storage = (BYTE *)malloc(max_size*sizeof(BYTE)); + mp->maxsz = max_size; + + mp->rdmflg = 1; + + return 0; +} + +//#endif diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 0000000..0dadaa2 --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,104 @@ + +#include "cpu.h" +#include "mem.h" +#include "mm.h" + +int calc(struct pcb_t * proc) { + return ((unsigned long)proc & 0UL); +} + +int alloc(struct pcb_t * proc, uint32_t size, uint32_t reg_index) { + addr_t addr = alloc_mem(size, proc); + if (addr == 0) { + return 1; + }else{ + proc->regs[reg_index] = addr; + return 0; + } +} + +int free_data(struct pcb_t * proc, uint32_t reg_index) { + return free_mem(proc->regs[reg_index], proc); +} + +int read( + struct pcb_t * proc, // Process executing the instruction + uint32_t source, // Index of source register + uint32_t offset, // Source address = [source] + [offset] + uint32_t destination) { // Index of destination register + + BYTE data; + if (read_mem(proc->regs[source] + offset, proc, &data)) { + proc->regs[destination] = data; + return 0; + }else{ + return 1; + } +} + +int write( + struct pcb_t * proc, // Process executing the instruction + BYTE data, // Data to be wrttien into memory + uint32_t destination, // Index of destination register + uint32_t offset) { // Destination address = + // [destination] + [offset] + return write_mem(proc->regs[destination] + offset, proc, data); +} + +int run(struct pcb_t * proc) { + /* Check if Program Counter point to the proper instruction */ + if (proc->pc >= proc->code->size) { + return 1; + } + + struct inst_t ins = proc->code->text[proc->pc]; + proc->pc++; + int stat = 1; + switch (ins.opcode) { + case CALC: + stat = calc(proc); + break; + case ALLOC: +#ifdef CPU_TLB + stat = tlballoc(proc, ins.arg_0, ins.arg_1); +#elif defined(MM_PAGING) + stat = pgalloc(proc, ins.arg_0, ins.arg_1); +#else + stat = alloc(proc, ins.arg_0, ins.arg_1); +#endif + break; + case FREE: +#ifdef CPU_TLB + stat = tlbfree_data(proc, ins.arg_0); +#elif defined(MM_PAGING) + stat = pgfree_data(proc, ins.arg_0); +#else + stat = free_data(proc, ins.arg_0); +#endif + break; + case READ: +#ifdef CPU_TLB + stat = tlbread(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#elif defined(MM_PAGING) + stat = pgread(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#else + stat = read(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#endif + break; + case WRITE: +#ifdef CPU_TLB + stat = tlbwrite(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#elif defined(MM_PAGING) + stat = pgwrite(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#else + stat = write(proc, ins.arg_0, ins.arg_1, ins.arg_2); +#endif + break; + default: + stat = 1; + } + return stat; + +} + + diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 0000000..4b36301 --- /dev/null +++ b/src/loader.c @@ -0,0 +1,91 @@ + +#include "loader.h" +#include +#include +#include + +static uint32_t avail_pid = 1; + +#define OPT_CALC "calc" +#define OPT_ALLOC "alloc" +#define OPT_FREE "free" +#define OPT_READ "read" +#define OPT_WRITE "write" + +static enum ins_opcode_t get_opcode(char * opt) { + if (!strcmp(opt, OPT_CALC)) { + return CALC; + }else if (!strcmp(opt, OPT_ALLOC)) { + return ALLOC; + }else if (!strcmp(opt, OPT_FREE)) { + return FREE; + }else if (!strcmp(opt, OPT_READ)) { + return READ; + }else if (!strcmp(opt, OPT_WRITE)) { + return WRITE; + }else{ + printf("Opcode: %s\n", opt); + exit(1); + } +} + +struct pcb_t * load(const char * path) { + /* Create new PCB for the new process */ + struct pcb_t * proc = (struct pcb_t * )malloc(sizeof(struct pcb_t)); + proc->pid = avail_pid; + avail_pid++; + proc->page_table = + (struct page_table_t*)malloc(sizeof(struct page_table_t)); + proc->bp = PAGE_SIZE; + proc->pc = 0; + + /* Read process code from file */ + FILE * file; + if ((file = fopen(path, "r")) == NULL) { + printf("Cannot find process description at '%s'\n", path); + exit(1); + } + char opcode[10]; + proc->code = (struct code_seg_t*)malloc(sizeof(struct code_seg_t)); + fscanf(file, "%u %u", &proc->priority, &proc->code->size); + proc->code->text = (struct inst_t*)malloc( + sizeof(struct inst_t) * proc->code->size + ); + uint32_t i = 0; + for (i = 0; i < proc->code->size; i++) { + fscanf(file, "%s", opcode); + proc->code->text[i].opcode = get_opcode(opcode); + switch(proc->code->text[i].opcode) { + case CALC: + break; + case ALLOC: + fscanf( + file, + "%u %u\n", + &proc->code->text[i].arg_0, + &proc->code->text[i].arg_1 + ); + break; + case FREE: + fscanf(file, "%u\n", &proc->code->text[i].arg_0); + break; + case READ: + case WRITE: + fscanf( + file, + "%u %u %u\n", + &proc->code->text[i].arg_0, + &proc->code->text[i].arg_1, + &proc->code->text[i].arg_2 + ); + break; + default: + printf("Opcode: %s\n", opcode); + exit(1); + } + } + return proc; +} + + + diff --git a/src/mem.c b/src/mem.c new file mode 100644 index 0000000..187108f --- /dev/null +++ b/src/mem.c @@ -0,0 +1,173 @@ + +#include "mem.h" +#include "stdlib.h" +#include "string.h" +#include +#include + +static BYTE _ram[RAM_SIZE]; + +static struct { + uint32_t proc; // ID of process currently uses this page + int index; // Index of the page in the list of pages allocated + // to the process. + int next; // The next page in the list. -1 if it is the last + // page. +} _mem_stat [NUM_PAGES]; + +static pthread_mutex_t mem_lock; + +void init_mem(void) { + memset(_mem_stat, 0, sizeof(*_mem_stat) * NUM_PAGES); + memset(_ram, 0, sizeof(BYTE) * RAM_SIZE); + pthread_mutex_init(&mem_lock, NULL); +} + +/* get offset of the virtual address */ +static addr_t get_offset(addr_t addr) { + return addr & ~((~0U) << OFFSET_LEN); +} + +/* get the first layer index */ +static addr_t get_first_lv(addr_t addr) { + return addr >> (OFFSET_LEN + PAGE_LEN); +} + +/* get the second layer index */ +static addr_t get_second_lv(addr_t addr) { + return (addr >> OFFSET_LEN) - (get_first_lv(addr) << PAGE_LEN); +} + +/* Search for page table table from the a segment table */ +static struct trans_table_t * get_trans_table( + addr_t index, // Segment level index + struct page_table_t * page_table) { // first level table + + /* DO NOTHING HERE. This mem is obsoleted */ + + int i; + for (i = 0; i < page_table->size; i++) { + // Enter your code here + } + return NULL; + +} + +/* Translate virtual address to physical address. If [virtual_addr] is valid, + * return 1 and write its physical counterpart to [physical_addr]. + * Otherwise, return 0 */ +static int translate( + addr_t virtual_addr, // Given virtual address + addr_t * physical_addr, // Physical address to be returned + struct pcb_t * proc) { // Process uses given virtual address + + /* Offset of the virtual address */ + addr_t offset = get_offset(virtual_addr); + offset++; offset--; + /* The first layer index */ + addr_t first_lv = get_first_lv(virtual_addr); + /* The second layer index */ + addr_t second_lv = get_second_lv(virtual_addr); + + /* Search in the first level */ + struct trans_table_t * trans_table = NULL; + trans_table = get_trans_table(first_lv, proc->page_table); + if (trans_table == NULL) { + return 0; + } + + int i; + for (i = 0; i < trans_table->size; i++) { + if (trans_table->table[i].v_index == second_lv) { + /* DO NOTHING HERE. This mem is obsoleted */ + return 1; + } + } + return 0; +} + +addr_t alloc_mem(uint32_t size, struct pcb_t * proc) { + pthread_mutex_lock(&mem_lock); + addr_t ret_mem = 0; + /* DO NOTHING HERE. This mem is obsoleted */ + + uint32_t num_pages = (size % PAGE_SIZE) ? size / PAGE_SIZE : + size / PAGE_SIZE + 1; // Number of pages we will use + int mem_avail = 0; // We could allocate new memory region or not? + + /* First we must check if the amount of free memory in + * virtual address space and physical address space is + * large enough to represent the amount of required + * memory. If so, set 1 to [mem_avail]. + * Hint: check [proc] bit in each page of _mem_stat + * to know whether this page has been used by a process. + * For virtual memory space, check bp (break pointer). + * */ + + if (mem_avail) { + /* We could allocate new memory region to the process */ + ret_mem = proc->bp; + proc->bp += num_pages * PAGE_SIZE; + /* Update status of physical pages which will be allocated + * to [proc] in _mem_stat. Tasks to do: + * - Update [proc], [index], and [next] field + * - Add entries to segment table page tables of [proc] + * to ensure accesses to allocated memory slot is + * valid. */ + } + pthread_mutex_unlock(&mem_lock); + return ret_mem; +} + +int free_mem(addr_t address, struct pcb_t * proc) { + /* DO NOTHING HERE. This mem is obsoleted */ + return 0; +} + +int read_mem(addr_t address, struct pcb_t * proc, BYTE * data) { + addr_t physical_addr; + if (translate(address, &physical_addr, proc)) { + *data = _ram[physical_addr]; + return 0; + }else{ + return 1; + } +} + +int write_mem(addr_t address, struct pcb_t * proc, BYTE data) { + addr_t physical_addr; + if (translate(address, &physical_addr, proc)) { + _ram[physical_addr] = data; + return 0; + }else{ + return 1; + } +} + +void dump(void) { + int i; + for (i = 0; i < NUM_PAGES; i++) { + if (_mem_stat[i].proc != 0) { + printf("%03d: ", i); + printf("%05x-%05x - PID: %02d (idx %03d, nxt: %03d)\n", + i << OFFSET_LEN, + ((i + 1) << OFFSET_LEN) - 1, + _mem_stat[i].proc, + _mem_stat[i].index, + _mem_stat[i].next + ); + int j; + for ( j = i << OFFSET_LEN; + j < ((i+1) << OFFSET_LEN) - 1; + j++) { + + if (_ram[j] != 0) { + printf("\t%05x: %02x\n", j, _ram[j]); + } + + } + } + } +} + + diff --git a/src/mm-memphy.c b/src/mm-memphy.c new file mode 100644 index 0000000..e638ce3 --- /dev/null +++ b/src/mm-memphy.c @@ -0,0 +1,199 @@ +//#ifdef MM_PAGING +/* + * PAGING based Memory Management + * Memory physical module mm/mm-memphy.c + */ + +#include "mm.h" +#include + +/* + * MEMPHY_mv_csr - move MEMPHY cursor + * @mp: memphy struct + * @offset: offset + */ +int MEMPHY_mv_csr(struct memphy_struct *mp, int offset) +{ + int numstep = 0; + + mp->cursor = 0; + while(numstep < offset && numstep < mp->maxsz){ + /* Traverse sequentially */ + mp->cursor = (mp->cursor + 1) % mp->maxsz; + numstep++; + } + + return 0; +} + +/* + * MEMPHY_seq_read - read MEMPHY device + * @mp: memphy struct + * @addr: address + * @value: obtained value + */ +int MEMPHY_seq_read(struct memphy_struct *mp, int addr, BYTE *value) +{ + if (mp == NULL) + return -1; + + if (!mp->rdmflg) + return -1; /* Not compatible mode for sequential read */ + + MEMPHY_mv_csr(mp, addr); + *value = (BYTE) mp->storage[addr]; + + return 0; +} + +/* + * MEMPHY_read read MEMPHY device + * @mp: memphy struct + * @addr: address + * @value: obtained value + */ +int MEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value) +{ + if (mp == NULL) + return -1; + + if (mp->rdmflg) + *value = mp->storage[addr]; + else /* Sequential access device */ + return MEMPHY_seq_read(mp, addr, value); + + return 0; +} + +/* + * MEMPHY_seq_write - write MEMPHY device + * @mp: memphy struct + * @addr: address + * @data: written data + */ +int MEMPHY_seq_write(struct memphy_struct * mp, int addr, BYTE value) +{ + + if (mp == NULL) + return -1; + + if (!mp->rdmflg) + return -1; /* Not compatible mode for sequential read */ + + MEMPHY_mv_csr(mp, addr); + mp->storage[addr] = value; + + return 0; +} + +/* + * MEMPHY_write-write MEMPHY device + * @mp: memphy struct + * @addr: address + * @data: written data + */ +int MEMPHY_write(struct memphy_struct * mp, int addr, BYTE data) +{ + if (mp == NULL) + return -1; + + if (mp->rdmflg) + mp->storage[addr] = data; + else /* Sequential access device */ + return MEMPHY_seq_write(mp, addr, data); + + return 0; +} + +/* + * MEMPHY_format-format MEMPHY device + * @mp: memphy struct + */ +int MEMPHY_format(struct memphy_struct *mp, int pagesz) +{ + /* This setting come with fixed constant PAGESZ */ + int numfp = mp->maxsz / pagesz; + struct framephy_struct *newfst, *fst; + int iter = 0; + + if (numfp <= 0) + return -1; + + /* Init head of free framephy list */ + fst = malloc(sizeof(struct framephy_struct)); + fst->fpn = iter; + mp->free_fp_list = fst; + + /* We have list with first element, fill in the rest num-1 element member*/ + for (iter = 1; iter < numfp ; iter++) + { + newfst = malloc(sizeof(struct framephy_struct)); + newfst->fpn = iter; + newfst->fp_next = NULL; + fst->fp_next = newfst; + fst = newfst; + } + + return 0; +} + +int MEMPHY_get_freefp(struct memphy_struct *mp, int *retfpn) +{ + struct framephy_struct *fp = mp->free_fp_list; + + if (fp == NULL) + return -1; + + *retfpn = fp->fpn; + mp->free_fp_list = fp->fp_next; + + /* MEMPHY is iteratively used up until its exhausted + * No garbage collector acting then it not been released + */ + free(fp); + + return 0; +} + +int MEMPHY_dump(struct memphy_struct * mp) +{ + /*TODO dump memphy contnt mp->storage + * for tracing the memory content + */ + + return 0; +} + +int MEMPHY_put_freefp(struct memphy_struct *mp, int fpn) +{ + struct framephy_struct *fp = mp->free_fp_list; + struct framephy_struct *newnode = malloc(sizeof(struct framephy_struct)); + + /* Create new node with value fpn */ + newnode->fpn = fpn; + newnode->fp_next = fp; + mp->free_fp_list = newnode; + + return 0; +} + + +/* + * Init MEMPHY struct + */ +int init_memphy(struct memphy_struct *mp, int max_size, int randomflg) +{ + mp->storage = (BYTE *)malloc(max_size*sizeof(BYTE)); + mp->maxsz = max_size; + + MEMPHY_format(mp,PAGING_PAGESZ); + + mp->rdmflg = (randomflg != 0)?1:0; + + if (!mp->rdmflg ) /* Not Ramdom acess device, then it serial device*/ + mp->cursor = 0; + + return 0; +} + +//#endif diff --git a/src/mm-vm.c b/src/mm-vm.c new file mode 100644 index 0000000..c2375d2 --- /dev/null +++ b/src/mm-vm.c @@ -0,0 +1,526 @@ +//#ifdef MM_PAGING +/* + * PAGING based Memory Management + * Virtual memory module mm/mm-vm.c + */ + +#include "string.h" +#include "mm.h" +#include +#include + +/*enlist_vm_freerg_list - add new rg to freerg_list + *@mm: memory region + *@rg_elmt: new region + * + */ +int enlist_vm_freerg_list(struct mm_struct *mm, struct vm_rg_struct rg_elmt) +{ + struct vm_rg_struct *rg_node = mm->mmap->vm_freerg_list; + + if (rg_elmt.rg_start >= rg_elmt.rg_end) + return -1; + + if (rg_node != NULL) + rg_elmt.rg_next = rg_node; + + /* Enlist the new region */ + mm->mmap->vm_freerg_list = &rg_elmt; + + return 0; +} + +/*get_vma_by_num - get vm area by numID + *@mm: memory region + *@vmaid: ID vm area to alloc memory region + * + */ +struct vm_area_struct *get_vma_by_num(struct mm_struct *mm, int vmaid) +{ + struct vm_area_struct *pvma= mm->mmap; + + if(mm->mmap == NULL) + return NULL; + + int vmait = 0; + + while (vmait < vmaid) + { + if(pvma == NULL) + return NULL; + + vmait++; + pvma = pvma->vm_next; + } + + return pvma; +} + +/*get_symrg_byid - get mem region by region ID + *@mm: memory region + *@rgid: region ID act as symbol index of variable + * + */ +struct vm_rg_struct *get_symrg_byid(struct mm_struct *mm, int rgid) +{ + if(rgid < 0 || rgid > PAGING_MAX_SYMTBL_SZ) + return NULL; + + return &mm->symrgtbl[rgid]; +} + +/*__alloc - allocate a region memory + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@rgid: memory region ID (used to identify variable in symbole table) + *@size: allocated size + *@alloc_addr: address of allocated memory region + * + */ +int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr) +{ + /*Allocate at the toproof */ + struct vm_rg_struct rgnode; + + if (get_free_vmrg_area(caller, vmaid, size, &rgnode) == 0) + { + caller->mm->symrgtbl[rgid].rg_start = rgnode.rg_start; + caller->mm->symrgtbl[rgid].rg_end = rgnode.rg_end; + + *alloc_addr = rgnode.rg_start; + + return 0; + } + + /* TODO get_free_vmrg_area FAILED handle the region management (Fig.6)*/ + + /*Attempt to increate limit to get space */ + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + int inc_sz = PAGING_PAGE_ALIGNSZ(size); + //int inc_limit_ret + int old_sbrk ; + + old_sbrk = cur_vma->sbrk; + + /* TODO INCREASE THE LIMIT + * inc_vma_limit(caller, vmaid, inc_sz) + */ + inc_vma_limit(caller, vmaid, inc_sz); + + /*Successful increase limit */ + caller->mm->symrgtbl[rgid].rg_start = old_sbrk; + caller->mm->symrgtbl[rgid].rg_end = old_sbrk + size; + + *alloc_addr = old_sbrk; + + return 0; +} + +/*__free - remove a region memory + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@rgid: memory region ID (used to identify variable in symbole table) + *@size: allocated size + * + */ +int __free(struct pcb_t *caller, int vmaid, int rgid) +{ + struct vm_rg_struct rgnode; + + if(rgid < 0 || rgid > PAGING_MAX_SYMTBL_SZ) + return -1; + + /* TODO: Manage the collect freed region to freerg_list */ + + /*enlist the obsoleted memory region */ + enlist_vm_freerg_list(caller->mm, rgnode); + + return 0; +} + +/*pgalloc - PAGING-based allocate a region memory + *@proc: Process executing the instruction + *@size: allocated size + *@reg_index: memory region ID (used to identify variable in symbole table) + */ +int pgalloc(struct pcb_t *proc, uint32_t size, uint32_t reg_index) +{ + int addr; + + /* By default using vmaid = 0 */ + return __alloc(proc, 0, reg_index, size, &addr); +} + +/*pgfree - PAGING-based free a region memory + *@proc: Process executing the instruction + *@size: allocated size + *@reg_index: memory region ID (used to identify variable in symbole table) + */ + +int pgfree_data(struct pcb_t *proc, uint32_t reg_index) +{ + return __free(proc, 0, reg_index); +} + +/*pg_getpage - get the page in ram + *@mm: memory region + *@pagenum: PGN + *@framenum: return FPN + *@caller: caller + * + */ +int pg_getpage(struct mm_struct *mm, int pgn, int *fpn, struct pcb_t *caller) +{ + uint32_t pte = mm->pgd[pgn]; + + if (!PAGING_PAGE_PRESENT(pte)) + { /* Page is not online, make it actively living */ + int vicpgn, swpfpn; + //int vicfpn; + //uint32_t vicpte; + + int tgtfpn = PAGING_SWP(pte);//the target frame storing our variable + + /* TODO: Play with your paging theory here */ + /* Find victim page */ + find_victim_page(caller->mm, &vicpgn); + + /* Get free frame in MEMSWP */ + MEMPHY_get_freefp(caller->active_mswp, &swpfpn); + + + /* Do swap frame from MEMRAM to MEMSWP and vice versa*/ + /* Copy victim frame to swap */ + //__swap_cp_page(); + /* Copy target frame from swap to mem */ + //__swap_cp_page(); + + /* Update page table */ + //pte_set_swap() &mm->pgd; + + /* Update its online status of the target page */ + //pte_set_fpn() & mm->pgd[pgn]; + pte_set_fpn(&pte, tgtfpn); + +#ifdef CPU_TLB + /* Update its online status of TLB (if needed) */ +#endif + + enlist_pgn_node(&caller->mm->fifo_pgn,pgn); + } + + *fpn = PAGING_FPN(pte); + + return 0; +} + +/*pg_getval - read value at given offset + *@mm: memory region + *@addr: virtual address to acess + *@value: value + * + */ +int pg_getval(struct mm_struct *mm, int addr, BYTE *data, struct pcb_t *caller) +{ + int pgn = PAGING_PGN(addr); + int off = PAGING_OFFST(addr); + int fpn; + + /* Get the page to MEMRAM, swap from MEMSWAP if needed */ + if(pg_getpage(mm, pgn, &fpn, caller) != 0) + return -1; /* invalid page access */ + + int phyaddr = (fpn << PAGING_ADDR_FPN_LOBIT) + off; + + MEMPHY_read(caller->mram,phyaddr, data); + + return 0; +} + +/*pg_setval - write value to given offset + *@mm: memory region + *@addr: virtual address to acess + *@value: value + * + */ +int pg_setval(struct mm_struct *mm, int addr, BYTE value, struct pcb_t *caller) +{ + int pgn = PAGING_PGN(addr); + int off = PAGING_OFFST(addr); + int fpn; + + /* Get the page to MEMRAM, swap from MEMSWAP if needed */ + if(pg_getpage(mm, pgn, &fpn, caller) != 0) + return -1; /* invalid page access */ + + int phyaddr = (fpn << PAGING_ADDR_FPN_LOBIT) + off; + + MEMPHY_write(caller->mram,phyaddr, value); + + return 0; +} + +/*__read - read value in region memory + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@offset: offset to acess in memory region + *@rgid: memory region ID (used to identify variable in symbole table) + *@size: allocated size + * + */ +int __read(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE *data) +{ + struct vm_rg_struct *currg = get_symrg_byid(caller->mm, rgid); + + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + + if(currg == NULL || cur_vma == NULL) /* Invalid memory identify */ + return -1; + + pg_getval(caller->mm, currg->rg_start + offset, data, caller); + + return 0; +} + + +/*pgwrite - PAGING-based read a region memory */ +int pgread( + struct pcb_t * proc, // Process executing the instruction + uint32_t source, // Index of source register + uint32_t offset, // Source address = [source] + [offset] + uint32_t destination) +{ + BYTE data; + int val = __read(proc, 0, source, offset, &data); + + destination = (uint32_t) data; +#ifdef IODUMP + printf("read region=%d offset=%d value=%d\n", source, offset, data); +#ifdef PAGETBL_DUMP + print_pgtbl(proc, 0, -1); //print max TBL +#endif + MEMPHY_dump(proc->mram); +#endif + + return val; +} + +/*__write - write a region memory + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@offset: offset to acess in memory region + *@rgid: memory region ID (used to identify variable in symbole table) + *@size: allocated size + * + */ +int __write(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE value) +{ + struct vm_rg_struct *currg = get_symrg_byid(caller->mm, rgid); + + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + + if(currg == NULL || cur_vma == NULL) /* Invalid memory identify */ + return -1; + + pg_setval(caller->mm, currg->rg_start + offset, value, caller); + + return 0; +} + +/*pgwrite - PAGING-based write a region memory */ +int pgwrite( + struct pcb_t * proc, // Process executing the instruction + BYTE data, // Data to be wrttien into memory + uint32_t destination, // Index of destination register + uint32_t offset) +{ +#ifdef IODUMP + printf("write region=%d offset=%d value=%d\n", destination, offset, data); +#ifdef PAGETBL_DUMP + print_pgtbl(proc, 0, -1); //print max TBL +#endif + MEMPHY_dump(proc->mram); +#endif + + return __write(proc, 0, destination, offset, data); +} + + +/*free_pcb_memphy - collect all memphy of pcb + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@incpgnum: number of page + */ +int free_pcb_memph(struct pcb_t *caller) +{ + int pagenum, fpn; + uint32_t pte; + + + for(pagenum = 0; pagenum < PAGING_MAX_PGN; pagenum++) + { + pte= caller->mm->pgd[pagenum]; + + if (!PAGING_PAGE_PRESENT(pte)) + { + fpn = PAGING_FPN(pte); + MEMPHY_put_freefp(caller->mram, fpn); + } else { + fpn = PAGING_SWP(pte); + MEMPHY_put_freefp(caller->active_mswp, fpn); + } + } + + return 0; +} + +/*get_vm_area_node - get vm area for a number of pages + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@incpgnum: number of page + *@vmastart: vma end + *@vmaend: vma end + * + */ +struct vm_rg_struct* get_vm_area_node_at_brk(struct pcb_t *caller, int vmaid, int size, int alignedsz) +{ + struct vm_rg_struct * newrg; + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + + newrg = malloc(sizeof(struct vm_rg_struct)); + + newrg->rg_start = cur_vma->sbrk; + newrg->rg_end = newrg->rg_start + size; + + return newrg; +} + +/*validate_overlap_vm_area + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@vmastart: vma end + *@vmaend: vma end + * + */ +int validate_overlap_vm_area(struct pcb_t *caller, int vmaid, int vmastart, int vmaend) +{ + //struct vm_area_struct *vma = caller->mm->mmap; + + /* TODO validate the planned memory area is not overlapped */ + + return 0; +} + +/*inc_vma_limit - increase vm area limits to reserve space for new variable + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@inc_sz: increment size + * + */ +int inc_vma_limit(struct pcb_t *caller, int vmaid, int inc_sz) +{ + struct vm_rg_struct * newrg = malloc(sizeof(struct vm_rg_struct)); + int inc_amt = PAGING_PAGE_ALIGNSZ(inc_sz); + int incnumpage = inc_amt / PAGING_PAGESZ; + struct vm_rg_struct *area = get_vm_area_node_at_brk(caller, vmaid, inc_sz, inc_amt); + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + + int old_end = cur_vma->vm_end; + + /*Validate overlap of obtained region */ + if (validate_overlap_vm_area(caller, vmaid, area->rg_start, area->rg_end) < 0) + return -1; /*Overlap and failed allocation */ + + /* The obtained vm area (only) + * now will be alloc real ram region */ + cur_vma->vm_end += inc_sz; + if (vm_map_ram(caller, area->rg_start, area->rg_end, + old_end, incnumpage , newrg) < 0) + return -1; /* Map the memory to MEMRAM */ + + return 0; + +} + +/*find_victim_page - find victim page + *@caller: caller + *@pgn: return page number + * + */ +int find_victim_page(struct mm_struct *mm, int *retpgn) +{ + struct pgn_t *pg = mm->fifo_pgn; + + /* TODO: Implement the theorical mechanism to find the victim page */ + + free(pg); + + return 0; +} + +/*get_free_vmrg_area - get a free vm region + *@caller: caller + *@vmaid: ID vm area to alloc memory region + *@size: allocated size + * + */ +int get_free_vmrg_area(struct pcb_t *caller, int vmaid, int size, struct vm_rg_struct *newrg) +{ + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + + struct vm_rg_struct *rgit = cur_vma->vm_freerg_list; + + if (rgit == NULL) + return -1; + + /* Probe unintialized newrg */ + newrg->rg_start = newrg->rg_end = -1; + + /* Traverse on list of free vm region to find a fit space */ + while (rgit != NULL) + { + if (rgit->rg_start + size <= rgit->rg_end) + { /* Current region has enough space */ + newrg->rg_start = rgit->rg_start; + newrg->rg_end = rgit->rg_start + size; + + /* Update left space in chosen region */ + if (rgit->rg_start + size < rgit->rg_end) + { + rgit->rg_start = rgit->rg_start + size; + } + else + { /*Use up all space, remove current node */ + /*Clone next rg node */ + struct vm_rg_struct *nextrg = rgit->rg_next; + + /*Cloning */ + if (nextrg != NULL) + { + rgit->rg_start = nextrg->rg_start; + rgit->rg_end = nextrg->rg_end; + + rgit->rg_next = nextrg->rg_next; + + free(nextrg); + } + else + { /*End of free list */ + rgit->rg_start = rgit->rg_end; //dummy, size 0 region + rgit->rg_next = NULL; + } + } + } + else + { + rgit = rgit->rg_next; // Traverse next rg + } + } + + if(newrg->rg_start == -1) // new region not found + return -1; + + return 0; +} + +//#endif diff --git a/src/mm.c b/src/mm.c new file mode 100644 index 0000000..e590e70 --- /dev/null +++ b/src/mm.c @@ -0,0 +1,347 @@ +//#ifdef MM_PAGING +/* + * PAGING based Memory Management + * Memory management unit mm/mm.c + */ + +#include "mm.h" +#include +#include + +/* + * init_pte - Initialize PTE entry + */ +int init_pte(uint32_t *pte, + int pre, // present + int fpn, // FPN + int drt, // dirty + int swp, // swap + int swptyp, // swap type + int swpoff) //swap offset +{ + if (pre != 0) { + if (swp == 0) { // Non swap ~ page online + if (fpn == 0) + return -1; // Invalid setting + + /* Valid setting with FPN */ + SETBIT(*pte, PAGING_PTE_PRESENT_MASK); + CLRBIT(*pte, PAGING_PTE_SWAPPED_MASK); + CLRBIT(*pte, PAGING_PTE_DIRTY_MASK); + + SETVAL(*pte, fpn, PAGING_PTE_FPN_MASK, PAGING_PTE_FPN_LOBIT); + } else { // page swapped + SETBIT(*pte, PAGING_PTE_PRESENT_MASK); + SETBIT(*pte, PAGING_PTE_SWAPPED_MASK); + CLRBIT(*pte, PAGING_PTE_DIRTY_MASK); + + SETVAL(*pte, swptyp, PAGING_PTE_SWPTYP_MASK, PAGING_PTE_SWPTYP_LOBIT); + SETVAL(*pte, swpoff, PAGING_PTE_SWPOFF_MASK, PAGING_PTE_SWPOFF_LOBIT); + } + } + + return 0; +} + +/* + * pte_set_swap - Set PTE entry for swapped page + * @pte : target page table entry (PTE) + * @swptyp : swap type + * @swpoff : swap offset + */ +int pte_set_swap(uint32_t *pte, int swptyp, int swpoff) +{ + SETBIT(*pte, PAGING_PTE_PRESENT_MASK); + SETBIT(*pte, PAGING_PTE_SWAPPED_MASK); + + SETVAL(*pte, swptyp, PAGING_PTE_SWPTYP_MASK, PAGING_PTE_SWPTYP_LOBIT); + SETVAL(*pte, swpoff, PAGING_PTE_SWPOFF_MASK, PAGING_PTE_SWPOFF_LOBIT); + + return 0; +} + +/* + * pte_set_swap - Set PTE entry for on-line page + * @pte : target page table entry (PTE) + * @fpn : frame page number (FPN) + */ +int pte_set_fpn(uint32_t *pte, int fpn) +{ + SETBIT(*pte, PAGING_PTE_PRESENT_MASK); + CLRBIT(*pte, PAGING_PTE_SWAPPED_MASK); + + SETVAL(*pte, fpn, PAGING_PTE_FPN_MASK, PAGING_PTE_FPN_LOBIT); + + return 0; +} + + +/* + * vmap_page_range - map a range of page at aligned address + */ +int vmap_page_range(struct pcb_t *caller, // process call + int addr, // start address which is aligned to pagesz + int pgnum, // num of mapping page + struct framephy_struct *frames,// list of the mapped frames + struct vm_rg_struct *ret_rg)// return mapped region, the real mapped fp +{ // no guarantee all given pages are mapped + //uint32_t * pte = malloc(sizeof(uint32_t)); + struct framephy_struct *fpit = malloc(sizeof(struct framephy_struct)); + //int fpn; + int pgit = 0; + int pgn = PAGING_PGN(addr); + + ret_rg->rg_end = ret_rg->rg_start = addr; // at least the very first space is usable + + fpit->fp_next = frames; + + /* TODO map range of frame to address space + * [addr to addr + pgnum*PAGING_PAGESZ + * in page table caller->mm->pgd[] + */ + + /* Tracking for later page replacement activities (if needed) + * Enqueue new usage page */ + enlist_pgn_node(&caller->mm->fifo_pgn, pgn+pgit); + + + return 0; +} + +/* + * alloc_pages_range - allocate req_pgnum of frame in ram + * @caller : caller + * @req_pgnum : request page num + * @frm_lst : frame list + */ + +int alloc_pages_range(struct pcb_t *caller, int req_pgnum, struct framephy_struct** frm_lst) +{ + int pgit, fpn; + //struct framephy_struct *newfp_str; + + for(pgit = 0; pgit < req_pgnum; pgit++) + { + if(MEMPHY_get_freefp(caller->mram, &fpn) == 0) + { + + } else { // ERROR CODE of obtaining somes but not enough frames + } + } + + return 0; +} + + +/* + * vm_map_ram - do the mapping all vm are to ram storage device + * @caller : caller + * @astart : vm area start + * @aend : vm area end + * @mapstart : start mapping point + * @incpgnum : number of mapped page + * @ret_rg : returned region + */ +int vm_map_ram(struct pcb_t *caller, int astart, int aend, int mapstart, int incpgnum, struct vm_rg_struct *ret_rg) +{ + struct framephy_struct *frm_lst = NULL; + int ret_alloc; + + /*@bksysnet: author provides a feasible solution of getting frames + *FATAL logic in here, wrong behaviour if we have not enough page + *i.e. we request 1000 frames meanwhile our RAM has size of 3 frames + *Don't try to perform that case in this simple work, it will result + *in endless procedure of swap-off to get frame and we have not provide + *duplicate control mechanism, keep it simple + */ + ret_alloc = alloc_pages_range(caller, incpgnum, &frm_lst); + + if (ret_alloc < 0 && ret_alloc != -3000) + return -1; + + /* Out of memory */ + if (ret_alloc == -3000) + { +#ifdef MMDBG + printf("OOM: vm_map_ram out of memory \n"); +#endif + return -1; + } + + /* it leaves the case of memory is enough but half in ram, half in swap + * do the swaping all to swapper to get the all in ram */ + vmap_page_range(caller, mapstart, incpgnum, frm_lst, ret_rg); + + return 0; +} + +/* Swap copy content page from source frame to destination frame + * @mpsrc : source memphy + * @srcfpn : source physical page number (FPN) + * @mpdst : destination memphy + * @dstfpn : destination physical page number (FPN) + **/ +int __swap_cp_page(struct memphy_struct *mpsrc, int srcfpn, + struct memphy_struct *mpdst, int dstfpn) +{ + int cellidx; + int addrsrc,addrdst; + for(cellidx = 0; cellidx < PAGING_PAGESZ; cellidx++) + { + addrsrc = srcfpn * PAGING_PAGESZ + cellidx; + addrdst = dstfpn * PAGING_PAGESZ + cellidx; + + BYTE data; + MEMPHY_read(mpsrc, addrsrc, &data); + MEMPHY_write(mpdst, addrdst, data); + } + + return 0; +} + +/* + *Initialize a empty Memory Management instance + * @mm: self mm + * @caller: mm owner + */ +int init_mm(struct mm_struct *mm, struct pcb_t *caller) +{ + struct vm_area_struct * vma = malloc(sizeof(struct vm_area_struct)); + + mm->pgd = malloc(PAGING_MAX_PGN*sizeof(uint32_t)); + + /* By default the owner comes with at least one vma */ + vma->vm_id = 1; + vma->vm_start = 0; + vma->vm_end = vma->vm_start; + vma->sbrk = vma->vm_start; + struct vm_rg_struct *first_rg = init_vm_rg(vma->vm_start, vma->vm_end); + enlist_vm_rg_node(&vma->vm_freerg_list, first_rg); + + vma->vm_next = NULL; + vma->vm_mm = mm; /*point back to vma owner */ + + mm->mmap = vma; + + return 0; +} + +struct vm_rg_struct* init_vm_rg(int rg_start, int rg_end) +{ + struct vm_rg_struct *rgnode = malloc(sizeof(struct vm_rg_struct)); + + rgnode->rg_start = rg_start; + rgnode->rg_end = rg_end; + rgnode->rg_next = NULL; + + return rgnode; +} + +int enlist_vm_rg_node(struct vm_rg_struct **rglist, struct vm_rg_struct* rgnode) +{ + rgnode->rg_next = *rglist; + *rglist = rgnode; + + return 0; +} + +int enlist_pgn_node(struct pgn_t **plist, int pgn) +{ + struct pgn_t* pnode = malloc(sizeof(struct pgn_t)); + + pnode->pgn = pgn; + pnode->pg_next = *plist; + *plist = pnode; + + return 0; +} + +int print_list_fp(struct framephy_struct *ifp) +{ + struct framephy_struct *fp = ifp; + + printf("print_list_fp: "); + if (fp == NULL) {printf("NULL list\n"); return -1;} + printf("\n"); + while (fp != NULL ) + { + printf("fp[%d]\n",fp->fpn); + fp = fp->fp_next; + } + printf("\n"); + return 0; +} + +int print_list_rg(struct vm_rg_struct *irg) +{ + struct vm_rg_struct *rg = irg; + + printf("print_list_rg: "); + if (rg == NULL) {printf("NULL list\n"); return -1;} + printf("\n"); + while (rg != NULL) + { + printf("rg[%ld->%ld]\n",rg->rg_start, rg->rg_end); + rg = rg->rg_next; + } + printf("\n"); + return 0; +} + +int print_list_vma(struct vm_area_struct *ivma) +{ + struct vm_area_struct *vma = ivma; + + printf("print_list_vma: "); + if (vma == NULL) {printf("NULL list\n"); return -1;} + printf("\n"); + while (vma != NULL ) + { + printf("va[%ld->%ld]\n",vma->vm_start, vma->vm_end); + vma = vma->vm_next; + } + printf("\n"); + return 0; +} + +int print_list_pgn(struct pgn_t *ip) +{ + printf("print_list_pgn: "); + if (ip == NULL) {printf("NULL list\n"); return -1;} + printf("\n"); + while (ip != NULL ) + { + printf("va[%d]-\n",ip->pgn); + ip = ip->pg_next; + } + printf("n"); + return 0; +} + +int print_pgtbl(struct pcb_t *caller, uint32_t start, uint32_t end) +{ + int pgn_start,pgn_end; + int pgit; + + if(end == -1){ + pgn_start = 0; + struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, 0); + end = cur_vma->vm_end; + } + pgn_start = PAGING_PGN(start); + pgn_end = PAGING_PGN(end); + + printf("print_pgtbl: %d - %d", start, end); + if (caller == NULL) {printf("NULL caller\n"); return -1;} + printf("\n"); + + + for(pgit = pgn_start; pgit < pgn_end; pgit++) + { + printf("%08ld: %08x\n", pgit * sizeof(uint32_t), caller->mm->pgd[pgit]); + } + + return 0; +} + +//#endif diff --git a/src/os.c b/src/os.c new file mode 100644 index 0000000..aa845e6 --- /dev/null +++ b/src/os.c @@ -0,0 +1,309 @@ + +#include "cpu.h" +#include "timer.h" +#include "sched.h" +#include "loader.h" +#include "mm.h" + +#include +#include +#include +#include + +static int time_slot; +static int num_cpus; +static int done = 0; + +#ifdef CPU_TLB +static int tlbsz; +#endif + +#ifdef MM_PAGING +static int memramsz; +static int memswpsz[PAGING_MAX_MMSWP]; + +struct mmpaging_ld_args { + /* A dispatched argument struct to compact many-fields passing to loader */ + struct memphy_struct *tlb; + struct memphy_struct *mram; + struct memphy_struct **mswp; + struct memphy_struct *active_mswp; + struct timer_id_t *timer_id; +}; +#endif + +static struct ld_args{ + char ** path; + unsigned long * start_time; +#ifdef MLQ_SCHED + unsigned long * prio; +#endif +} ld_processes; +int num_processes; + +struct cpu_args { + struct timer_id_t * timer_id; + int id; +}; + + +static void * cpu_routine(void * args) { + struct timer_id_t * timer_id = ((struct cpu_args*)args)->timer_id; + int id = ((struct cpu_args*)args)->id; + /* Check for new process in ready queue */ + int time_left = 0; + struct pcb_t * proc = NULL; + while (1) { + /* Check the status of current process */ + if (proc == NULL) { + /* No process is running, the we load new process from + * ready queue */ + proc = get_proc(); + if (proc == NULL) { + next_slot(timer_id); + continue; /* First load failed. skip dummy load */ + } + }else if (proc->pc == proc->code->size) { + /* The porcess has finish it job */ + printf("\tCPU %d: Processed %2d has finished\n", + id ,proc->pid); + free(proc); + proc = get_proc(); + time_left = 0; + }else if (time_left == 0) { + /* The process has done its job in current time slot */ + printf("\tCPU %d: Put process %2d to run queue\n", + id, proc->pid); + put_proc(proc); + proc = get_proc(); + } + + /* Recheck process status after loading new process */ + if (proc == NULL && done) { + /* No process to run, exit */ + printf("\tCPU %d stopped\n", id); + break; + }else if (proc == NULL) { + /* There may be new processes to run in + * next time slots, just skip current slot */ + next_slot(timer_id); + continue; + }else if (time_left == 0) { + printf("\tCPU %d: Dispatched process %2d\n", + id, proc->pid); + time_left = time_slot; + } + + /* Run current process */ + run(proc); + time_left--; + next_slot(timer_id); + } + detach_event(timer_id); + pthread_exit(NULL); +} + +static void * ld_routine(void * args) { +#ifdef MM_PAGING + struct memphy_struct* mram = ((struct mmpaging_ld_args *)args)->mram; + struct memphy_struct** mswp = ((struct mmpaging_ld_args *)args)->mswp; + struct memphy_struct* active_mswp = ((struct mmpaging_ld_args *)args)->active_mswp; + struct timer_id_t * timer_id = ((struct mmpaging_ld_args *)args)->timer_id; +#else + struct timer_id_t * timer_id = (struct timer_id_t*)args; +#endif + int i = 0; + printf("ld_routine\n"); + while (i < num_processes) { + struct pcb_t * proc = load(ld_processes.path[i]); +#ifdef MLQ_SCHED + proc->prio = ld_processes.prio[i]; +#endif + while (current_time() < ld_processes.start_time[i]) { + next_slot(timer_id); + } +#ifdef MM_PAGING + proc->mm = malloc(sizeof(struct mm_struct)); + init_mm(proc->mm, proc); + proc->mram = mram; + proc->mswp = mswp; + proc->active_mswp = active_mswp; +#endif + printf("\tLoaded a process at %s, PID: %d PRIO: %ld\n", + ld_processes.path[i], proc->pid, ld_processes.prio[i]); + add_proc(proc); + free(ld_processes.path[i]); + i++; + next_slot(timer_id); + } + free(ld_processes.path); + free(ld_processes.start_time); + done = 1; + detach_event(timer_id); + pthread_exit(NULL); +} + +static void read_config(const char * path) { + FILE * file; + if ((file = fopen(path, "r")) == NULL) { + printf("Cannot find configure file at %s\n", path); + exit(1); + } + fscanf(file, "%d %d %d\n", &time_slot, &num_cpus, &num_processes); + ld_processes.path = (char**)malloc(sizeof(char*) * num_processes); + ld_processes.start_time = (unsigned long*) + malloc(sizeof(unsigned long) * num_processes); + +#ifdef CPU_TLB +#ifdef CPUTLB_FIXED_TLBSZ + /* We provide here a back compatible with legacy OS simulatiom config file + * In which, it have no addition config line for CPU_TLB + */ + tlbsz = 0x10000; +#else + /* Read input config of TLB size: + * Format: + * CPU_TLBSZ + */ + fscanf(file, "%d\n", &tlbsz); +#endif +#endif + +#ifdef MM_PAGING + int sit; +#ifdef MM_FIXED_MEMSZ + /* We provide here a back compatible with legacy OS simulatiom config file + * In which, it have no addition config line for Mema, keep only one line + * for legacy info + * [time slice] [N = Number of CPU] [M = Number of Processes to be run] + */ + memramsz = 0x100000; + memswpsz[0] = 0x1000000; + for(sit = 1; sit < PAGING_MAX_MMSWP; sit++) + memswpsz[sit] = 0; +#else + /* Read input config of memory size: MEMRAM and upto 4 MEMSWP (mem swap) + * Format: (size=0 result non-used memswap, must have RAM and at least 1 SWAP) + * MEM_RAM_SZ MEM_SWP0_SZ MEM_SWP1_SZ MEM_SWP2_SZ MEM_SWP3_SZ + */ + fscanf(file, "%d\n", &memramsz); + for(sit = 0; sit < PAGING_MAX_MMSWP; sit++) + fscanf(file, "%d", &(memswpsz[sit])); + + fscanf(file, "\n"); /* Final character */ +#endif +#endif + +#ifdef MLQ_SCHED + ld_processes.prio = (unsigned long*) + malloc(sizeof(unsigned long) * num_processes); +#endif + int i; + for (i = 0; i < num_processes; i++) { + ld_processes.path[i] = (char*)malloc(sizeof(char) * 100); + ld_processes.path[i][0] = '\0'; + strcat(ld_processes.path[i], "input/proc/"); + char proc[100]; +#ifdef MLQ_SCHED + fscanf(file, "%lu %s %lu\n", &ld_processes.start_time[i], proc, &ld_processes.prio[i]); +#else + fscanf(file, "%lu %s\n", &ld_processes.start_time[i], proc); +#endif + strcat(ld_processes.path[i], proc); + } +} + +int main(int argc, char * argv[]) { + /* Read config */ + if (argc != 2) { + printf("Usage: os [path to configure file]\n"); + return 1; + } + char path[100]; + path[0] = '\0'; + strcat(path, "input/"); + strcat(path, argv[1]); + read_config(path); + + pthread_t * cpu = (pthread_t*)malloc(num_cpus * sizeof(pthread_t)); + struct cpu_args * args = + (struct cpu_args*)malloc(sizeof(struct cpu_args) * num_cpus); + pthread_t ld; + + /* Init timer */ + int i; + for (i = 0; i < num_cpus; i++) { + args[i].timer_id = attach_event(); + args[i].id = i; + } + struct timer_id_t * ld_event = attach_event(); + start_timer(); +#ifdef CPU_TLB + struct memphy_struct tlb; + + init_tlbmemphy(&tlb, tlbsz); +#endif + +#ifdef MM_PAGING + /* Init all MEMPHY include 1 MEMRAM and n of MEMSWP */ + int rdmflag = 1; /* By default memphy is RANDOM ACCESS MEMORY */ + + struct memphy_struct mram; + struct memphy_struct mswp[PAGING_MAX_MMSWP]; + + + /* Create MEM RAM */ + init_memphy(&mram, memramsz, rdmflag); + + /* Create all MEM SWAP */ + int sit; + for(sit = 0; sit < PAGING_MAX_MMSWP; sit++) + init_memphy(&mswp[sit], memswpsz[sit], rdmflag); + + /* In Paging mode, it needs passing the system mem to each PCB through loader*/ + struct mmpaging_ld_args *mm_ld_args = malloc(sizeof(struct mmpaging_ld_args)); + + mm_ld_args->timer_id = ld_event; + mm_ld_args->mram = (struct memphy_struct *) &mram; + mm_ld_args->mswp = (struct memphy_struct**) &mswp; + mm_ld_args->active_mswp = (struct memphy_struct *) &mswp[0]; +#endif + +#ifdef CPU_TLB +#ifdef MM_PAGING + /* In MM_PAGING employ CPU_TLB mode, it needs passing + * the system tlb to each PCB through loader + */ + mm_ld_args->tlb = (struct memphy_struct *) &tlb; +#endif +#endif + + /* Init scheduler */ + init_scheduler(); + + /* Run CPU and loader */ +#ifdef MM_PAGING + pthread_create(&ld, NULL, ld_routine, (void*)mm_ld_args); +#else + pthread_create(&ld, NULL, ld_routine, (void*)ld_event); +#endif + for (i = 0; i < num_cpus; i++) { + pthread_create(&cpu[i], NULL, + cpu_routine, (void*)&args[i]); + } + + /* Wait for CPU and loader finishing */ + for (i = 0; i < num_cpus; i++) { + pthread_join(cpu[i], NULL); + } + pthread_join(ld, NULL); + + /* Stop timer */ + stop_timer(); + + return 0; + +} + + + diff --git a/src/paging.c b/src/paging.c new file mode 100644 index 0000000..b061019 --- /dev/null +++ b/src/paging.c @@ -0,0 +1,18 @@ + +#include "mem.h" +#include "cpu.h" +#include "loader.h" +#include + +int main() { + struct pcb_t * ld = load("input/p0"); + struct pcb_t * proc = load("input/p0"); + unsigned int i; + for (i = 0; i < proc->code->size; i++) { + run(proc); + run(ld); + } + dump(); + return 0; +} + diff --git a/src/queue.c b/src/queue.c new file mode 100644 index 0000000..5799c2a --- /dev/null +++ b/src/queue.c @@ -0,0 +1,20 @@ +#include +#include +#include "queue.h" + +int empty(struct queue_t * q) { + if (q == NULL) return 1; + return (q->size == 0); +} + +void enqueue(struct queue_t * q, struct pcb_t * proc) { + /* TODO: put a new process to queue [q] */ +} + +struct pcb_t * dequeue(struct queue_t * q) { + /* TODO: return a pcb whose prioprity is the highest + * in the queue [q] and remember to remove it from q + * */ + return NULL; +} + diff --git a/src/sched.c b/src/sched.c new file mode 100644 index 0000000..b4f3348 --- /dev/null +++ b/src/sched.c @@ -0,0 +1,99 @@ + +#include "queue.h" +#include "sched.h" +#include + +#include +#include +static struct queue_t ready_queue; +static struct queue_t run_queue; +static pthread_mutex_t queue_lock; + +#ifdef MLQ_SCHED +static struct queue_t mlq_ready_queue[MAX_PRIO]; +#endif + +int queue_empty(void) { +#ifdef MLQ_SCHED + unsigned long prio; + for (prio = 0; prio < MAX_PRIO; prio++) + if(!empty(&mlq_ready_queue[prio])) + return -1; +#endif + return (empty(&ready_queue) && empty(&run_queue)); +} + +void init_scheduler(void) { +#ifdef MLQ_SCHED + int i ; + + for (i = 0; i < MAX_PRIO; i ++) + mlq_ready_queue[i].size = 0; +#endif + ready_queue.size = 0; + run_queue.size = 0; + pthread_mutex_init(&queue_lock, NULL); +} + +#ifdef MLQ_SCHED +/* + * Stateful design for routine calling + * based on the priority and our MLQ policy + * We implement stateful here using transition technique + * State representation prio = 0 .. MAX_PRIO, curr_slot = 0..(MAX_PRIO - prio) + */ +struct pcb_t * get_mlq_proc(void) { + struct pcb_t * proc = NULL; + /*TODO: get a process from PRIORITY [ready_queue]. + * Remember to use lock to protect the queue. + */ + proc = dequeue(&mlq_ready_queue[0]); + return proc; +} + +void put_mlq_proc(struct pcb_t * proc) { + pthread_mutex_lock(&queue_lock); + enqueue(&mlq_ready_queue[proc->prio], proc); + pthread_mutex_unlock(&queue_lock); +} + +void add_mlq_proc(struct pcb_t * proc) { + pthread_mutex_lock(&queue_lock); + enqueue(&mlq_ready_queue[proc->prio], proc); + pthread_mutex_unlock(&queue_lock); +} + +struct pcb_t * get_proc(void) { + return get_mlq_proc(); +} + +void put_proc(struct pcb_t * proc) { + return put_mlq_proc(proc); +} + +void add_proc(struct pcb_t * proc) { + return add_mlq_proc(proc); +} +#else +struct pcb_t * get_proc(void) { + struct pcb_t * proc = NULL; + /*TODO: get a process from [ready_queue]. + * Remember to use lock to protect the queue. + * */ + return proc; +} + +void put_proc(struct pcb_t * proc) { + pthread_mutex_lock(&queue_lock); + enqueue(&run_queue, proc); + pthread_mutex_unlock(&queue_lock); +} + +void add_proc(struct pcb_t * proc) { + pthread_mutex_lock(&queue_lock); + enqueue(&ready_queue, proc); + pthread_mutex_unlock(&queue_lock); +} +#endif + + diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..02c4111 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,136 @@ + +#include "timer.h" +#include +#include + +static pthread_t _timer; + +struct timer_id_container_t { + struct timer_id_t id; + struct timer_id_container_t * next; +}; + +static struct timer_id_container_t * dev_list = NULL; + +static uint64_t _time; + +static int timer_started = 0; +static int timer_stop = 0; + + +static void * timer_routine(void * args) { + while (!timer_stop) { + printf("Time slot %3lu\n", current_time()); + int fsh = 0; + int event = 0; + /* Wait for all devices have done the job in current + * time slot */ + struct timer_id_container_t * temp; + for (temp = dev_list; temp != NULL; temp = temp->next) { + pthread_mutex_lock(&temp->id.event_lock); + while (!temp->id.done && !temp->id.fsh) { + pthread_cond_wait( + &temp->id.event_cond, + &temp->id.event_lock + ); + } + if (temp->id.fsh) { + fsh++; + } + event++; + pthread_mutex_unlock(&temp->id.event_lock); + } + + /* Increase the time slot */ + _time++; + + /* Let devices continue their job */ + for (temp = dev_list; temp != NULL; temp = temp->next) { + pthread_mutex_lock(&temp->id.timer_lock); + temp->id.done = 0; + pthread_cond_signal(&temp->id.timer_cond); + pthread_mutex_unlock(&temp->id.timer_lock); + } + if (fsh == event) { + break; + } + } + pthread_exit(args); +} + +void next_slot(struct timer_id_t * timer_id) { + /* Tell to timer that we have done our job in current slot */ + pthread_mutex_lock(&timer_id->event_lock); + timer_id->done = 1; + pthread_cond_signal(&timer_id->event_cond); + pthread_mutex_unlock(&timer_id->event_lock); + + /* Wait for going to next slot */ + pthread_mutex_lock(&timer_id->timer_lock); + while (timer_id->done) { + pthread_cond_wait( + &timer_id->timer_cond, + &timer_id->timer_lock + ); + } + pthread_mutex_unlock(&timer_id->timer_lock); +} + +uint64_t current_time() { + return _time; +} + +void start_timer() { + timer_started = 1; + pthread_create(&_timer, NULL, timer_routine, NULL); +} + +void detach_event(struct timer_id_t * event) { + pthread_mutex_lock(&event->event_lock); + event->fsh = 1; + pthread_cond_signal(&event->event_cond); + pthread_mutex_unlock(&event->event_lock); +} + +struct timer_id_t * attach_event() { + if (timer_started) { + return NULL; + }else{ + struct timer_id_container_t * container = + (struct timer_id_container_t*)malloc( + sizeof(struct timer_id_container_t) + ); + container->id.done = 0; + container->id.fsh = 0; + pthread_cond_init(&container->id.event_cond, NULL); + pthread_mutex_init(&container->id.event_lock, NULL); + pthread_cond_init(&container->id.timer_cond, NULL); + pthread_mutex_init(&container->id.timer_lock, NULL); + if (dev_list == NULL) { + dev_list = container; + dev_list->next = NULL; + }else{ + container->next = dev_list; + dev_list = container; + } + return &(container->id); + } +} + +void stop_timer() { + timer_stop = 1; + pthread_join(_timer, NULL); + while (dev_list != NULL) { + struct timer_id_container_t * temp = dev_list; + dev_list = dev_list->next; + pthread_cond_destroy(&temp->id.event_cond); + pthread_mutex_destroy(&temp->id.event_lock); + pthread_cond_destroy(&temp->id.timer_cond); + pthread_mutex_destroy(&temp->id.timer_lock); + free(temp); + } +} + + + + From eb9eac06644e63a23ca06cb3805a89883e785183 Mon Sep 17 00:00:00 2001 From: KoderuNoKo <4trung9kien123@gmail.com> Date: Fri, 10 May 2024 13:09:19 +0700 Subject: [PATCH 2/2] Fix on ANH KIET --- include/bitops.h | 11 ++ include/mm.h | 44 ++++++++ include/os-mm.h | 3 +- src/cpu-tlb.c | 191 +++++++++++++++++++++++++++++--- src/cpu-tlbcache.c | 267 +++++++++++++++++++++++++++++++++++++++++++-- src/mm-memphy.c | 18 ++- src/mm-vm.c | 120 ++++++++++++++++---- src/mm.c | 61 ++++++++--- 8 files changed, 651 insertions(+), 64 deletions(-) diff --git a/include/bitops.h b/include/bitops.h index 0cc9413..608de6d 100644 --- a/include/bitops.h +++ b/include/bitops.h @@ -6,6 +6,7 @@ #define BITS_PER_BYTE 8 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define DIV_ROUND_DOWN(n,d) ((n) / (d)) #define BIT(nr) (1U << (nr)) #define BIT_ULL(nr) (1ULL << (nr)) @@ -35,3 +36,13 @@ #define NBITS(n) (n==0?0:NBITS32(n)) #define EXTRACT_NBITS(nr, h, l) ((nr&GENMASK(h,l)) >> l) + +/* + * student implemented macros + */ + +// macros supporting 64-bit address +#define GENMASK64(h, l) \ + (((~0ULL) << (l)) & (~0ULL >> (64 - (h) - 1))) + +#define EXTRACT_NBITS64(nr, h, l) ((nr & GENMASK64(h,l)) >> l) \ No newline at end of file diff --git a/include/mm.h b/include/mm.h index 464a88a..db4b55f 100644 --- a/include/mm.h +++ b/include/mm.h @@ -38,6 +38,10 @@ /* SWPOFF */ #define PAGING_PTE_SWPOFF_LOBIT 5 #define PAGING_PTE_SWPOFF_HIBIT 25 +#define PAGING_PTE_PRESENT_BIT 31 +#define PAGING_PTE_SWAPPED_BIT 30 +#define PAGING_PTE_RESERVED_BIT 29 +#define PAGING_PTE_DIRTY_BIT 28 /* PTE masks */ #define PAGING_PTE_USRNUM_MASK GENMASK(PAGING_PTE_USRNUM_HIBIT,PAGING_PTE_USRNUM_LOBIT) @@ -116,6 +120,39 @@ int __read(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE *data); int __write(struct pcb_t *caller, int vmaid, int rgid, int offset, BYTE value); int init_mm(struct mm_struct *mm, struct pcb_t *caller); +/* CPUTLB prototypes */ +#define ASSOCIATED_MAPPING 0 + +/* TLB configs */ +#define TLB_ENTRY_SZ 12 // size of each TLB entry (in bytes) + +#if ASSOCIATED_MAPPING + +#define N_WAY 16 // degree of associated cache mapping + +/* TLB entry bit format */ +#define TLB_LRU_LBIT 0 +#define TLB_LRU_HBIT 3 + +#define TLB_PID_LBIT 4 +#define TLB_PID_HBIT 31 + +#define TLB_PTE_LBIT 32 +#define TLB_PTE_HBIT 63 + +#else + +#define TLB_PID_LBIT 0 +#define TLB_PID_HBIT 31 + +#define TLB_PGN_LBIT 32 +#define TLB_PGN_HBIT 63 + +#define TLB_PTE_LBIT 64 +#define TLB_PTE_HBIT 95 + +#endif + /* CPUTLB prototypes */ int tlb_change_all_page_tables_of(struct pcb_t *proc, struct memphy_struct * mp); int tlb_flush_tlb_of(struct pcb_t *proc, struct memphy_struct * mp); @@ -127,6 +164,13 @@ int init_tlbmemphy(struct memphy_struct *mp, int max_size); int TLBMEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value); int TLBMEMPHY_write(struct memphy_struct * mp, int addr, BYTE data); int TLBMEMPHY_dump(struct memphy_struct * mp); +/* local CPUTLB prototypes */ +int tlb_cache_read(struct memphy_struct * mp, uint32_t pid, int pgnum, int *frnum); +int tlb_cache_write(struct memphy_struct *mp, uint32_t pid, int pgnum, uint32_t pte); +int tlb_cache_clear(struct memphy_struct *mp, uint32_t pid, int pgnum); +int tlb_cache_update(struct memphy_struct *mp, uint32_t pid, int pgnum, uint32_t pte); + + /* VM prototypes */ int pgalloc(struct pcb_t *proc, uint32_t size, uint32_t reg_index); diff --git a/include/os-mm.h b/include/os-mm.h index 80a25aa..da91cda 100644 --- a/include/os-mm.h +++ b/include/os-mm.h @@ -12,6 +12,7 @@ typedef uint32_t addr_t; struct pgn_t{ int pgn; struct pgn_t *pg_next; + struct mm_struct* owner; }; /* @@ -82,4 +83,4 @@ struct memphy_struct { struct framephy_struct *used_fp_list; }; -#endif +#endif \ No newline at end of file diff --git a/src/cpu-tlb.c b/src/cpu-tlb.c index e5fe767..1535075 100644 --- a/src/cpu-tlb.c +++ b/src/cpu-tlb.c @@ -11,23 +11,85 @@ * CPU TLB * TLB module cpu/cpu-tlb.c */ - + #include "mm.h" +#include "os-mm.h" #include #include +/* + * update the pte of all TLB entries of a process + * @proc: caller process + * @mp: tlb memphy struct + */ int tlb_change_all_page_tables_of(struct pcb_t *proc, struct memphy_struct * mp) { /* TODO update all page table directory info * in flush or wipe TLB (if needed) */ +#if ASSOCIATED_MAPPING + + +#else + + for (int i = 0; i < PAGING_MAX_SYMTBL_SZ; i++) + { + struct vm_rg_struct* curr_rg = get_symrg_byid(proc->mm, i); + + if (curr_rg->rg_start == curr_rg->rg_end) { // region id unused - skip + continue; + } + + unsigned long rg_start = curr_rg->rg_start; + unsigned long rg_end = curr_rg->rg_end; + + int pgn = PAGING_PGN(rg_start); + while(pgn * PAGING_PAGESZ < rg_end) { + tlb_cache_update(mp, proc->pid, pgn, proc->mm->pgd[pgn]); + pgn++; + } + tlb_cache_update(mp, proc->pid, pgn, proc->mm->pgd[pgn]); + } + +#endif return 0; } +/* + * clear all TLB entries of a process + * @proc: caller process + * @mp: tlb memphy struct + */ int tlb_flush_tlb_of(struct pcb_t *proc, struct memphy_struct * mp) { /* TODO flush tlb cached*/ +#if ASSOCIATED_MAPPING + + + +#else + + for (int i = 0; i < PAGING_MAX_SYMTBL_SZ; i++) + { + struct vm_rg_struct* curr_rg = get_symrg_byid(proc->mm, i); + + if (curr_rg->rg_start == curr_rg->rg_end) { // region id unused - skip + continue; + } + + unsigned long rg_start = curr_rg->rg_start; + unsigned long rg_end = curr_rg->rg_end; + + int pgn = PAGING_PGN(rg_start); + while(pgn * PAGING_PAGESZ < rg_end) { + tlb_cache_clear(proc->tlb, proc->pid, pgn); + pgn++; + } + tlb_cache_clear(proc->tlb, proc->pid, pgn); + } + +#endif return 0; } @@ -43,10 +105,21 @@ int tlballoc(struct pcb_t *proc, uint32_t size, uint32_t reg_index) /* By default using vmaid = 0 */ val = __alloc(proc, 0, reg_index, size, &addr); - + if(proc == NULL) return -1; /* TODO update TLB CACHED frame num of the new allocated page(s)*/ /* by using tlb_cache_read()/tlb_cache_write()*/ + + if (val == 0 ) + { + int pgn = PAGING_PGN(addr); + while (pgn * PAGING_PAGESZ < addr + size) { + tlb_cache_write(proc->tlb, proc->pid, pgn, proc->mm->pgd[pgn]); + pgn++; + } + tlb_cache_write(proc->tlb, proc->pid, pgn, proc->mm->pgd[pgn]); + } + return val; } @@ -57,6 +130,19 @@ int tlballoc(struct pcb_t *proc, uint32_t size, uint32_t reg_index) */ int tlbfree_data(struct pcb_t *proc, uint32_t reg_index) { + // free entries in TLB + if(proc == NULL) return -1; + struct vm_rg_struct *curr_rg = get_symrg_byid(proc->mm, reg_index); + unsigned long rg_start = curr_rg->rg_start; + unsigned long rg_end = curr_rg->rg_end; + + int pgn = PAGING_PGN(rg_start); + while (pgn * PAGING_PAGESZ < rg_end) { + tlb_cache_clear(proc->tlb, proc->pid, pgn); + pgn++; + } + tlb_cache_clear(proc->tlb, proc->pid, pgn); + __free(proc, 0, reg_index); /* TODO update TLB CACHED frame num of freed page(s)*/ @@ -75,12 +161,49 @@ int tlbfree_data(struct pcb_t *proc, uint32_t reg_index) int tlbread(struct pcb_t * proc, uint32_t source, uint32_t offset, uint32_t destination) { - BYTE data, frmnum = -1; - + if(proc == NULL) return -1; + BYTE data = -1; + int frmnum = -1; + /* TODO retrieve TLB CACHED frame num of accessing page(s)*/ /* by using tlb_cache_read()/tlb_cache_write()*/ /* frmnum is return value of tlb_cache_read/write value*/ - + + // search in TLB for page + int val = tlb_cache_read(proc->tlb, proc->pid, source, &frmnum); + + if (frmnum >= 0) + { + // TLB hit & frame is available in MEMRAM + MEMPHY_read(proc->mram, frmnum*PAGING_PAGESZ + offset, &data); + destination = (uint32_t) data; + return 0; + } + + if (val < 0) + { + // TLB hit but the page is not available in MEMRAM + // attempt to bring it to MEMRAM + + pg_getpage(proc->mm, source, &frmnum, proc); + + if (frmnum < 0) { // attempt failed + return -1; + } + + tlb_cache_update(proc->tlb, proc->pid, source, proc->mm->pgd[source]); + } + else + { + // handle TLB miss + + // obtain the frame through page table + uint32_t pte = proc->mm->pgd[source]; + + // update TLB + tlb_cache_write(proc->tlb, proc->pid, source, pte); + } + #ifdef IODUMP if (frmnum >= 0) printf("TLB hit at read region=%d offset=%d\n", @@ -94,8 +217,8 @@ int tlbread(struct pcb_t * proc, uint32_t source, MEMPHY_dump(proc->mram); #endif - int val = __read(proc, 0, source, offset, &data); - + // perform the read + val = __read(proc, 0, source, offset, &data); destination = (uint32_t) data; /* TODO update TLB CACHED with frame num of recent accessing page(s)*/ @@ -104,15 +227,17 @@ int tlbread(struct pcb_t * proc, uint32_t source, return val; } -/*tlbwrite - CPU TLB-based write a region memory - *@proc: Process executing the instruction - *@data: data to be wrttien into memory - *@destination: index of destination register - *@offset: destination address = [destination] + [offset] +/* + * tlbwrite - CPU TLB-based write a region memory + * @proc: Process executing the instruction + * @data: data to be wrttien into memory + * @destination: index of destination register + * @offset: destination address = [destination] + [offset] */ int tlbwrite(struct pcb_t * proc, BYTE data, uint32_t destination, uint32_t offset) { + if(proc == NULL) return -1; int val; BYTE frmnum = -1; @@ -120,6 +245,46 @@ int tlbwrite(struct pcb_t * proc, BYTE data, /* by using tlb_cache_read()/tlb_cache_write() frmnum is return value of tlb_cache_read/write value*/ + //BYTE data, frmnum; + + /* TODO retrieve TLB CACHED frame num of accessing page(s)*/ + /* by using tlb_cache_read()/tlb_cache_write()*/ + /* frmnum is return value of tlb_cache_read/write value*/ + + // search in TLB for page + val = tlb_cache_read(proc->tlb, proc->pid, destination, &frmnum); + + if (frmnum >= 0) + { + /* TLB hit & frame is available in MEMRAM */ + MEMPHY_write(proc->mram, frmnum*PAGING_PAGESZ + offset, data); + return 0; + } + + if (val < 0) + { + /* TLB hit but the page is not available in MEMRAM */ + + // attempt to bring it to MEMRAM + pg_getpage(proc->mm, destination, &frmnum, proc); + + if (frmnum < 0) { // attempt failed + return -1; + } + + tlb_cache_update(proc->tlb, proc->pid, destination, proc->mm->pgd[destination]); + } + else + { + /* TLB miss */ + + // obtain the frame through page table of caller process + uint32_t pte = proc->mm->pgd[destination]; + + // update TLB + tlb_cache_write(proc->tlb, proc->pid, destination, pte); + } + #ifdef IODUMP if (frmnum >= 0) printf("TLB hit at write region=%d offset=%d value=%d\n", @@ -141,4 +306,4 @@ int tlbwrite(struct pcb_t * proc, BYTE data, return val; } -//#endif +//#endif \ No newline at end of file diff --git a/src/cpu-tlbcache.c b/src/cpu-tlbcache.c index a7a929e..611d7ca 100644 --- a/src/cpu-tlbcache.c +++ b/src/cpu-tlbcache.c @@ -18,39 +18,273 @@ #include "mm.h" +#include "bitops.h" #include #define init_tlbcache(mp,sz,...) init_memphy(mp, sz, (1, ##__VA_ARGS__)) + /* - * tlb_cache_read read TLB cache device + * tlb_cache_read read TLB cache device for process page number * @mp: memphy struct * @pid: process id * @pgnum: page number - * @value: obtained value + * @frnum: obtained frame number if hit */ -int tlb_cache_read(struct memphy_struct * mp, int pid, int pgnum, BYTE value) +int tlb_cache_read(struct memphy_struct * mp, uint32_t pid, int pgnum, int *frnum) { /* TODO: the identify info is mapped to * cache line by employing: * direct mapped, associated mapping etc. */ - return 0; + if(mp==NULL) return -1; + *frnum = -1; + int val = 0; + +#if ASSOCIATED_MAPPING + + int set_idx = pid % DIV_ROUND_DOWN(mp->maxsz, N_WAY); + + // translate set index to TLB entry + int entr = set_idx * N_WAY; + + // traverse the set for designated pgnum of pid + for (; entr < (set_idx + 1)*N_WAY && entr*TLB_ENTRY_SZ < mp->maxsz; entr++) + { + // retrieve the TLB entry + BYTE byte = 0; + uint64_t tlb_entr = 0; + + for (int i = TLB_ENTRY_SZ - 1; i >= 0; i--) { + TLBMEMPHY_READ(mp, entr*TLB_ENTRY_SZ + i, byte); + tlb_entr |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + // extract the pid and corresponding page number + uint32_t epid = EXTRACT_NBITS64(tlb_entr, TLB_PID_HBIT, TLB_PID_LBIT); + int epgnum = EXTRACT_NBITS64(tlb_entr, TLB_PTE_LBIT + PAGING_PTE_USRNUM_LOBIT, TLB_PTE_LBIT + PAGING_PTE_USRNUM_HIBIT); + + if (epid == pid && epgnum == pgnum) + { + // TLB hit - attempt to extract frame number of page if it is present in RAM + int present = EXTRACT_NBITS64(tlb_entr, + TLB_PTE_LBIT + PAGING_PTE_PRESENT_BIT, + TLB_PTE_LBIT + PAGING_PTE_PRESENT_BIT); + + if (present) { + *frnum = EXTRACT_NBITS64(tlb_entr, TLB_PTE_LBIT + PAGING_PTE_FPN_HIBIT, TLB_PTE_LBIT + PAGING_PTE_FPN_LOBIT); + } + else { + *frnum = -1; + } + + // update LRU + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ, byte); + byte = byte >> 1; // shift right + byte |= 0x80; // insert 1 + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ, byte); + } + else + { + // update LRU + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ, byte); + byte = byte >> 1; // shift right + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ, byte); + } + } + +#else + + // go to the entry where pid and pgnum will be mapped to + int entr = (pid * pgnum) % DIV_ROUND_DOWN(mp->maxsz, TLB_ENTRY_SZ); + + // retrieve information from entry + BYTE byte = 0; + uint32_t epid, epte; + int epgnum; + + // pid + for (int i = 0; i < sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epid |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + // page number + for (int i = sizeof(uint32_t); i < 2*sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epgnum |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + // pte + for (int i = sizeof(uint32_t) - 1; i >= 0; i--) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epte |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + if (epid == pid && epgnum == pgnum) + { + // TLB hit - attempt to extract frame number of page if it is present in RAM + int present = EXTRACT_NBITS64(epte, PAGING_PTE_PRESENT_BIT, PAGING_PTE_PRESENT_BIT); + + if (present) { + *frnum = EXTRACT_NBITS64(epte, PAGING_PTE_FPN_HIBIT, PAGING_PTE_FPN_LOBIT); + val = 0; + } + else { + // it is a hit but the frame is unavailable in MEMRAM + *frnum = -1; + val = -1; + } + } + +#endif + + return val; } /* - * tlb_cache_write write TLB cache device + * tlb_cache_write write new entry to TLB cache device * @mp: memphy struct * @pid: process id * @pgnum: page number - * @value: obtained value + * @pte: to write pte */ -int tlb_cache_write(struct memphy_struct *mp, int pid, int pgnum, BYTE value) +int tlb_cache_write(struct memphy_struct *mp, uint32_t pid, int pgnum, uint32_t pte) { /* TODO: the identify info is mapped to * cache line by employing: * direct mapped, associated mapping etc. */ + +#if ASSOCIATED_MAPPING + // TODO: implement cache writing for associated cache mapping technique + // handle case when it's a TLB hit the page is not present + + +#else + + // find the entry index in which new entry will be written + if(mp==NULL) return -1; + int entr = (pid * pgnum) % DIV_ROUND_DOWN(mp->maxsz, TLB_ENTRY_SZ); + + // write down the new pid + for (int i = TLB_PID_LBIT/sizeof(BYTE); i < TLB_PID_HBIT/sizeof(BYTE); i++) { + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ + i, (BYTE)(pid >> i*sizeof(BYTE) & 0xFF)); + } + + // write down new page number + for (int i = TLB_PGN_LBIT/sizeof(BYTE); i < TLB_PGN_HBIT/sizeof(BYTE); i++) { + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ + i, (BYTE)(pgnum >> i*sizeof(BYTE) & 0xFF)); + } + + // write down the new pte + for (int i = TLB_PTE_LBIT/sizeof(BYTE); i < TLB_PTE_HBIT/sizeof(BYTE); i++) { + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ + i, (BYTE)(pte >> i*sizeof(BYTE) & 0xFF)); + } + +#endif + + + return 0; +} +/* + * tlb_cache_clear: clear the cache entry (if hit) + * @mp: tlb memphy struct + * @pid: process id + * @pgnum: page number + */ +int tlb_cache_clear(struct memphy_struct *mp, uint32_t pid, int pgnum) +{ +#if ASSOCIATED_MAPPING + + +#else + if(mp==NULL) return 0; + int entr = (pid * pgnum) % DIV_ROUND_DOWN(mp->maxsz, TLB_ENTRY_SZ); + + // check if it is a hit + // retrieve information from entry + BYTE byte = 0; + uint32_t epid = 0; + uint32_t epgnum = 0; + + // pid + for (int i = 0; i < sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epid |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + // page number + for (int i = sizeof(uint32_t); i < 2*sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epgnum |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + if (epid == pid && epgnum == pgnum) + { + // hit - clear this entry + for (int i = TLB_ENTRY_SZ - 1; i >= 0; i--) { + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ + i, 0); + } + } + +#endif + + return 0; +} + +/* + * tlb_cache_update_pte: update the pte of pid and pgnum (if hit) + * @mp: tlb memphy struct + * @pid: calling process id + * @pgnum: page nunber + * @pte: new pte + */ +int tlb_cache_update(struct memphy_struct *mp, uint32_t pid, int pgnum, uint32_t pte) +{ +#if ASSOCIATED_MAPPING + + + +#else + if(mp==NULL) return 0; + int entr = (pid * pgnum) % DIV_ROUND_DOWN(mp->maxsz, TLB_ENTRY_SZ); + + // check if it is a hit + // retrieve information from entry + BYTE byte = 0; + uint32_t epid = 0; + uint32_t epgnum = 0; + + // pid + for (int i = 0; i < sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epid |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + // page number + for (int i = sizeof(uint32_t); i < 2*sizeof(uint32_t); i++) + { + TLBMEMPHY_read(mp, entr*TLB_ENTRY_SZ + i, &byte); + epgnum |= ((unsigned char)byte << i*sizeof(BYTE)); + } + + if (epid == pid && epgnum == pgnum) + { + // hit - update pte of this entry + for (int i = TLB_PTE_LBIT/sizeof(BYTE); i < TLB_PTE_HBIT/sizeof(BYTE); i++) { + TLBMEMPHY_write(mp, entr*TLB_ENTRY_SZ + i, (BYTE)(pte >> i*sizeof(BYTE) & 0xFF)); + } + } + +#endif + return 0; } @@ -62,8 +296,13 @@ int tlb_cache_write(struct memphy_struct *mp, int pid, int pgnum, BYTE value) */ int TLBMEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value) { - if (mp == NULL) - return -1; + if (mp == NULL) { + return -1; + } + else if (addr >= mp->maxsz) { + return -1; + } + /* TLB cached is random access by native */ *value = mp->storage[addr]; @@ -80,8 +319,12 @@ int TLBMEMPHY_read(struct memphy_struct * mp, int addr, BYTE *value) */ int TLBMEMPHY_write(struct memphy_struct * mp, int addr, BYTE data) { - if (mp == NULL) - return -1; + if (mp == NULL) { + return -1; + } + else if (addr >= mp->maxsz) { + return -1; + } /* TLB cached is random access by native */ mp->storage[addr] = data; @@ -117,3 +360,5 @@ int init_tlbmemphy(struct memphy_struct *mp, int max_size) } //#endif + +// Student costume functions \ No newline at end of file diff --git a/src/mm-memphy.c b/src/mm-memphy.c index e638ce3..272911d 100644 --- a/src/mm-memphy.c +++ b/src/mm-memphy.c @@ -6,7 +6,7 @@ #include "mm.h" #include - +#include /* * MEMPHY_mv_csr - move MEMPHY cursor * @mp: memphy struct @@ -154,12 +154,22 @@ int MEMPHY_get_freefp(struct memphy_struct *mp, int *retfpn) return 0; } - -int MEMPHY_dump(struct memphy_struct * mp) + int MEMPHY_dump(struct memphy_struct * mp) { /*TODO dump memphy contnt mp->storage * for tracing the memory content */ + printf("%d", mp->maxsz); + for (int i = 0; i < mp->maxsz; i++) + { + if ((i != 0) && (i % 40 == 0)) { // newline every 40 bytes + printf("\n"); + } + else if ((i != 0) && (i % 4 == 0)) { // space every 4 bytes + printf(" "); + } + printf("%c", mp->storage[i]); + } return 0; } @@ -184,7 +194,7 @@ int MEMPHY_put_freefp(struct memphy_struct *mp, int fpn) int init_memphy(struct memphy_struct *mp, int max_size, int randomflg) { mp->storage = (BYTE *)malloc(max_size*sizeof(BYTE)); - mp->maxsz = max_size; + mp->maxsz = max_size; MEMPHY_format(mp,PAGING_PAGESZ); diff --git a/src/mm-vm.c b/src/mm-vm.c index c2375d2..1101b4d 100644 --- a/src/mm-vm.c +++ b/src/mm-vm.c @@ -14,18 +14,18 @@ *@rg_elmt: new region * */ -int enlist_vm_freerg_list(struct mm_struct *mm, struct vm_rg_struct rg_elmt) +int enlist_vm_freerg_list(struct mm_struct *mm, struct vm_rg_struct* rg_elmt) { struct vm_rg_struct *rg_node = mm->mmap->vm_freerg_list; - if (rg_elmt.rg_start >= rg_elmt.rg_end) + if (rg_elmt->rg_start >= rg_elmt->rg_end) return -1; if (rg_node != NULL) - rg_elmt.rg_next = rg_node; + rg_elmt->rg_next = rg_node; /* Enlist the new region */ - mm->mmap->vm_freerg_list = &rg_elmt; + mm->mmap->vm_freerg_list = rg_elmt; return 0; } @@ -69,7 +69,7 @@ struct vm_rg_struct *get_symrg_byid(struct mm_struct *mm, int rgid) return &mm->symrgtbl[rgid]; } -/*__alloc - allocate a region memory +/*__alloc - allocate a region memoryfv *@caller: caller *@vmaid: ID vm area to alloc memory region *@rgid: memory region ID (used to identify variable in symbole table) @@ -79,7 +79,7 @@ struct vm_rg_struct *get_symrg_byid(struct mm_struct *mm, int rgid) */ int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr) { - /*Allocate at the toproof */ + /*Allocate at the toproof */\ struct vm_rg_struct rgnode; if (get_free_vmrg_area(caller, vmaid, size, &rgnode) == 0) @@ -93,9 +93,10 @@ int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr } /* TODO get_free_vmrg_area FAILED handle the region management (Fig.6)*/ - + /*Attempt to increate limit to get space */ struct vm_area_struct *cur_vma = get_vma_by_num(caller->mm, vmaid); + int inc_sz = PAGING_PAGE_ALIGNSZ(size); //int inc_limit_ret int old_sbrk ; @@ -105,14 +106,16 @@ int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr /* TODO INCREASE THE LIMIT * inc_vma_limit(caller, vmaid, inc_sz) */ - inc_vma_limit(caller, vmaid, inc_sz); + if( inc_vma_limit(caller, vmaid, inc_sz) == 0 ) { - /*Successful increase limit */ - caller->mm->symrgtbl[rgid].rg_start = old_sbrk; - caller->mm->symrgtbl[rgid].rg_end = old_sbrk + size; - - *alloc_addr = old_sbrk; + caller->mm->symrgtbl[rgid].rg_start = old_sbrk; + caller->mm->symrgtbl[rgid].rg_end = old_sbrk + size; //end cua cai nay khong can align, oke roi + *alloc_addr = old_sbrk; //tra ve + cur_vma->sbrk = old_sbrk + inc_sz;// Cap nhat sbrk?? aligned + //Cap nhat pgd? ham inc tren lam r + + } return 0; } @@ -125,16 +128,53 @@ int __alloc(struct pcb_t *caller, int vmaid, int rgid, int size, int *alloc_addr */ int __free(struct pcb_t *caller, int vmaid, int rgid) { - struct vm_rg_struct rgnode; - - if(rgid < 0 || rgid > PAGING_MAX_SYMTBL_SZ) + printf("Free here, proc %d, vmaid %d, rgid %d\n", caller->pid, vmaid, rgid); + //ncl set cai rgid do start = end = -1, + //Set bit present = 0 + //Co trong RAM/ SWP thi xoa (cho vao freelist) + //Lam gi voi dong BYTE? -> Muon vao duoc BYTE phai thong qua virtual, RAM/SWP nay + //tra vao free list + // struct vm_rg_struct rgnode; -> chang biet lam gi + + if(rgid < 0 || rgid > PAGING_MAX_SYMTBL_SZ) { + //pthread_mutex_unlock(&mem_lock); return -1; + } /* TODO: Manage the collect freed region to freerg_list */ + struct vm_rg_struct *currg = get_symrg_byid(caller->mm, rgid); + + //Xoa trong RAM/ SWP, dem ra ngoai RAM het! + //Can co duoc pgn, pte, start/end -> byte addressable, chua align dau + if(currg->rg_start % PAGING_PAGESZ != 0) { //Kiem tra lai page_align + printf("Region start is not aligned, currg->rg_start %ld\n", currg->rg_start); + } + if(currg->rg_start == -1) { //Double free, unsigned ??? <0 k dc dau + printf("Double free region %d, free_rg->rg_start %ld, free_rg->rg_end %ld\n", rgid, currg->rg_start, currg->rg_end); + //pthread_mutex_unlock(&mem_lock); + return 0; + } + int numpages = (PAGING_PAGE_ALIGNSZ(currg->rg_end - currg->rg_start)) / PAGING_PAGESZ; + int pgn_start = PAGING_PGN(currg->rg_start); + // Set lai PTE, set present = 0. Set byte ve NULL? + for(int i = pgn_start; i < (pgn_start + numpages); i++) { + CLRBIT((caller->mm->pgd[i]), PAGING_PTE_PRESENT_MASK); + /* Can set cac byte ve NULL khong? + if(!PAGING_PAGE_IN_SWAP(caller->mm->pgd[i])) { //trong RAM + }*/ + } + + //Tao 1 free region. Thi no van co fpn cu ma + struct vm_rg_struct *free_rg = malloc(sizeof(struct vm_rg_struct)); + free_rg->rg_start = currg->rg_start; + free_rg->rg_end = PAGING_PAGE_ALIGNSZ(currg->rg_end); + /*enlist the obsoleted memory region*/ + enlist_vm_freerg_list(caller->mm, free_rg); - /*enlist the obsoleted memory region */ - enlist_vm_freerg_list(caller->mm, rgnode); + currg->rg_end = -1; + currg->rg_start = -1; + //pthread_mutex_unlock(&mem_lock); return 0; } @@ -204,6 +244,7 @@ int pg_getpage(struct mm_struct *mm, int pgn, int *fpn, struct pcb_t *caller) #ifdef CPU_TLB /* Update its online status of TLB (if needed) */ + #endif enlist_pgn_node(&caller->mm->fifo_pgn,pgn); @@ -405,9 +446,21 @@ struct vm_rg_struct* get_vm_area_node_at_brk(struct pcb_t *caller, int vmaid, in int validate_overlap_vm_area(struct pcb_t *caller, int vmaid, int vmastart, int vmaend) { //struct vm_area_struct *vma = caller->mm->mmap; - + /* TODO validate the planned memory area is not overlapped */ + struct vm_area_struct *vma = caller->mm->mmap; + // Traverse through the existing memory areas + while (vma != NULL) { + // Check if the planned memory area overlaps with the current VMA + if ((vma->vm_end > vmastart && vma->vm_start < vmaend) || + (vmastart < vma->vm_end && vmaend > vma->vm_start)) { + // Overlap detected + return -1; // Error: Overlapping memory area + } + // Move to the next VMA + vma = vma->vm_next; + } return 0; } @@ -447,17 +500,40 @@ int inc_vma_limit(struct pcb_t *caller, int vmaid, int inc_sz) *@pgn: return page number * */ + int find_victim_page(struct mm_struct *mm, int *retpgn) { - struct pgn_t *pg = mm->fifo_pgn; + struct pgn_t *pgit = mm->fifo_pgn; /* TODO: Implement the theorical mechanism to find the victim page */ + // implementing FIFO mechanism - free(pg); + // ERROR! empty page list + if (pgit == NULL) { + perror("\nERROR! Cannot find victime page since page list is empty!\n"); + *retpgn = -1; + return -1; + } + else if(pgit->pg_next == NULL){ + *retpgn = pgit->pgn;; + } + else{ + // traverse to end of queue + while(pgit->pg_next->pg_next != NULL) + { + pgit = pgit->pg_next; + } + + struct pgn_t * last = pgit->pg_next; + *retpgn = last->pgn; + pgit->pg_next = NULL; + pgit = last; + } + + free(pgit); return 0; } - /*get_free_vmrg_area - get a free vm region *@caller: caller *@vmaid: ID vm area to alloc memory region diff --git a/src/mm.c b/src/mm.c index e590e70..6be0677 100644 --- a/src/mm.c +++ b/src/mm.c @@ -89,21 +89,37 @@ int vmap_page_range(struct pcb_t *caller, // process call struct framephy_struct *fpit = malloc(sizeof(struct framephy_struct)); //int fpn; int pgit = 0; - int pgn = PAGING_PGN(addr); + int pgn = PAGING_PGN(addr); // chuyen tu virtual -> index cua PTE ret_rg->rg_end = ret_rg->rg_start = addr; // at least the very first space is usable - fpit->fp_next = frames; + fpit->fp_next = frames; //free frame cbi map - /* TODO map range of frame to address space - * [addr to addr + pgnum*PAGING_PAGESZ + /* TODO map range of frame to address space (virtual address) + * [addr (start) to addr(end -> start + ...) + pgnum*PAGING_PAGESZ (So address dc tang len) * in page table caller->mm->pgd[] */ - + // tom lai la chuyen doi PTE + // Luu y la co truong hop map khong du, vi co the dia chi no cap nhieu qua, tran luon khoi so page co the cap cua pgd + + for( ; pgit < pgnum; pgit++) { + if(fpit == NULL) { + printf("Not enough frame in alloc\n"); + return -1; // k du frame + } + if((pgn+pgit) >= PAGING_MAX_PGN) { + printf("Out_of_range pgd of alloc\n"); + return -1; //het cho roi + } + pte_set_fpn(caller->mm->pgd + (pgn+pgit), fpit->fpn); //map cai pte tai idx voi cai frame trong /* Tracking for later page replacement activities (if needed) * Enqueue new usage page */ - enlist_pgn_node(&caller->mm->fifo_pgn, pgn+pgit); + enlist_pgn_node(&caller->mm->fifo_pgn, pgn+pgit); // cho thi dung, FIFO + + ret_rg->rg_end = ret_rg->rg_end + PAGING_PAGESZ; + fpit = fpit->fp_next; //qua frame tiep theo + } return 0; } @@ -117,16 +133,32 @@ int vmap_page_range(struct pcb_t *caller, // process call int alloc_pages_range(struct pcb_t *caller, int req_pgnum, struct framephy_struct** frm_lst) { - int pgit, fpn; - //struct framephy_struct *newfp_str; + int pgit; + int retfpn; + struct framephy_struct *new_frm = NULL; + for(pgit = 0; pgit < req_pgnum; pgit++) { - if(MEMPHY_get_freefp(caller->mram, &fpn) == 0) - { - - } else { // ERROR CODE of obtaining somes but not enough frames - } + if(MEMPHY_get_freefp(caller->mram, &retfpn) == 0) + { + // new frame obtained - put it in the returned frame list + new_frm = malloc(sizeof(struct framephy_struct)); + new_frm->fpn = retfpn; + new_frm->fp_next = *frm_lst; + + *frm_lst = new_frm; + } + else + { + // ERROR CODE of obtaining somes but not enough frames + if (frm_lst == NULL) { + return -1; // failed to obtain any frame + } + else { + return -3000; // failed to obtain all frames + } + } } return 0; @@ -172,6 +204,9 @@ int vm_map_ram(struct pcb_t *caller, int astart, int aend, int mapstart, int inc * do the swaping all to swapper to get the all in ram */ vmap_page_range(caller, mapstart, incpgnum, frm_lst, ret_rg); + if( (ret_rg->rg_start != astart) || (ret_rg->rg_end != aend) ) { + printf("Mapped region is wrong?\n%ld %d %ld %d\n", ret_rg->rg_start, astart, ret_rg->rg_end, aend); + } return 0; }