Files
pintos_22/src/vm/stackgrowth.c

58 lines
1.4 KiB
C

#include <stdio.h>
#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;
}