File: dt_buf.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (153 lines) | stat: -rw-r--r-- 3,382 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * Oracle Linux DTrace.
 * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

/*
 * DTrace Memory Buffer Routines
 *
 * The routines in this file are used to create an automatically resizing
 * memory buffer that can be written to like a file.  Memory buffers are
 * used to construct DOF to ioctl() to dtrace(7D), and provide semantics that
 * simplify caller code.  Specifically, any allocation errors result in an
 * error code being set inside the buffer which is maintained persistently and
 * propagates to another buffer if the buffer in error is concatenated.  These
 * semantics permit callers to execute a large series of writes without needing
 * to check for errors and then perform a single check before using the buffer.
 */

#include <dt_impl.h>
#include <dt_buf.h>

void
dt_buf_create(dtrace_hdl_t *dtp, dt_buf_t *bp, const char *name, size_t len)
{
	if (len == 0)
		len = _dtrace_bufsize;

	bp->dbu_buf = bp->dbu_ptr = dt_zalloc(dtp, len);
	bp->dbu_len = len;

	if (bp->dbu_buf == NULL)
		bp->dbu_err = dtrace_errno(dtp);
	else
		bp->dbu_err = 0;

	bp->dbu_resizes = 0;
	bp->dbu_name = name;
}

void
dt_buf_destroy(dtrace_hdl_t *dtp, dt_buf_t *bp)
{
	dt_dprintf("dt_buf_destroy(%s): size=%lu resizes=%u\n",
	    bp->dbu_name, (ulong_t)bp->dbu_len, bp->dbu_resizes);

	dt_free(dtp, bp->dbu_buf);
}

void
dt_buf_reset(dtrace_hdl_t *dtp, dt_buf_t *bp)
{
	if ((bp->dbu_ptr = bp->dbu_buf) != NULL)
		bp->dbu_err = 0;
	else
		dt_buf_create(dtp, bp, bp->dbu_name, bp->dbu_len);
}

void
dt_buf_write(dtrace_hdl_t *dtp, dt_buf_t *bp,
    const void *buf, size_t len, size_t align)
{
	size_t off = (size_t)(bp->dbu_ptr - bp->dbu_buf);
	size_t adj = roundup(off, align) - off;

	if (bp->dbu_err != 0) {
		dt_set_errno(dtp, bp->dbu_err);
		return; /* write silently fails */
	}

	if (bp->dbu_ptr + adj + len > bp->dbu_buf + bp->dbu_len) {
		size_t new_len = bp->dbu_len * 2;
		uchar_t *new_buf;
		uint_t r = 1;

		while (bp->dbu_ptr + adj + len > bp->dbu_buf + new_len) {
			new_len *= 2;
			r++;
		}

		if ((new_buf = dt_zalloc(dtp, new_len)) == NULL) {
			bp->dbu_err = dtrace_errno(dtp);
			return;
		}

		memcpy(new_buf, bp->dbu_buf, off);
		dt_free(dtp, bp->dbu_buf);

		bp->dbu_buf = new_buf;
		bp->dbu_ptr = new_buf + off;
		bp->dbu_len = new_len;
		bp->dbu_resizes += r;
	}

	bp->dbu_ptr += adj;
	memcpy(bp->dbu_ptr, buf, len);
	bp->dbu_ptr += len;
}

void
dt_buf_concat(dtrace_hdl_t *dtp, dt_buf_t *dst,
    const dt_buf_t *src, size_t align)
{
	if (dst->dbu_err == 0 && src->dbu_err != 0) {
		dt_set_errno(dtp, src->dbu_err);
		dst->dbu_err = src->dbu_err;
	} else {
		dt_buf_write(dtp, dst, src->dbu_buf,
		    (size_t)(src->dbu_ptr - src->dbu_buf), align);
	}
}

size_t
dt_buf_offset(const dt_buf_t *bp, size_t align)
{
	size_t off = (size_t)(bp->dbu_ptr - bp->dbu_buf);
	return roundup(off, align);
}

size_t
dt_buf_len(const dt_buf_t *bp)
{
	return bp->dbu_ptr - bp->dbu_buf;
}

int
dt_buf_error(const dt_buf_t *bp)
{
	return bp->dbu_err;
}

void *
dt_buf_ptr(const dt_buf_t *bp)
{
	return bp->dbu_buf;
}

void *
dt_buf_claim(dtrace_hdl_t *dtp, dt_buf_t *bp)
{
	void *buf = bp->dbu_buf;

	if (bp->dbu_err != 0) {
		dt_free(dtp, buf);
		buf = NULL;
	}

	bp->dbu_buf = bp->dbu_ptr = NULL;
	bp->dbu_len = 0;

	return buf;
}