diff options
author | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-10-03 21:54:08 +0300 |
---|---|---|
committer | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-10-07 21:30:46 +0300 |
commit | 8ebff284d24bf2a201f9518c5b7b9e399228f1ca (patch) | |
tree | 7fec38cb2697488e7b06e60672701bdbe48719a6 | |
parent | 5b0b432533b56ad79e7352ba0349e64210e177be (diff) |
Move console translator to new pager interface.
This implementation transfers data by one page and uses inline functions.
* console/pager.c (cons_read_pages): Function renamed. Old name was
pager_read_page.
(cons_write_pages): Function renamed. Old name was pager_write_page.
(cons_report_extent): Function renamed. Old name was pager_report_extent.
(cons_clear_user_data): Function renamed. Old name was pager_clear_user_data.
(pager_dropweak): Delete obsolete function.
(pager_unlock_page): Likewise.
(console_ops): New structure.
(user_pager_create): Function changed.
-rw-r--r-- | console/pager.c | 156 |
1 files changed, 103 insertions, 53 deletions
diff --git a/console/pager.c b/console/pager.c index 092a8820..cb0ebc7b 100644 --- a/console/pager.c +++ b/console/pager.c @@ -45,71 +45,125 @@ static struct port_bucket *pager_bucket; /* Implement the pager_clear_user_data callback from the pager library. */ void -pager_clear_user_data (struct user_pager_info *upi) +cons_clear_user_data (struct user_pager_info *upi) { int idx; - - for (idx = 0; idx < upi->memobj_npages; idx++) - if (upi->memobj_pages[idx]) - vm_deallocate (mach_task_self (), upi->memobj_pages[idx], vm_page_size); - free (upi); + int len = 1; + + for (idx = 1; idx < upi->memobj_npages; idx++) + if (upi->memobj_pages[idx] - vm_page_size != upi->memobj_pages[idx - 1]) + { + if (upi->memobj_pages[idx - len]) + { + vm_deallocate (mach_task_self (), upi->memobj_pages[idx - len], + len * vm_page_size); + len = 1; + } + } + else + len ++; + + vm_deallocate (mach_task_self (), upi->memobj_pages[idx - len], + len * vm_page_size); } -error_t -pager_read_page (struct user_pager_info *upi, vm_offset_t page, - vm_address_t *buf, int *writelock) +void +cons_read_pages (struct pager *pager, struct user_pager_info *upi, + off_t start, off_t npages) { - /* XXX clients should get a read only object. */ - *writelock = 0; - - if (upi->memobj_pages[page / vm_page_size] != (vm_address_t) NULL) - { - *buf = upi->memobj_pages[page / vm_page_size]; - upi->memobj_pages[page / vm_page_size] = (vm_address_t) NULL; - } - else - *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - return 0; + enum read_state {NO_PAGE = 0, CONSECUTIVE_PAGE, RANDOM_PAGE}; + + inline error_t process_code (off_t address) + { + off_t page = address / vm_page_size; + vm_address_t cur_addr = upi->memobj_pages[page]; + if (cur_addr == (vm_address_t) NULL) + return NO_PAGE; + else if (cur_addr - vm_page_size == upi->memobj_pages[page - 1]) + return CONSECUTIVE_PAGE; + else + return RANDOM_PAGE; + } + + inline void no_error_code (off_t range_start, off_t range_len) + { + /* We haven't allocated memory for this range, so just do it. */ + void * buf; + buf = mmap (0, range_len, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); + pager_data_supply (pager, 0 /* precious */, 0 /* writelock */, + range_start, range_len / vm_page_size, + buf, 1 /* dealloc */); + } + + inline void error_code (int err, off_t range_start, off_t range_len) + { + off_t page = range_start; + switch (err) + { + case CONSECUTIVE_PAGE: + /* It is range of pages that are placed consecutive. + Supply all of them at once. */ + pager_data_supply (pager, 0, 0, range_start, + range_len / vm_page_size, + (void *)upi->memobj_pages[range_start], 1); + for (; page < range_start + range_len / vm_page_size; page ++) + upi->memobj_pages[page] = (vm_address_t) NULL; + break; + case RANDOM_PAGE: + /* Range is not of consecutive pages, so report about each page + separately */ + for (; page < range_start + range_len / vm_page_size; page ++) + { + pager_data_supply (pager, 0, 0, page, 1, + (void *)upi->memobj_pages[page], 1); + upi->memobj_pages[page] = (vm_address_t) NULL; + } + break; + } + } + + pager_process_pages (start, npages, vm_page_size, + &process_code, &no_error_code, &error_code); } -error_t -pager_write_page (struct user_pager_info *upi, vm_offset_t page, - vm_address_t buf) +void +cons_write_pages (struct pager *pager, struct user_pager_info *upi, + off_t start, off_t npages, void *buf, int dealloc) { - assert (upi->memobj_pages[page / vm_page_size] == (vm_address_t) NULL); - upi->memobj_pages[page / vm_page_size] = buf; - return 0; -} + off_t page; + for (page = start; page < npages; page++) + { + assert (upi->memobj_pages[page] == (vm_address_t) NULL); + upi->memobj_pages[page] = (vm_address_t) buf; + buf += vm_page_size; + } -error_t -pager_unlock_page (struct user_pager_info *pager, - vm_offset_t address) -{ - assert (!"unlocking requested on unlocked page"); - return 0; + assert (!dealloc && "There shouldn't be deallocation"); } /* Tell how big the file is. */ -error_t -pager_report_extent (struct user_pager_info *upi, - vm_address_t *offset, - vm_size_t *size) +void +cons_report_extent (struct user_pager_info *upi, + off_t *offset, + off_t *size) { *offset = 0; *size = upi->memobj_npages * vm_page_size; - return 0; } - -void -pager_dropweak (struct user_pager_info *upi) -{ -} +struct pager_ops cons_ops = + { + .read = &cons_read_pages, + .write = &cons_write_pages, + .unlock = NULL, + .report_extent = &cons_report_extent, + .clear_user_data = &cons_clear_user_data, + .dropweak = NULL + }; /* A top-level function for the paging thread that just services paging @@ -148,21 +202,15 @@ user_pager_create (struct user_pager *user_pager, unsigned int npages, struct cons_display **user) { error_t err; - struct user_pager_info *upi; - - upi = calloc (1, sizeof (struct user_pager_info) - + sizeof (vm_address_t) * npages); - if (!upi) - return errno; + size_t upi_size = (sizeof (struct user_pager_info) + + sizeof (vm_address_t) * npages); - upi->memobj_npages = npages; /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */ - user_pager->pager = pager_create (upi, pager_bucket, + user_pager->pager = pager_create (&cons_ops, upi_size, pager_bucket, 1, MEMORY_OBJECT_COPY_DELAY); if (!user_pager->pager) { - free (upi); return errno; } user_pager->memobj = pager_get_port (user_pager->pager); @@ -188,6 +236,8 @@ user_pager_create (struct user_pager *user_pager, unsigned int npages, return err; } + pager_get_upi(user_pager->pager)->memobj_npages = npages; + return 0; } |