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 (c) 1994,1997-1998 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #ifndef _TNF_BUF_H 28 #define _TNF_BUF_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <sys/tnf_com.h> 33 #include <sys/machlock.h> 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 /* 40 * Size of a TNF buffer block 41 */ 42 43 #define TNF_BLOCK_SIZE 512 44 #define TNF_BLOCK_SHIFT 9 45 #define TNF_BLOCK_MASK ~(TNF_BLOCK_SIZE - 1) 46 47 /* 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. 51 */ 52 53 #define TNF_DIRECTORY_SIZE (4 * 1024) 54 #define TNFW_B_FW_ZONE TNF_DIRECTORY_SIZE 55 56 /* 57 * Reserved space for tag blocks, after directory area. 58 */ 59 60 #define TNFW_B_TAG_RESERVE (28 * 1024) 61 62 #define TNFW_B_DATA_BLOCK_BEGIN (TNFW_B_FW_ZONE + TNFW_B_TAG_RESERVE) 63 64 /* 65 * Reserved directory entries, and their precomputed tags. These are byte 66 * offsets from start of file. 67 */ 68 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 73 74 #define TNF_FILE_HEADER_TAG \ 75 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_FILE_HEADER) | TNF_REF32_T_TAG) 76 77 #define TNF_BLOCK_HEADER_TAG \ 78 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_BLOCK_HEADER) | TNF_REF32_T_TAG) 79 80 #define TNF_ROOT_TAG \ 81 (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_ROOT) | TNF_REF32_T_TAG) 82 83 /* 84 * Allocation type: permanent or reusable 85 */ 86 87 enum tnf_alloc_mode { 88 TNF_ALLOC_REUSABLE = 0, 89 TNF_ALLOC_FIXED = 1 90 }; 91 92 /* 93 * Buffer status 94 */ 95 96 typedef enum { 97 TNFW_B_RUNNING = 0, 98 TNFW_B_NOBUFFER, 99 TNFW_B_BROKEN 100 } TNFW_B_STATE; 101 102 /* 103 * The STOPPED bit may be or-ed into the state field. 104 */ 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) 109 110 /* 111 * Layout of the first block of TNF file (file header) 112 */ 113 114 typedef struct { 115 tnf_uint32_t magic; /* magic number */ 116 tnf_file_header_t com; /* common header */ 117 struct { 118 volatile ulong_t gen; /* generation */ 119 volatile ulong_t block[2]; /* block number */ 120 } next_alloc; 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; 126 127 /* 128 * Per-thread write-control information 129 */ 130 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; 135 } TNFW_B_POS; 136 137 typedef struct tnfw_b_wcb { 138 struct tnfw_b_pos tnfw_w_pos; 139 struct tnfw_b_pos tnfw_w_tag_pos; 140 } TNFW_B_WCB; 141 142 /* 143 * Global tracing state 144 */ 145 146 extern TNFW_B_STATE tnfw_b_state; 147 148 /* 149 * Global trace buffer 150 */ 151 152 extern caddr_t tnf_buf; 153 154 #define TNF_FILE_HEADER() ((tnf_buf_file_header_t *)tnf_buf) 155 156 /* 157 * External interface 158 */ 159 160 /* 161 * Allocate 'size' data bytes using 'wcb'; store result into 'buf'. 162 * This inlines the common trace case. 163 */ 164 #define TNFW_B_ALLOC(wcb, size, buf, typ) \ 165 { \ 166 TNFW_B_POS *xx_pos; \ 167 ushort_t xx_off, xx_nof; \ 168 tnf_block_header_t *xx_blk; \ 169 size_t xx_size; \ 170 \ 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; \ 180 /* LINTED */ \ 181 *((int *)((char *)buf + xx_size - sizeof (int))) = 0; \ 182 } else \ 183 buf = tnfw_b_alloc((wcb), xx_size, TNF_ALLOC_REUSABLE);\ 184 } 185 186 /* 187 * Giveback words after new_pos. 188 */ 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) 194 195 /* 196 * Commit transaction bytes allocated via 'pos' 197 */ 198 #define TNFW_B_COMMIT(pos) \ 199 { \ 200 tnf_block_header_t *xx_blk, *xx_nxt; \ 201 \ 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; \ 209 xx_blk = xx_nxt; \ 210 xx_nxt = xx_blk->next_block; \ 211 xx_blk->bytes_valid = TNF_BLOCK_SIZE;\ 212 lock_clear(&xx_blk->A_lock); \ 213 } \ 214 (pos)->tnfw_w_dirty = 0; \ 215 } \ 216 } \ 217 } 218 219 /* 220 * Rollback transaction bytes allocated via 'pos' 221 */ 222 #define TNFW_B_ROLLBACK(pos) \ 223 { \ 224 tnf_block_header_t *xx_blk, *xx_nxt; \ 225 \ 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; \ 233 xx_blk = xx_nxt; \ 234 xx_nxt = xx_blk->next_block; \ 235 lock_clear(&xx_blk->A_lock); \ 236 } \ 237 (pos)->tnfw_w_dirty = 0; \ 238 } \ 239 } \ 240 } 241 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 *); 245 246 #ifdef __cplusplus 247 } 248 #endif 249 250 #endif /* _TNF_BUF_H */ 251