1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "@(#)dt_buf.c 1.2 05/06/08 SMI" 28 29/* 30 * DTrace Memory Buffer Routines 31 * 32 * The routines in this file are used to create an automatically resizing 33 * memory buffer that can be written to like a file. Memory buffers are 34 * used to construct DOF to ioctl() to dtrace(7D), and provide semantics that 35 * simplify caller code. Specifically, any allocation errors result in an 36 * error code being set inside the buffer which is maintained persistently and 37 * propagates to another buffer if the buffer in error is concatenated. These 38 * semantics permit callers to execute a large series of writes without needing 39 * to check for errors and then perform a single check before using the buffer. 40 */ 41 42#include <strings.h> 43 44#include <dt_impl.h> 45#include <dt_buf.h> 46 47void 48dt_buf_create(dtrace_hdl_t *dtp, dt_buf_t *bp, const char *name, size_t len) 49{ 50 if (len == 0) 51 len = _dtrace_bufsize; 52 53 bp->dbu_buf = bp->dbu_ptr = dt_zalloc(dtp, len); 54 bp->dbu_len = len; 55 56 if (bp->dbu_buf == NULL) 57 bp->dbu_err = dtrace_errno(dtp); 58 else 59 bp->dbu_err = 0; 60 61 bp->dbu_resizes = 0; 62 bp->dbu_name = name; 63} 64 65void 66dt_buf_destroy(dtrace_hdl_t *dtp, dt_buf_t *bp) 67{ 68 dt_dprintf("dt_buf_destroy(%s): size=%lu resizes=%u\n", 69 bp->dbu_name, (ulong_t)bp->dbu_len, bp->dbu_resizes); 70 71 dt_free(dtp, bp->dbu_buf); 72} 73 74void 75dt_buf_reset(dtrace_hdl_t *dtp, dt_buf_t *bp) 76{ 77 if ((bp->dbu_ptr = bp->dbu_buf) != NULL) 78 bp->dbu_err = 0; 79 else 80 dt_buf_create(dtp, bp, bp->dbu_name, bp->dbu_len); 81} 82 83void 84dt_buf_write(dtrace_hdl_t *dtp, dt_buf_t *bp, 85 const void *buf, size_t len, size_t align) 86{ 87 size_t off = (size_t)(bp->dbu_ptr - bp->dbu_buf); 88 size_t adj = roundup(off, align) - off; 89 90 if (bp->dbu_err != 0) { 91 (void) dt_set_errno(dtp, bp->dbu_err); 92 return; /* write silently fails */ 93 } 94 95 if (bp->dbu_ptr + adj + len > bp->dbu_buf + bp->dbu_len) { 96 size_t new_len = bp->dbu_len * 2; 97 uchar_t *new_buf; 98 uint_t r = 1; 99 100 while (bp->dbu_ptr + adj + len > bp->dbu_buf + new_len) { 101 new_len *= 2; 102 r++; 103 } 104 105 if ((new_buf = dt_zalloc(dtp, new_len)) == NULL) { 106 bp->dbu_err = dtrace_errno(dtp); 107 return; 108 } 109 110 bcopy(bp->dbu_buf, new_buf, off); 111 dt_free(dtp, bp->dbu_buf); 112 113 bp->dbu_buf = new_buf; 114 bp->dbu_ptr = new_buf + off; 115 bp->dbu_len = new_len; 116 bp->dbu_resizes += r; 117 } 118 119 bp->dbu_ptr += adj; 120 bcopy(buf, bp->dbu_ptr, len); 121 bp->dbu_ptr += len; 122} 123 124void 125dt_buf_concat(dtrace_hdl_t *dtp, dt_buf_t *dst, 126 const dt_buf_t *src, size_t align) 127{ 128 if (dst->dbu_err == 0 && src->dbu_err != 0) { 129 (void) dt_set_errno(dtp, src->dbu_err); 130 dst->dbu_err = src->dbu_err; 131 } else { 132 dt_buf_write(dtp, dst, src->dbu_buf, 133 (size_t)(src->dbu_ptr - src->dbu_buf), align); 134 } 135} 136 137size_t 138dt_buf_offset(const dt_buf_t *bp, size_t align) 139{ 140 size_t off = (size_t)(bp->dbu_ptr - bp->dbu_buf); 141 return (roundup(off, align)); 142} 143 144size_t 145dt_buf_len(const dt_buf_t *bp) 146{ 147 return (bp->dbu_ptr - bp->dbu_buf); 148} 149 150int 151dt_buf_error(const dt_buf_t *bp) 152{ 153 return (bp->dbu_err); 154} 155 156void * 157dt_buf_ptr(const dt_buf_t *bp) 158{ 159 return (bp->dbu_buf); 160} 161 162void * 163dt_buf_claim(dtrace_hdl_t *dtp, dt_buf_t *bp) 164{ 165 void *buf = bp->dbu_buf; 166 167 if (bp->dbu_err != 0) { 168 dt_free(dtp, buf); 169 buf = NULL; 170 } 171 172 bp->dbu_buf = bp->dbu_ptr = NULL; 173 bp->dbu_len = 0; 174 175 return (buf); 176} 177