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
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.
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]
23 * Copyright (c) 1994,1997-1998 by Sun Microsystems, Inc.
24 * All rights reserved.
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/tnf_com.h>
33 #include <sys/machlock.h>
40 * Size of a TNF buffer block
43 #define TNF_BLOCK_SIZE 512
44 #define TNF_BLOCK_SHIFT 9
45 #define TNF_BLOCK_MASK ~(TNF_BLOCK_SIZE - 1)
48 * Size of the file header and forwarding pointer (directory) area combined.
49 * Tag and data blocks start this many bytes into the file.
50 * The maximum size of this area is 64KB.
53 #define TNF_DIRECTORY_SIZE (4 * 1024)
54 #define TNFW_B_FW_ZONE TNF_DIRECTORY_SIZE
57 * Reserved space for tag blocks, after directory area.
60 #define TNFW_B_TAG_RESERVE (28 * 1024)
62 #define TNFW_B_DATA_BLOCK_BEGIN (TNFW_B_FW_ZONE + TNFW_B_TAG_RESERVE)
65 * Reserved directory entries, and their precomputed tags. These are byte
66 * offsets from start of file.
69 #define TNF_DIRENT_FILE_HEADER (TNF_BLOCK_SIZE + 0)
70 #define TNF_DIRENT_BLOCK_HEADER (TNF_BLOCK_SIZE + 4)
71 #define TNF_DIRENT_ROOT (TNF_BLOCK_SIZE + 8)
72 #define TNF_DIRENT_LAST TNF_DIRENT_ROOT
74 #define TNF_FILE_HEADER_TAG \
75 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_FILE_HEADER) | TNF_REF32_T_TAG)
77 #define TNF_BLOCK_HEADER_TAG \
78 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_BLOCK_HEADER) | TNF_REF32_T_TAG)
80 #define TNF_ROOT_TAG \
81 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_ROOT) | TNF_REF32_T_TAG)
84 * Allocation type: permanent or reusable
88 TNF_ALLOC_REUSABLE
= 0,
103 * The STOPPED bit may be or-ed into the state field.
105 #define TNFW_B_STOPPED 16
106 #define TNFW_B_SET_STOPPED(state) ((state) |= TNFW_B_STOPPED)
107 #define TNFW_B_UNSET_STOPPED(state) ((state) &= ~TNFW_B_STOPPED)
108 #define TNFW_B_IS_STOPPED(state) ((state) & TNFW_B_STOPPED)
111 * Layout of the first block of TNF file (file header)
115 tnf_uint32_t magic
; /* magic number */
116 tnf_file_header_t com
; /* common header */
118 volatile ulong_t gen
; /* generation */
119 volatile ulong_t block
[2]; /* block number */
121 ulong_t next_tag_alloc
; /* block counter */
122 ulong_t next_fw_alloc
; /* byte offset */
123 lock_t lock
; /* protects hint updates */
124 /* Padding to end of block */
125 } tnf_buf_file_header_t
;
128 * Per-thread write-control information
131 typedef struct tnfw_b_pos
{
132 tnf_block_header_t
*tnfw_w_block
;
133 ushort_t tnfw_w_write_off
;
134 uchar_t tnfw_w_dirty
;
137 typedef struct tnfw_b_wcb
{
138 struct tnfw_b_pos tnfw_w_pos
;
139 struct tnfw_b_pos tnfw_w_tag_pos
;
143 * Global tracing state
146 extern TNFW_B_STATE tnfw_b_state
;
149 * Global trace buffer
152 extern caddr_t tnf_buf
;
154 #define TNF_FILE_HEADER() ((tnf_buf_file_header_t *)tnf_buf)
161 * Allocate 'size' data bytes using 'wcb'; store result into 'buf'.
162 * This inlines the common trace case.
164 #define TNFW_B_ALLOC(wcb, size, buf, typ) \
166 TNFW_B_POS *xx_pos; \
167 ushort_t xx_off, xx_nof; \
168 tnf_block_header_t *xx_blk; \
171 /* Round size up to a multiple of 8. */ \
172 xx_size = (size + 7) & ~7; \
173 xx_pos = &(wcb)->tnfw_w_pos; \
174 xx_blk = xx_pos->tnfw_w_block; \
175 xx_off = xx_pos->tnfw_w_write_off; \
176 xx_nof = xx_off + xx_size; \
177 if (xx_blk != NULL && xx_nof <= TNF_BLOCK_SIZE) { \
178 buf = (typ)((char *)xx_blk + xx_off); \
179 xx_pos->tnfw_w_write_off = xx_nof; \
181 *((int *)((char *)buf + xx_size - sizeof (int))) = 0; \
183 buf = tnfw_b_alloc((wcb), xx_size, TNF_ALLOC_REUSABLE);\
187 * Giveback words after new_pos.
189 #define TNFW_B_GIVEBACK(wcb, new_pos) \
190 ((wcb)->tnfw_w_pos.tnfw_w_write_off = \
191 (((char *)(new_pos) \
192 - (char *)((wcb)->tnfw_w_pos.tnfw_w_block) + 7) \
193 & ~7), *(int *)(new_pos) = 0)
196 * Commit transaction bytes allocated via 'pos'
198 #define TNFW_B_COMMIT(pos) \
200 tnf_block_header_t *xx_blk, *xx_nxt; \
202 xx_blk = (pos)->tnfw_w_block; \
203 if (xx_blk != NULL) { \
204 xx_blk->bytes_valid = (pos)->tnfw_w_write_off; \
205 if ((pos)->tnfw_w_dirty) { \
206 xx_nxt = xx_blk->next_block; \
207 while (xx_nxt != NULL) { \
208 xx_blk->next_block = NULL; \
210 xx_nxt = xx_blk->next_block; \
211 xx_blk->bytes_valid = TNF_BLOCK_SIZE;\
212 lock_clear(&xx_blk->A_lock); \
214 (pos)->tnfw_w_dirty = 0; \
220 * Rollback transaction bytes allocated via 'pos'
222 #define TNFW_B_ROLLBACK(pos) \
224 tnf_block_header_t *xx_blk, *xx_nxt; \
226 xx_blk = (pos)->tnfw_w_block; \
227 if (xx_blk != NULL) { \
228 (pos)->tnfw_w_write_off = xx_blk->bytes_valid; \
229 if ((pos)->tnfw_w_dirty) { \
230 xx_nxt = xx_blk->next_block; \
231 while (xx_nxt != NULL) { \
232 xx_blk->next_block = NULL; \
234 xx_nxt = xx_blk->next_block; \
235 lock_clear(&xx_blk->A_lock); \
237 (pos)->tnfw_w_dirty = 0; \
242 extern void tnfw_b_init_buffer(caddr_t
, size_t);
243 extern void *tnfw_b_alloc(TNFW_B_WCB
*, size_t, enum tnf_alloc_mode
);
244 extern void *tnfw_b_fw_alloc(TNFW_B_WCB
*);
250 #endif /* _TNF_BUF_H */