diff options
Diffstat (limited to 'console')
-rw-r--r-- | console/ChangeLog | 17 | ||||
-rw-r--r-- | console/Makefile | 4 | ||||
-rw-r--r-- | console/display.c | 184 | ||||
-rw-r--r-- | console/pager.c | 221 | ||||
-rw-r--r-- | console/pager.h | 47 |
5 files changed, 311 insertions, 162 deletions
diff --git a/console/ChangeLog b/console/ChangeLog index a538f6c4..049c1b74 100644 --- a/console/ChangeLog +++ b/console/ChangeLog @@ -1,5 +1,22 @@ 2002-09-22 Marcus Brinkmann <marcus@gnu.org> + * pager.c, pager.h: New file. + * Makefile (SRCS): Add pager.c. + (LCLHDRS): Add pager.h. + * display.c: Do not include <hurd/pager.h>, <sys/mman.h>, + <sys/io.h>, <fcntl.h> and <sys/fcntl.h>. Include <hurd/ports.h> + and "pager.h". + (struct display): Replace member PAGER and MEMOBJ with USER_PAGER. + (display_get_filemap): Implement with user_pager_get_filemap. + (user_destroy): Implement with user_pager_destroy. + (user_create): Implement partially with user_create. + (display_init): Call user_pager_init. + (struct user_pager_info, pager_bucket, pager_clear_user_data, + pager_read_page, pager_write_page, pager_unlock_page, + pager_report_extent, pager_dropweak, service_paging_requests): + Move to ... + * pager.c: ... here. + * console.c: Include <mach.h>. (netfs_S_dir_notice_changes): New variable PREQ. Clean out the dead wood, eh, dead name notifications from the CONS->dirmod_req diff --git a/console/Makefile b/console/Makefile index 0ad406e7..71f7f1e4 100644 --- a/console/Makefile +++ b/console/Makefile @@ -23,8 +23,8 @@ makemode := server target = console -SRCS = console.c display.c input.c -LCLHDRS = display.h input.h priv.h mutations.h +SRCS = console.c display.c pager.c input.c +LCLHDRS = display.h pager.h input.h priv.h mutations.h DIST_FILES = hurd.ti MIGSTUBS = notifyServer.o tioctlServer.o fs_notifyUser.o diff --git a/console/display.c b/console/display.c index 8d75976c..ac9ef92f 100644 --- a/console/display.c +++ b/console/display.c @@ -21,7 +21,6 @@ #include <stddef.h> #include <errno.h> -#include <fcntl.h> #include <unistd.h> #include <wchar.h> #include <iconv.h> @@ -30,13 +29,10 @@ #include <assert.h> #include <error.h> -#include <sys/io.h> -#include <sys/fcntl.h> -#include <sys/mman.h> #include <cthreads.h> #include <hurd.h> -#include <hurd/pager.h> +#include <hurd/ports.h> #include <hurd/console.h> #ifndef __STDC_ISO_10646__ @@ -44,6 +40,7 @@ #endif #include "display.h" +#include "pager.h" struct changes @@ -141,12 +138,6 @@ struct attr }; typedef struct attr *attr_t; -struct user_pager_info -{ - size_t memobj_npages; - vm_address_t memobj_pages[0]; -}; - /* Pending directory and file modification requests. */ struct modreq { @@ -193,8 +184,8 @@ struct display struct cons_display *user; - struct pager *pager; - memory_object_t memobj; + /* The pager for the USER member. */ + struct user_pager user_pager; /* A list of ports to send file change notifications to. */ struct modreq *filemod_reqs; @@ -205,99 +196,6 @@ struct display }; -/* We need a separate bucket for the pager ports. */ -struct port_bucket *pager_bucket; - -mach_port_t -display_get_filemap (display_t display, vm_prot_t prot) -{ - error_t err; - - /* Add a reference for each call, the caller will deallocate it. */ - err = mach_port_mod_refs (mach_task_self (), display->memobj, - MACH_PORT_RIGHT_SEND, +1); - assert_perror (err); - - return display->memobj; -} - -/* Implement the pager_clear_user_data callback from the pager library. */ -void -pager_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); -} - -error_t -pager_read_page (struct user_pager_info *upi, vm_offset_t page, - vm_address_t *buf, int *writelock) -{ - /* 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; -} - -error_t -pager_write_page (struct user_pager_info *upi, vm_offset_t page, - vm_address_t buf) -{ - assert (upi->memobj_pages[page / vm_page_size] == (vm_address_t) NULL); - upi->memobj_pages[page / vm_page_size] = buf; - return 0; -} - -error_t -pager_unlock_page (struct user_pager_info *pager, - vm_offset_t address) -{ - assert (!"unlocking requested on unlocked page"); - return 0; -} - -/* Tell how big the file is. */ -error_t -pager_report_extent (struct user_pager_info *upi, - vm_address_t *offset, - vm_size_t *size) -{ - *offset = 0; - *size = upi->memobj_npages * vm_page_size; - return 0; -} - -void -pager_dropweak (struct user_pager_info *upi) -{ -} - -/* A top-level function for the paging thread that just services paging - requests. */ -static void -service_paging_requests (any_t arg) -{ - struct port_bucket *pager_bucket = arg; - for (;;) - ports_manage_port_operations_multithread (pager_bucket, - pager_demuxer, - 1000 * 60 * 2, - 1000 * 60 * 10, 0); -} - - /* The bucket and class for notification messages. */ static struct port_bucket *notify_bucket; static struct port_class *notify_class; @@ -874,54 +772,21 @@ conchar_memset (conchar_t *conchar, wchar_t chr, conchar_attr_t attr, } } + static error_t user_create (display_t display, uint32_t width, uint32_t height, uint32_t lines, wchar_t chr, conchar_attr_t attr) { error_t err; struct cons_display *user; - struct user_pager_info *upi; - - int npages = (round_page (sizeof (struct cons_display) + - sizeof (conchar_t) * width * lines)) / vm_page_size; - - upi = calloc (1, sizeof (struct user_pager_info) - + sizeof (vm_address_t) * npages); - if (!upi) - return MACH_PORT_NULL; - upi->memobj_npages = npages; - /* 1 & MOCD correct? */ - display->pager = pager_create (upi, pager_bucket, - 1, MEMORY_OBJECT_COPY_DELAY); - if (display->pager == 0) - { - free (upi); - return errno; - } - display->memobj = pager_get_port (display->pager); - ports_port_deref (display->pager); - - mach_port_insert_right (mach_task_self (), display->memobj, display->memobj, - MACH_MSG_TYPE_MAKE_SEND); - - err = vm_map (mach_task_self (), - (vm_address_t *) &user, - (vm_size_t) npages * vm_page_size, - (vm_address_t) 0, - 1 /* ! (flags & MAP_FIXED) */, - display->memobj, 0 /* (vm_offset_t) offset */, - 0 /* ! (flags & MAP_SHARED) */, - VM_PROT_READ | VM_PROT_WRITE, - VM_PROT_READ | VM_PROT_WRITE, - VM_INHERIT_NONE); + int npages = (round_page (sizeof (struct cons_display) + sizeof (conchar_t) + * width * lines)) / vm_page_size; + err = user_pager_create (&display->user_pager, npages, &display->user); if (err) - { - /* UPI will be cleaned up by libpager. */ - mach_port_deallocate (mach_task_self (), display->memobj); - return err; - } - + return err; + + user = display->user; user->magic = CONS_MAGIC; user->version = CONS_VERSION_MAJ << 16 | CONS_VERSION_AGE; user->changes.buffer = offsetof (struct cons_display, changes._buffer) @@ -938,18 +803,13 @@ user_create (display_t display, uint32_t width, uint32_t height, user->cursor.status = CONS_CURSOR_NORMAL; conchar_memset (user->_matrix, chr, attr, user->screen.width * user->screen.lines); - - display->user = user; return 0; } static void user_destroy (display_t display) { - /* The pager will be deallocated by libpager. */ - vm_deallocate (mach_task_self (), (vm_offset_t) display->user, - pager_get_upi (display->pager)->memobj_npages * vm_page_size); - mach_port_deallocate (mach_task_self (), display->memobj); + user_pager_destroy (&display->user_pager, display->user); } @@ -1922,14 +1782,7 @@ void display_destroy_complete (void *pi); void display_init (void) { - /* Create the pager bucket, and start to serve paging requests. */ - pager_bucket = ports_create_bucket (); - if (! pager_bucket) - error (5, errno, "Cannot create pager bucket"); - - /* Make a thread to service paging requests. */ - cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests, - (any_t) pager_bucket)); + user_pager_init (); /* Create the notify bucket, and start to serve notifications. */ notify_bucket = ports_create_bucket (); @@ -2250,3 +2103,14 @@ display_discard_output (display_t display) display->output.size = 0; mutex_unlock (&display->lock); } + + +mach_port_t +display_get_filemap (display_t display, vm_prot_t prot) +{ + mach_port_t memobj; + mutex_lock (&display->lock); + memobj = user_pager_get_filemap (&display->user_pager, prot); + mutex_unlock (&display->lock); + return memobj; +} diff --git a/console/pager.c b/console/pager.c new file mode 100644 index 00000000..092a8820 --- /dev/null +++ b/console/pager.c @@ -0,0 +1,221 @@ +/* pager.c - The pager for the display component of a virtual console. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <errno.h> +#include <assert.h> +#include <error.h> + +#include <sys/mman.h> +#include <cthreads.h> + +#include <hurd.h> +#include <hurd/pager.h> +#include <hurd/console.h> + +#include "pager.h" + + +struct user_pager_info +{ + size_t memobj_npages; + vm_address_t memobj_pages[0]; +}; + + +/* We need a separate bucket for the pager ports. */ +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) +{ + 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); +} + + +error_t +pager_read_page (struct user_pager_info *upi, vm_offset_t page, + vm_address_t *buf, int *writelock) +{ + /* 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; +} + + +error_t +pager_write_page (struct user_pager_info *upi, vm_offset_t page, + vm_address_t buf) +{ + assert (upi->memobj_pages[page / vm_page_size] == (vm_address_t) NULL); + upi->memobj_pages[page / vm_page_size] = buf; + return 0; +} + + +error_t +pager_unlock_page (struct user_pager_info *pager, + vm_offset_t address) +{ + assert (!"unlocking requested on unlocked page"); + return 0; +} + + +/* Tell how big the file is. */ +error_t +pager_report_extent (struct user_pager_info *upi, + vm_address_t *offset, + vm_size_t *size) +{ + *offset = 0; + *size = upi->memobj_npages * vm_page_size; + return 0; +} + + +void +pager_dropweak (struct user_pager_info *upi) +{ +} + + +/* A top-level function for the paging thread that just services paging + requests. */ +static void +service_paging_requests (any_t arg) +{ + struct port_bucket *pager_bucket = arg; + for (;;) + ports_manage_port_operations_multithread (pager_bucket, + pager_demuxer, + 1000 * 60 * 2, + 1000 * 60 * 10, 0); +} + + +/* Initialize the pager for the display component. */ +void +user_pager_init (void) +{ + /* Create the pager bucket, and start to serve paging requests. */ + pager_bucket = ports_create_bucket (); + if (! pager_bucket) + error (5, errno, "Cannot create pager bucket"); + + /* Make a thread to service paging requests. */ + cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests, + (any_t) pager_bucket)); +} + + +/* Create a new pager in USER_PAGER with NPAGES pages, and return a + mapping to the memory in *USER. */ +error_t +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; + + upi->memobj_npages = npages; + + /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */ + user_pager->pager = pager_create (upi, pager_bucket, + 1, MEMORY_OBJECT_COPY_DELAY); + if (!user_pager->pager) + { + free (upi); + return errno; + } + user_pager->memobj = pager_get_port (user_pager->pager); + ports_port_deref (user_pager->pager); + + mach_port_insert_right (mach_task_self (), user_pager->memobj, + user_pager->memobj, MACH_MSG_TYPE_MAKE_SEND); + + err = vm_map (mach_task_self (), + (vm_address_t *) user, + (vm_size_t) npages * vm_page_size, + (vm_address_t) 0, + 1 /* ! (flags & MAP_FIXED) */, + user_pager->memobj, 0 /* (vm_offset_t) offset */, + 0 /* ! (flags & MAP_SHARED) */, + VM_PROT_READ | VM_PROT_WRITE, + VM_PROT_READ | VM_PROT_WRITE, + VM_INHERIT_NONE); + if (err) + { + /* UPI will be cleaned up by libpager. */ + mach_port_deallocate (mach_task_self (), user_pager->memobj); + return err; + } + + return 0; +} + + +/* Destroy the pager USER_PAGER and the mapping at USER. */ +void +user_pager_destroy (struct user_pager *user_pager, struct cons_display *user) +{ + /* The pager will be deallocated by libpager. */ + vm_deallocate (mach_task_self (), (vm_offset_t) user, + pager_get_upi (user_pager->pager)->memobj_npages + * vm_page_size); + mach_port_deallocate (mach_task_self (), user_pager->memobj); +} + + +/* Allocate a reference for the memory object backing the pager + USER_PAGER with protection PROT and return it. */ +mach_port_t +user_pager_get_filemap (struct user_pager *user_pager, vm_prot_t prot) +{ + error_t err; + + /* Add a reference for each call, the caller will deallocate it. */ + err = mach_port_mod_refs (mach_task_self (), user_pager->memobj, + MACH_PORT_RIGHT_SEND, +1); + assert_perror (err); + + return user_pager->memobj; +} + diff --git a/console/pager.h b/console/pager.h new file mode 100644 index 00000000..974db961 --- /dev/null +++ b/console/pager.h @@ -0,0 +1,47 @@ +/* pager.h - Interface to the pager for display component of a virtual console. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#ifndef PAGER_H +#define PAGER_H + +struct user_pager +{ + struct pager *pager; + memory_object_t memobj; +}; + +/* Initialize the pager for the display component. */ +void user_pager_init (void); + +/* Create a new pager in USER_PAGER with NPAGES pages, and return a + mapping to the memory in *USER. */ +error_t user_pager_create (struct user_pager *user_pager, unsigned int npages, + struct cons_display **user); + +/* Destroy the pager USER_PAGER and the mapping at USER. */ +void user_pager_destroy (struct user_pager *user_pager, + struct cons_display *user); + +/* Allocate a reference for the memory object backing the pager + USER_PAGER with protection PROT and return it. */ +mach_port_t user_pager_get_filemap (struct user_pager *user_pager, + vm_prot_t prot); + +#endif /* PAGER_H_ */ |