/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1985-2001 by Sun Microsystems, Inc. * All rights reserved. */ /* * Vuid_store.c - Implement the vuid_store.h event storage interface. */ #include #include #include #include #include #include #include #include static void vuid_destroy_seg(); static Vuid_seg * vuid_copy_seg(); static Vuid_seg * vuid_find_seg(); static Vuid_value * vuid_add_value(); static Vuid_value * vuid_find_value(); #ifdef _KERNEL #define vuid_alloc(bytes) \ kmem_alloc((bytes), servicing_interrupt()) #define vuid_free(ptr, bytes) kmem_free((ptr), (bytes)) #else #define vuid_alloc(bytes) malloc((bytes)) #define vuid_free(ptr, bytes) free((ptr)) #endif /* _KERNEL */ void vuid_set_value(client_state_ptr, event) Vuid_state *client_state_ptr; register Firm_event *event; { Vuid_seg **state_ptr = (Vuid_seg **)client_state_ptr; Vuid_seg *state = *state_ptr; register Vuid_seg *seg; register Vuid_value *val_node; register Vuid_value *pair_val_node; register ushort_t offset = vuid_id_offset(event->id); register ushort_t pair = event->pair; int int_bit, val_original; /* Get (search for) seg from state assoicated with event */ if ((seg = vuid_find_seg(state, vuid_id_addr(event->id))) == VUID_SEG_NULL) { /* Allocate and initialize new seg for event */ seg = (Vuid_seg *) vuid_alloc(sizeof (*seg)); bzero((caddr_t)seg, sizeof (*seg)); seg->addr = vuid_id_addr(event->id); /* Add the seg to state */ *state_ptr = seg; seg->next = state; } int_bit = vuid_get_int_bit(seg, offset); /* See if no value node and event value is not boolean */ if ((!int_bit) && vuid_int_value(event->value)) { (void) vuid_add_value(seg, offset); int_bit = 1; } /* If boolean event then set boolean bit */ if (!int_bit) { if (event->value) vuid_set_boolean_bit(seg, offset); else vuid_clear_boolean_bit(seg, offset); } else { /* Get (search for) value node (should be there) */ val_node = vuid_find_value(seg, offset); val_original = val_node->value; val_node->value = event->value; switch (event->pair_type) { case FE_PAIR_DELTA: /* See if value node for pair */ if (!vuid_get_int_bit(seg, pair)) (void) vuid_add_value(seg, pair); /* Get (search for) value node (should be there) */ pair_val_node = vuid_find_value(seg, pair); /* Set pair value to difference */ pair_val_node->value = event->value - val_original; break; case FE_PAIR_ABSOLUTE: /* See if value node for pair */ if (!vuid_get_int_bit(seg, pair)) (void) vuid_add_value(seg, pair); /* Get (search for) value node (should be there) */ pair_val_node = vuid_find_value(seg, pair); /* Add event value to pair value */ pair_val_node->value += event->value; break; default: {} } } /* Recursively call vuid_set_value if there is an associated pair */ if (event->pair_type == FE_PAIR_SET) { Firm_event pair_event; pair_event = *event; pair_event.id = vuid_id_addr(event->id) | pair; pair_event.pair_type = FE_PAIR_NONE; pair_event.pair = 0; vuid_set_value(client_state_ptr, &pair_event); } } int vuid_get_value(client_state, id) Vuid_state client_state; ushort_t id; { Vuid_seg *state = vuid_cstate_to_state(client_state); register Vuid_seg *seg; Vuid_value *val_node; register ushort_t offset = vuid_id_offset(id); /* Get (search for) seg from state assoicated with id */ if ((seg = vuid_find_seg(state, vuid_id_addr(id))) == VUID_SEG_NULL) return (0); /* If boolean event (i.e., no ints bit on) then return boolean value */ if (!vuid_get_int_bit(seg, offset)) return (vuid_get_boolean_bit(seg, offset) != 0); else { /* Get (search for) value node and return value */ val_node = vuid_find_value(seg, offset); return (val_node->value); } } void vuid_destroy_state(client_state) Vuid_state client_state; { Vuid_seg *state = vuid_cstate_to_state(client_state); register Vuid_seg *seg; Vuid_seg *seg_next; for (seg = state; seg; seg = seg_next) { seg_next = seg->next; vuid_destroy_seg(seg); } } static void vuid_destroy_seg(seg) Vuid_seg *seg; { register Vuid_value *val_node; Vuid_value *val_node_next; for (val_node = seg->list; val_node; val_node = val_node_next) { val_node_next = val_node->next; vuid_free((caddr_t)val_node, sizeof (Vuid_value)); } vuid_free((caddr_t)seg, sizeof (Vuid_seg)); } Vuid_state vuid_copy_state(client_state) Vuid_state client_state; { Vuid_seg *state = vuid_cstate_to_state(client_state); register Vuid_seg *seg; Vuid_seg *new_first_seg = VUID_SEG_NULL; register Vuid_seg *new_previous_seg = VUID_SEG_NULL; register Vuid_seg *new_seg; for (seg = state; seg; seg = seg->next) { new_seg = vuid_copy_seg(seg); /* Remember first seg as state */ if (new_first_seg == VUID_SEG_NULL) new_first_seg = new_seg; /* Link segs together */ if (new_previous_seg != VUID_SEG_NULL) new_previous_seg->next = new_seg; /* Remember seg for linking later */ new_previous_seg = new_seg; } return ((Vuid_state) new_first_seg); } static Vuid_seg * vuid_copy_seg(seg) Vuid_seg *seg; { register Vuid_value *val_node; Vuid_seg *new_seg; register Vuid_value *new_previous_val = VUID_VALUE_NULL; register Vuid_value *new_val; /* Allocate and initialize new seg for event */ new_seg = (Vuid_seg *) vuid_alloc(sizeof (*seg)); *new_seg = *seg; /* Terminate new pointer with null */ new_seg->next = VUID_SEG_NULL; new_seg->list = VUID_VALUE_NULL; /* Copy list elements */ for (val_node = seg->list; val_node; val_node = val_node->next) { new_val = (Vuid_value *) vuid_alloc(sizeof (*new_val)); *new_val = *val_node; new_val->next = VUID_VALUE_NULL; /* Remember first value as head of list */ if (new_seg->list == VUID_VALUE_NULL) new_seg->list = new_val; /* Link vals together */ if (new_previous_val != VUID_VALUE_NULL) new_previous_val->next = new_val; /* Remember val for linking later */ new_previous_val = new_val; } return (new_seg); } static Vuid_seg * vuid_find_seg(state, addr) Vuid_seg *state; ushort_t addr; { register Vuid_seg *seg; for (seg = state; seg; seg = seg->next) { if (seg->addr == addr) return (seg); } return (VUID_SEG_NULL); } static Vuid_value * vuid_find_value(seg, offset) Vuid_seg *seg; ushort_t offset; { register Vuid_value *val_node; for (val_node = seg->list; val_node; val_node = val_node->next) { if (vuid_id_offset(val_node->offset) == offset) return (val_node); } return (VUID_VALUE_NULL); } static Vuid_value * vuid_add_value(seg, offset) Vuid_seg *seg; ushort_t offset; { Vuid_value *list_tmp; Vuid_value *val_node; /* Allocate and initialize new value node for event */ val_node = (Vuid_value *) vuid_alloc(sizeof (*val_node)); bzero((caddr_t)val_node, sizeof (*val_node)); val_node->offset = offset; /* Add the value node to list */ list_tmp = seg->list; seg->list = val_node; val_node->next = list_tmp; vuid_set_int_bit(seg, offset); /* Clear boolean bit for event */ vuid_clear_boolean_bit(seg, offset); return (val_node); }