#include #include "filesys/file.h" #include "threads/thread.h" #include "threads/vaddr.h" #include "threads/malloc.h" #include "threads/palloc.h" #include "vm/mmap.h" #include "vm/page.h" static struct mmap_table_entry *mmap_table_get (struct mmap_table *table, mapid_t mapid); /* initialize memory mapped files table */ bool mmap_table_init (struct mmap_table *table) { table->ids = palloc_get_page (PAL_ZERO); if (table->ids == NULL) return false; table->id_cap = PGSIZE / sizeof (table->ids[0]); table->id_free = 0; table->id_max = -1; return true; } /* frees the content of mmap table */ void mmap_table_free (struct mmap_table *table) { //TODO palloc_free_page (table->ids); } /* inserts a new mmap entry in the mmap table returns -1 if entry is invalid or already in the table */ mapid_t mmap_table_insert (struct mmap_table *table, void *addr, struct file *file, off_t len) { off_t ofs = 0; size_t page_read_bytes; struct mmap_table_entry *mme; mapid_t mapid; /* no more entries left */ if (table->id_free >= table->id_cap) return -1; mme = malloc (sizeof *mme); if (mme == NULL) return -1; mapid = table->id_free++; mme->addr = addr; mme->file = file; table->ids[mapid] = mme; /* create needed pages in page table */ while (len > 0) { page_read_bytes = (len < PGSIZE) ? len : PGSIZE; if (!page_table_insert_segment (&thread_current ()->page_table, file, ofs, addr, page_read_bytes, true)) return -1; /* Advance. */ len -= PGSIZE; ofs += page_read_bytes; addr += PGSIZE; } /* update index of free/max mapid index */ if (mapid > table->id_max) table->id_max = mapid; while (table->ids[table->id_free] != NULL) { table->id_free++; if (table->id_free >= table->id_cap) break; } return mapid; } static struct mmap_table_entry * mmap_table_get (struct mmap_table *table, mapid_t mapid) { if (mapid < 0 || mapid >= table->id_cap || !table->ids[mapid]) return NULL; return table->ids[mapid]; } bool mmap_table_remove (struct mmap_table *table, mapid_t mapid) { struct mmap_table_entry *mme = mmap_table_get(table, mapid); if (mme == NULL) return false; table->ids[mapid] = NULL; //TODO /* update index of free/max file descriptor index */ if (mapid < table->id_free) table->id_free = mapid; while (table->ids[table->id_max] == NULL) { table->id_max--; if (table->id_max < 0) break; } return true; }