1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 1994,1997-1998 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #ifndef _TNF_BUF_H 28*0Sstevel@tonic-gate #define _TNF_BUF_H 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #include <sys/tnf_com.h> 33*0Sstevel@tonic-gate #include <sys/machlock.h> 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #ifdef __cplusplus 36*0Sstevel@tonic-gate extern "C" { 37*0Sstevel@tonic-gate #endif 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * Size of a TNF buffer block 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #define TNF_BLOCK_SIZE 512 44*0Sstevel@tonic-gate #define TNF_BLOCK_SHIFT 9 45*0Sstevel@tonic-gate #define TNF_BLOCK_MASK ~(TNF_BLOCK_SIZE - 1) 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate /* 48*0Sstevel@tonic-gate * Size of the file header and forwarding pointer (directory) area combined. 49*0Sstevel@tonic-gate * Tag and data blocks start this many bytes into the file. 50*0Sstevel@tonic-gate * The maximum size of this area is 64KB. 51*0Sstevel@tonic-gate */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #define TNF_DIRECTORY_SIZE (4 * 1024) 54*0Sstevel@tonic-gate #define TNFW_B_FW_ZONE TNF_DIRECTORY_SIZE 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * Reserved space for tag blocks, after directory area. 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate #define TNFW_B_TAG_RESERVE (28 * 1024) 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate #define TNFW_B_DATA_BLOCK_BEGIN (TNFW_B_FW_ZONE + TNFW_B_TAG_RESERVE) 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * Reserved directory entries, and their precomputed tags. These are byte 66*0Sstevel@tonic-gate * offsets from start of file. 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate #define TNF_DIRENT_FILE_HEADER (TNF_BLOCK_SIZE + 0) 70*0Sstevel@tonic-gate #define TNF_DIRENT_BLOCK_HEADER (TNF_BLOCK_SIZE + 4) 71*0Sstevel@tonic-gate #define TNF_DIRENT_ROOT (TNF_BLOCK_SIZE + 8) 72*0Sstevel@tonic-gate #define TNF_DIRENT_LAST TNF_DIRENT_ROOT 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate #define TNF_FILE_HEADER_TAG \ 75*0Sstevel@tonic-gate (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_FILE_HEADER) | TNF_REF32_T_TAG) 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate #define TNF_BLOCK_HEADER_TAG \ 78*0Sstevel@tonic-gate (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_BLOCK_HEADER) | TNF_REF32_T_TAG) 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate #define TNF_ROOT_TAG \ 81*0Sstevel@tonic-gate (TNF_REF32_MAKE_PERMANENT(TNF_DIRENT_ROOT) | TNF_REF32_T_TAG) 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Allocation type: permanent or reusable 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate enum tnf_alloc_mode { 88*0Sstevel@tonic-gate TNF_ALLOC_REUSABLE = 0, 89*0Sstevel@tonic-gate TNF_ALLOC_FIXED = 1 90*0Sstevel@tonic-gate }; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * Buffer status 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate typedef enum { 97*0Sstevel@tonic-gate TNFW_B_RUNNING = 0, 98*0Sstevel@tonic-gate TNFW_B_NOBUFFER, 99*0Sstevel@tonic-gate TNFW_B_BROKEN 100*0Sstevel@tonic-gate } TNFW_B_STATE; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /* 103*0Sstevel@tonic-gate * The STOPPED bit may be or-ed into the state field. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate #define TNFW_B_STOPPED 16 106*0Sstevel@tonic-gate #define TNFW_B_SET_STOPPED(state) ((state) |= TNFW_B_STOPPED) 107*0Sstevel@tonic-gate #define TNFW_B_UNSET_STOPPED(state) ((state) &= ~TNFW_B_STOPPED) 108*0Sstevel@tonic-gate #define TNFW_B_IS_STOPPED(state) ((state) & TNFW_B_STOPPED) 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * Layout of the first block of TNF file (file header) 112*0Sstevel@tonic-gate */ 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate typedef struct { 115*0Sstevel@tonic-gate tnf_uint32_t magic; /* magic number */ 116*0Sstevel@tonic-gate tnf_file_header_t com; /* common header */ 117*0Sstevel@tonic-gate struct { 118*0Sstevel@tonic-gate volatile ulong_t gen; /* generation */ 119*0Sstevel@tonic-gate volatile ulong_t block[2]; /* block number */ 120*0Sstevel@tonic-gate } next_alloc; 121*0Sstevel@tonic-gate ulong_t next_tag_alloc; /* block counter */ 122*0Sstevel@tonic-gate ulong_t next_fw_alloc; /* byte offset */ 123*0Sstevel@tonic-gate lock_t lock; /* protects hint updates */ 124*0Sstevel@tonic-gate /* Padding to end of block */ 125*0Sstevel@tonic-gate } tnf_buf_file_header_t; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * Per-thread write-control information 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate typedef struct tnfw_b_pos { 132*0Sstevel@tonic-gate tnf_block_header_t *tnfw_w_block; 133*0Sstevel@tonic-gate ushort_t tnfw_w_write_off; 134*0Sstevel@tonic-gate uchar_t tnfw_w_dirty; 135*0Sstevel@tonic-gate } TNFW_B_POS; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate typedef struct tnfw_b_wcb { 138*0Sstevel@tonic-gate struct tnfw_b_pos tnfw_w_pos; 139*0Sstevel@tonic-gate struct tnfw_b_pos tnfw_w_tag_pos; 140*0Sstevel@tonic-gate } TNFW_B_WCB; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * Global tracing state 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate extern TNFW_B_STATE tnfw_b_state; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate /* 149*0Sstevel@tonic-gate * Global trace buffer 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate extern caddr_t tnf_buf; 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate #define TNF_FILE_HEADER() ((tnf_buf_file_header_t *)tnf_buf) 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* 157*0Sstevel@tonic-gate * External interface 158*0Sstevel@tonic-gate */ 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Allocate 'size' data bytes using 'wcb'; store result into 'buf'. 162*0Sstevel@tonic-gate * This inlines the common trace case. 163*0Sstevel@tonic-gate */ 164*0Sstevel@tonic-gate #define TNFW_B_ALLOC(wcb, size, buf, typ) \ 165*0Sstevel@tonic-gate { \ 166*0Sstevel@tonic-gate TNFW_B_POS *xx_pos; \ 167*0Sstevel@tonic-gate ushort_t xx_off, xx_nof; \ 168*0Sstevel@tonic-gate tnf_block_header_t *xx_blk; \ 169*0Sstevel@tonic-gate size_t xx_size; \ 170*0Sstevel@tonic-gate \ 171*0Sstevel@tonic-gate /* Round size up to a multiple of 8. */ \ 172*0Sstevel@tonic-gate xx_size = (size + 7) & ~7; \ 173*0Sstevel@tonic-gate xx_pos = &(wcb)->tnfw_w_pos; \ 174*0Sstevel@tonic-gate xx_blk = xx_pos->tnfw_w_block; \ 175*0Sstevel@tonic-gate xx_off = xx_pos->tnfw_w_write_off; \ 176*0Sstevel@tonic-gate xx_nof = xx_off + xx_size; \ 177*0Sstevel@tonic-gate if (xx_blk != NULL && xx_nof <= TNF_BLOCK_SIZE) { \ 178*0Sstevel@tonic-gate buf = (typ)((char *)xx_blk + xx_off); \ 179*0Sstevel@tonic-gate xx_pos->tnfw_w_write_off = xx_nof; \ 180*0Sstevel@tonic-gate /* LINTED */ \ 181*0Sstevel@tonic-gate *((int *)((char *)buf + xx_size - sizeof (int))) = 0; \ 182*0Sstevel@tonic-gate } else \ 183*0Sstevel@tonic-gate buf = tnfw_b_alloc((wcb), xx_size, TNF_ALLOC_REUSABLE);\ 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * Giveback words after new_pos. 188*0Sstevel@tonic-gate */ 189*0Sstevel@tonic-gate #define TNFW_B_GIVEBACK(wcb, new_pos) \ 190*0Sstevel@tonic-gate ((wcb)->tnfw_w_pos.tnfw_w_write_off = \ 191*0Sstevel@tonic-gate (((char *)(new_pos) \ 192*0Sstevel@tonic-gate - (char *)((wcb)->tnfw_w_pos.tnfw_w_block) + 7) \ 193*0Sstevel@tonic-gate & ~7), *(int *)(new_pos) = 0) 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate /* 196*0Sstevel@tonic-gate * Commit transaction bytes allocated via 'pos' 197*0Sstevel@tonic-gate */ 198*0Sstevel@tonic-gate #define TNFW_B_COMMIT(pos) \ 199*0Sstevel@tonic-gate { \ 200*0Sstevel@tonic-gate tnf_block_header_t *xx_blk, *xx_nxt; \ 201*0Sstevel@tonic-gate \ 202*0Sstevel@tonic-gate xx_blk = (pos)->tnfw_w_block; \ 203*0Sstevel@tonic-gate if (xx_blk != NULL) { \ 204*0Sstevel@tonic-gate xx_blk->bytes_valid = (pos)->tnfw_w_write_off; \ 205*0Sstevel@tonic-gate if ((pos)->tnfw_w_dirty) { \ 206*0Sstevel@tonic-gate xx_nxt = xx_blk->next_block; \ 207*0Sstevel@tonic-gate while (xx_nxt != NULL) { \ 208*0Sstevel@tonic-gate xx_blk->next_block = NULL; \ 209*0Sstevel@tonic-gate xx_blk = xx_nxt; \ 210*0Sstevel@tonic-gate xx_nxt = xx_blk->next_block; \ 211*0Sstevel@tonic-gate xx_blk->bytes_valid = TNF_BLOCK_SIZE;\ 212*0Sstevel@tonic-gate lock_clear(&xx_blk->A_lock); \ 213*0Sstevel@tonic-gate } \ 214*0Sstevel@tonic-gate (pos)->tnfw_w_dirty = 0; \ 215*0Sstevel@tonic-gate } \ 216*0Sstevel@tonic-gate } \ 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Rollback transaction bytes allocated via 'pos' 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate #define TNFW_B_ROLLBACK(pos) \ 223*0Sstevel@tonic-gate { \ 224*0Sstevel@tonic-gate tnf_block_header_t *xx_blk, *xx_nxt; \ 225*0Sstevel@tonic-gate \ 226*0Sstevel@tonic-gate xx_blk = (pos)->tnfw_w_block; \ 227*0Sstevel@tonic-gate if (xx_blk != NULL) { \ 228*0Sstevel@tonic-gate (pos)->tnfw_w_write_off = xx_blk->bytes_valid; \ 229*0Sstevel@tonic-gate if ((pos)->tnfw_w_dirty) { \ 230*0Sstevel@tonic-gate xx_nxt = xx_blk->next_block; \ 231*0Sstevel@tonic-gate while (xx_nxt != NULL) { \ 232*0Sstevel@tonic-gate xx_blk->next_block = NULL; \ 233*0Sstevel@tonic-gate xx_blk = xx_nxt; \ 234*0Sstevel@tonic-gate xx_nxt = xx_blk->next_block; \ 235*0Sstevel@tonic-gate lock_clear(&xx_blk->A_lock); \ 236*0Sstevel@tonic-gate } \ 237*0Sstevel@tonic-gate (pos)->tnfw_w_dirty = 0; \ 238*0Sstevel@tonic-gate } \ 239*0Sstevel@tonic-gate } \ 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate extern void tnfw_b_init_buffer(caddr_t, size_t); 243*0Sstevel@tonic-gate extern void *tnfw_b_alloc(TNFW_B_WCB *, size_t, enum tnf_alloc_mode); 244*0Sstevel@tonic-gate extern void *tnfw_b_fw_alloc(TNFW_B_WCB *); 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate #ifdef __cplusplus 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate #endif 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate #endif /* _TNF_BUF_H */ 251