#include #include "stackgrowth.h" #include "threads/palloc.h" #include "threads/thread.h" #include "threads/vaddr.h" #include "userprog/pagedir.h" #define MAX_STACK_ACCESS_DIST 32 static bool needs_new_page (const void *addr, const void *esp); static bool grow_stack (const void *addr); bool try_alloc_new_page (const void *ptr, const void *esp) { if (needs_new_page (ptr, esp)) { if (!grow_stack (ptr)) return 0; else return 1; } else return 0; } /* Validates a given address for being a stack query and not a generic erroneous address */ static bool needs_new_page (const void *addr, const void *esp) { return (is_user_vaddr (addr) && (uint32_t*)addr >= ((uint32_t*)esp - MAX_STACK_ACCESS_DIST) && ((PHYS_BASE - pg_round_down (addr)) <= MAX_STACK_SIZE)); } /* Extends the stack by the necessary number of pages */ static bool grow_stack (const void *addr) { struct thread *t = thread_current (); void *last_page = pg_round_down (addr); uint8_t *new_page = palloc_get_page (PAL_USER | PAL_ZERO); if ( new_page == NULL) return false; bool added_page = pagedir_get_page (t->pagedir, last_page) == NULL && pagedir_set_page (t->pagedir, last_page, new_page, true); if (!added_page) { palloc_free_page (new_page); return false; } return true; }