summaryrefslogtreecommitdiff
path: root/libsigsegv/src/dispatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsigsegv/src/dispatcher.c')
-rw-r--r--libsigsegv/src/dispatcher.c255
1 files changed, 0 insertions, 255 deletions
diff --git a/libsigsegv/src/dispatcher.c b/libsigsegv/src/dispatcher.c
deleted file mode 100644
index 2619e65d..00000000
--- a/libsigsegv/src/dispatcher.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* Dispatch signal to right virtual memory area.
- Copyright (C) 1993-1999, 2002-2003 Bruno Haible <bruno@clisp.org>
-
- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-
-#include "sigsegv.h"
-
-#include <stddef.h> /* needed for NULL on SunOS4 */
-#include <stdlib.h>
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-
-/*
- * A dispatcher contains an AVL tree of non-empty intervals, sorted according
- * to their starting address.
- */
-typedef
-struct node_t
-{
- /* AVL tree management. */
- struct node_t *left;
- struct node_t *right;
- unsigned int height;
- /* Representation of interval. */
- unsigned long address;
- unsigned long len;
- /* User handler. */
- sigsegv_area_handler_t handler;
- void *handler_arg;
-}
-node_t;
-
-#define empty ((node_t *) 0)
-#define heightof(tree) ((tree) == empty ? 0 : (tree)->height)
-#define MAXHEIGHT 41
-
-static void
-rebalance (node_t ***nodeplaces_ptr, unsigned int count)
-{
- if (count > 0)
- do
- {
- node_t **nodeplace = *--nodeplaces_ptr;
- node_t *node = *nodeplace;
- node_t *nodeleft = node->left;
- node_t *noderight = node->right;
- unsigned int heightleft = heightof (nodeleft);
- unsigned int heightright = heightof (noderight);
- if (heightright + 1 < heightleft)
- {
- node_t *nodeleftleft = nodeleft->left;
- node_t *nodeleftright = nodeleft->right;
- unsigned int heightleftright = heightof (nodeleftright);
- if (heightof (nodeleftleft) >= heightleftright)
- {
- node->left = nodeleftright; nodeleft->right = node;
- nodeleft->height = 1 + (node->height = 1 + heightleftright);
- *nodeplace = nodeleft;
- }
- else
- {
- nodeleft->right = nodeleftright->left;
- node->left = nodeleftright->right;
- nodeleftright->left = nodeleft;
- nodeleftright->right = node;
- nodeleft->height = node->height = heightleftright;
- nodeleftright->height = heightleft;
- *nodeplace = nodeleftright;
- }
- }
- else if (heightleft + 1 < heightright)
- {
- node_t *noderightright = noderight->right;
- node_t *noderightleft = noderight->left;
- unsigned int heightrightleft = heightof (noderightleft);
- if (heightof (noderightright) >= heightrightleft)
- {
- node->right = noderightleft; noderight->left = node;
- noderight->height = 1 + (node->height = 1 + heightrightleft);
- *nodeplace = noderight;
- }
- else
- {
- noderight->left = noderightleft->right;
- node->right = noderightleft->left;
- noderightleft->right = noderight;
- noderightleft->left = node;
- noderight->height = node->height = heightrightleft;
- noderightleft->height = heightright;
- *nodeplace = noderightleft;
- }
- }
- else
- {
- unsigned int height =
- (heightleft<heightright ? heightright : heightleft) + 1;
- if (height == node->height)
- break;
- node->height = height;
- }
- }
- while (--count > 0);
-}
-
-static node_t *
-insert (node_t *new_node, node_t *tree)
-{
- unsigned long key = new_node->address;
- node_t **nodeplace = &tree;
- node_t **stack[MAXHEIGHT];
- unsigned int stack_count = 0;
- node_t ***stack_ptr = &stack[0];
- for (;;)
- {
- node_t *node = *nodeplace;
- if (node == empty)
- break;
- *stack_ptr++ = nodeplace; stack_count++;
- if (key < node->address)
- nodeplace = &node->left;
- else
- nodeplace = &node->right;
- }
- new_node->left = empty;
- new_node->right = empty;
- new_node->height = 1;
- *nodeplace = new_node;
- rebalance (stack_ptr, stack_count);
- return tree;
-}
-
-static node_t *
-delete (node_t *node_to_delete, node_t *tree)
-{
- unsigned long key = node_to_delete->address;
- node_t **nodeplace = &tree;
- node_t **stack[MAXHEIGHT];
- unsigned int stack_count = 0;
- node_t ***stack_ptr = &stack[0];
- for (;;)
- {
- node_t *node = *nodeplace;
- if (node == empty)
- return tree;
- *stack_ptr++ = nodeplace; stack_count++;
- if (key == node->address)
- {
- if (node != node_to_delete)
- abort ();
- break;
- }
- if (key < node->address)
- nodeplace = &node->left;
- else
- nodeplace = &node->right;
- }
- {
- node_t **nodeplace_to_delete = nodeplace;
- if (node_to_delete->left == empty)
- {
- *nodeplace_to_delete = node_to_delete->right;
- stack_ptr--; stack_count--;
- }
- else
- {
- node_t ***stack_ptr_to_delete = stack_ptr;
- node_t **nodeplace = &node_to_delete->left;
- node_t *node;
- for (;;)
- {
- node = *nodeplace;
- if (node->right == empty)
- break;
- *stack_ptr++ = nodeplace; stack_count++;
- nodeplace = &node->right;
- }
- *nodeplace = node->left;
- node->left = node_to_delete->left;
- node->right = node_to_delete->right;
- node->height = node_to_delete->height;
- *nodeplace_to_delete = node;
- *stack_ptr_to_delete = &node->left;
- }
- }
- rebalance (stack_ptr, stack_count);
- return tree;
-}
-
-void
-sigsegv_init (sigsegv_dispatcher *dispatcher)
-{
- dispatcher->tree = empty;
-}
-
-void *
-sigsegv_register (sigsegv_dispatcher *dispatcher,
- void *address, unsigned long len,
- sigsegv_area_handler_t handler, void *handler_arg)
-{
- if (len == 0)
- return NULL;
- else
- {
- node_t *new_node = (node_t *) malloc (sizeof (node_t));
- new_node->address = (unsigned long) address;
- new_node->len = len;
- new_node->handler = handler;
- new_node->handler_arg = handler_arg;
- dispatcher->tree = insert (new_node, (node_t *) dispatcher->tree);
- return new_node;
- }
-}
-
-void
-sigsegv_unregister (sigsegv_dispatcher *dispatcher, void *ticket)
-{
- if (ticket != NULL)
- {
- node_t *node_to_delete = (node_t *) ticket;
- dispatcher->tree = delete (node_to_delete, (node_t *) dispatcher->tree);
- free (node_to_delete);
- }
-}
-
-int
-sigsegv_dispatch (sigsegv_dispatcher *dispatcher, void *fault_address)
-{
- unsigned long key = (unsigned long) fault_address;
- node_t *tree = (node_t *) dispatcher->tree;
- for (;;)
- {
- if (tree == empty)
- return 0;
- if (key < tree->address)
- tree = tree->left;
- else if (key - tree->address >= tree->len)
- tree = tree->right;
- else
- break;
- }
- return (*tree->handler) (fault_address, tree->handler_arg);
-}