diff options
Diffstat (limited to 'libdiskfs/=exc.c')
-rw-r--r-- | libdiskfs/=exc.c | 141 |
1 files changed, 0 insertions, 141 deletions
diff --git a/libdiskfs/=exc.c b/libdiskfs/=exc.c deleted file mode 100644 index ced9c5b9..00000000 --- a/libdiskfs/=exc.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - Copyright (C) 1994, 1995 Free Software Foundation - - This program 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. - - This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "priv.h" - -/* List of preempters that are around. */ -struct preempt_record -{ - struct preempt_record *next; - struct hurd_signal_preempt preempter1, preempter2; - struct pager *p; - vm_address_t off; - void *addr; - long len; -}; - -static struct preempt_record *preempt_list; -static spin_lock_t preempt_list_lock = SPIN_LOCK_INITIALIZER; - -/* This special signal handler is run anytime we have taken a fault on - a page that we map (registered through - diskfs_register_memory_fault_area). What we do is just longjmp to the - context saved on the stack by diskfs_catch_exception. */ -static void -special_segv_handler (int code, int subcode, int error) -{ - struct preempt_record *rec; - struct thread_stuff *stack_record; - - /* SUBCODE is the address and ERROR is the error returned by the - pager through the kernel. But because there is an annoying - kernel bug (or rather unimplemented feature) the errors are not - actually passed back. So we have to scan the list of preempt - records and find the one that got us here, and then query the - pager to find out what error it gave the kernel. */ - spin_lock (&preempt_list_lock); - for (rec = preempt_list; rec; rec = rec->next) - if ((void *)subcode >= rec->addr - && (void *)subcode < rec->addr + rec->len) - break; - assert (rec); - spin_unlock (&preempt_list_lock); - error = pager_get_error (rec->p, rec->off + (void *)subcode - rec->addr); - - /* Now look up the stack record left by diskfs_catch_exception, consuming it - on the way */ - stack_record = (struct thread_stuff *) cthread_data (cthread_self ()); - assert (stack_record); - cthread_set_data (cthread_self (), (any_t)stack_record->link); - - /* And return to it... */ - longjmp (&stack_record->buf, error); - - abort (); -} - -/* Return a signal handler for a thread which has faulted inside a - region registered as expecting such faults. This routine runs - inside the library's signal thread, and accordingly must be - careful. */ -static sighandler_t -segv_preempter (thread_t thread, int signo, - long int sigcode, int sigerror) -{ - /* Just assume that everything is cool (how could it not be?) - and return our special handler above. */ - return special_segv_handler; -} - -/* Mark the memory at ADDR continuing for LEN bytes as mapped from pager P - at offset OFF. Call when vm_map-ing part of the disk. */ -void -diskfs_register_memory_fault_area (struct pager *p, - vm_address_t off, - void *addr, - long len) -{ - struct preempt_record *rec = malloc (sizeof (struct preempt_record)); - - hurd_preempt_signals (&rec->preempter1, SIGSEGV, addr, addr + len, - segv_preempter); - hurd_preempt_signals (&rec->preempter2, SIGBUS, addr, addr + len, - segv_preempter); - rec->p = p; - rec->off = off; - rec->addr = addr; - rec->len = len; - - spin_lock (&preempt_list_lock); - rec->next = preempt_list; - preempt_list = rec; - spin_unlock (&preempt_list_lock); -} - -/* Mark the memory at ADDR continuing for LEN bytes as no longer - mapped from the disk. Call when vm_unmap-ing part of the disk. */ -void -diskfs_unregister_memory_fault_area (void *addr, - long len) -{ - struct preempt_record *rec, **prevp; - - spin_lock (&preempt_list_lock); - for (rec = preempt_list, prevp = &preempt_list; - rec; - rec = rec->next, prevp = &rec->next) - if (rec->addr == addr && rec->len == len) - { - /* This is it, make it go away. */ - *prevp = rec->next; - spin_unlock (&preempt_list_lock); - hurd_unpreempt_signals (&rec->preempter1, SIGSEGV); - hurd_unpreempt_signals (&rec->preempter2, SIGBUS); - free (rec); - return; - } - spin_unlock (&preempt_list_lock); - - /* Not found */ - assert (0); -} - -/* Set up the exception handling system. */ -void -init_exceptions () -{ -} |