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 1994-2003 Sun Microsytems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
30 #include <sys/param.h>
32 #include <sys/systm.h> /* for bzero */
34 #include <sys/cmn_err.h>
36 #include <string.h> /* for memset */
48 #endif /* TNFW_DEBUG */
54 #define TNFW_B_FW_INVALID 0xffffffff
55 #define TNFW_B_ALLOC_LO_SELECTOR 0x1
56 #define TNFW_B_MAXALLOCTRY 200
58 #ifdef TNF_BLOCK_STATS
62 int tnf_max_block_tries
;
64 int tnf_generation_laps
;
71 * Regular record tag pointer - CAUTION - has to be in sync with tnf_tag
74 #define TNFW_B_TAG_DIFF(item, ref) \
75 ((TNF_REF32_MAKE_PERMANENT((tnf_ref32_t) \
76 ((char *)(item) - (char *)(ref)))) | TNF_REF32_T_TAG)
79 * Exported interface by buffering layer to indicate where fowarding ptrs
80 * for file header and block header are.
82 static tnf_buf_header_t forwarding_ptrs
= {NULL
, NULL
, NULL
};
83 tnf_buf_header_t
*_tnf_buf_headers_p
= &forwarding_ptrs
;
86 extern volatile caddr_t tnf_buf
;
88 static kmutex_t hintlock
;
92 * (Private) Allocate a new block. Return NULL on failure. 'istag'
93 * is true if the block is to be non-reclaimable.
95 static tnf_block_header_t
*
96 tnfw_b_alloc_block(TNFW_B_WCB
*wcb
, enum tnf_alloc_mode istag
)
98 tnf_block_header_t
*block
;
99 uint_t hint_hi
, hint_lo
;
100 uint_t new_hint_hi
, new_hint_lo
;
104 uint_t prev_block
= 0;
106 boolean_t gotit
= B_FALSE
;
107 volatile tnf_buf_file_header_t
*fh
;
108 #ifdef TNF_BLOCK_STATS
109 register int tag_blocks
= 0, generation_laps
= 0, a_locks
= 0,
114 fprintf(stderr
, "tnfw_b_alloc_block: \n");
117 if (_tnfw_b_control
->tnf_state
!= TNFW_B_RUNNING
) {
119 if (_tnfw_b_control
->tnf_state
== TNFW_B_NOBUFFER
)
120 if (_tnfw_b_control
->tnf_init_callback() == 0)
123 if (TNFW_B_IS_STOPPED(_tnfw_b_control
->tnf_state
))
125 if (_tnfw_b_control
->tnf_state
== TNFW_B_BROKEN
)
129 /* LINTED pointer cast may result in improper alignment */
130 fh
= (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
131 if (!wcb
->tnfw_w_initialized
) {
132 /* Get the block shift and generation shift values. */
134 wcb
->tnfw_w_block_shift
= wcb
->tnfw_w_gen_shift
= 0;
135 while (b
!= fh
->com
.block_size
) {
137 ++wcb
->tnfw_w_block_shift
;
140 while (b
< fh
->com
.block_count
) {
142 ++wcb
->tnfw_w_gen_shift
;
144 wcb
->tnfw_w_pid
= _tnfw_b_control
->tnf_pid
;
145 wcb
->tnfw_w_initialized
= B_TRUE
;
149 * If we need a tag block, check the reserved tag block space
150 * first. fh->next_tag_alloc is only a hint; it is updated
151 * without concurrency control.
153 if (istag
&& fh
->next_tag_alloc
< TNFW_B_DATA_BLOCK_BEGIN
) {
154 i
= fh
->next_tag_alloc
;
156 /* LINTED pointer cast */
157 block
= (tnf_block_header_t
*) ((char *) fh
+ i
);
158 if (!tnfw_b_get_lock(&block
->A_lock
) &&
159 block
->generation
== 0)
161 i
+= fh
->com
.block_size
;
162 } while (i
< TNFW_B_DATA_BLOCK_BEGIN
);
163 if (i
< TNFW_B_DATA_BLOCK_BEGIN
) {
164 if (i
> fh
->next_tag_alloc
)
165 fh
->next_tag_alloc
= i
;
166 blocknum
= i
>> wcb
->tnfw_w_block_shift
;
167 if (blocknum
> fh
->com
.blocks_valid
)
168 fh
->com
.blocks_valid
= blocknum
;
169 /* LINTED pointer subtraction casted to 32 bits */
170 block
->tag
= TNFW_B_TAG_DIFF(
171 forwarding_ptrs
.fw_block_header
, fh
);
172 /* LINTED constant truncated by assignment */
173 block
->generation
= TNF_TAG_GENERATION_NUM
;
174 block
->bytes_valid
= sizeof (tnf_block_header_t
);
175 block
->next_block
= NULL
;
176 tnfw_b_clear_lock(&block
->A_lock
);
181 for (i
= 0; !gotit
&& i
!= TNFW_B_MAXALLOCTRY
; ++i
) {
182 hint_hi
= fh
->next_alloc
.hi
;
183 hint_lo
= (hint_hi
& TNFW_B_ALLOC_LO_SELECTOR
)
184 ? fh
->next_alloc
.lo
[1] : fh
->next_alloc
.lo
[0];
185 generation
= (hint_hi
<< (32 - wcb
->tnfw_w_gen_shift
)) |
186 (hint_lo
>> wcb
->tnfw_w_gen_shift
);
187 blocknum
= hint_lo
& ((1 << wcb
->tnfw_w_gen_shift
) - 1);
189 fprintf(stderr
, "alloc_block (%d): read hint (%d, %d)\n",
190 thr_self(), generation
, blocknum
);
192 if ((prev_gen
== generation
&& prev_block
> blocknum
) ||
193 prev_gen
> generation
) {
194 generation
= prev_gen
;
195 blocknum
= prev_block
;
199 "alloc_block (%d): trying blocknum = %d, gen %d\n",
200 thr_self(), blocknum
, generation
);
202 block
= (tnf_block_header_t
*)
203 /* LINTED pointer cast may result in improper alignment */
204 ((char *)fh
+ blocknum
* fh
->com
.block_size
);
205 #ifdef TNF_BLOCK_STATS
206 if (block
->generation
== TNF_TAG_GENERATION_NUM
)
208 else if (block
->generation
>= generation
)
210 else if (tnfw_b_get_lock(&block
->A_lock
))
212 else if (block
->generation
== TNF_TAG_GENERATION_NUM
)
214 else if (block
->generation
>= generation
)
216 else if (tnfw_b_get_lock(&block
->B_lock
)) {
217 tnfw_b_clear_lock(&block
->A_lock
);
223 if (block
->generation
< generation
&&
224 !tnfw_b_get_lock(&block
->A_lock
)) {
225 if (block
->generation
< generation
&&
226 !tnfw_b_get_lock(&block
->B_lock
)) {
229 tnfw_b_clear_lock(&block
->A_lock
);
233 prev_block
= blocknum
+ 1;
234 prev_gen
= generation
;
235 if (prev_block
== fh
->com
.block_count
) {
237 TNFW_B_DATA_BLOCK_BEGIN
>> wcb
->tnfw_w_block_shift
;
240 if (blocknum
> fh
->com
.blocks_valid
) {
241 fh
->com
.blocks_valid
= blocknum
;
245 if (i
== TNFW_B_MAXALLOCTRY
) {
246 _tnfw_b_control
->tnf_state
= TNFW_B_BROKEN
;
251 "alloc_block (%d): got blocknum = %d, gen %d, block at 0x%x\n",
252 thr_self(), blocknum
, generation
, block
);
254 /* LINTED pointer subtraction casted to 32 bits */
255 block
->tag
= TNFW_B_TAG_DIFF(forwarding_ptrs
.fw_block_header
, fh
);
256 block
->generation
= (istag
) ? TNF_TAG_GENERATION_NUM
: generation
;
257 block
->bytes_valid
= sizeof (tnf_block_header_t
);
258 block
->next_block
= NULL
;
260 tnfw_b_clear_lock(&block
->A_lock
);
262 tnfw_b_clear_lock(&block
->B_lock
);
265 * Read the hint one more time, only update it if we'll be increasing
268 new_hint_hi
= prev_gen
>> (32 - wcb
->tnfw_w_gen_shift
);
269 new_hint_lo
= prev_block
| (prev_gen
<< wcb
->tnfw_w_gen_shift
);
271 mutex_enter(&hintlock
);
273 hint_hi
= fh
->next_alloc
.hi
;
274 hint_lo
= (hint_hi
& TNFW_B_ALLOC_LO_SELECTOR
) ?
275 fh
->next_alloc
.lo
[1] : fh
->next_alloc
.lo
[0];
277 if ((new_hint_hi
== hint_hi
&& new_hint_lo
> hint_lo
) ||
278 new_hint_hi
> hint_hi
) {
280 * Order is important here! It is the write to next_alloc.hi
281 * that atomically records the new value.
283 if (new_hint_hi
& TNFW_B_ALLOC_LO_SELECTOR
)
284 fh
->next_alloc
.lo
[1] = new_hint_lo
;
286 fh
->next_alloc
.lo
[0] = new_hint_lo
;
287 fh
->next_alloc
.hi
= new_hint_hi
;
289 fprintf(stderr
, "alloc_block (%d): wrote hint (%d, %d)\n",
290 thr_self(), prev_gen
, prev_block
);
294 mutex_exit(&hintlock
);
296 #ifdef TNF_BLOCK_STATS
297 ++tnf_block_stats
.tnf_block_allocs
;
298 tnf_block_stats
.tnf_block_tries
+= i
;
299 if (i
> tnf_block_stats
.tnf_max_block_tries
) {
300 tnf_block_stats
.tnf_max_block_tries
= i
;
301 tnf_block_stats
.tnf_tag_blocks
= tag_blocks
;
302 tnf_block_stats
.tnf_generation_laps
= generation_laps
;
303 tnf_block_stats
.tnf_a_locks
= a_locks
;
304 tnf_block_stats
.tnf_b_locks
= b_locks
;
310 static void release_block_from_pos(TNFW_B_POS
* pos
)
312 if (pos
->tnfw_w_block
== NULL
)
314 if (pos
->tnfw_w_uncommitted
!= NULL
)
316 tnfw_b_clear_lock(&pos
->tnfw_w_block
->A_lock
);
317 pos
->tnfw_w_block
= NULL
;
321 tnfw_b_release_block(TNFW_B_WCB
* wcb
)
325 release_block_from_pos(&wcb
->tnfw_w_tag_pos
);
326 release_block_from_pos(&wcb
->tnfw_w_pos
);
330 * Initialize a buffer. NOT RE-ENTRANT! Block sizes other than 512
331 * are currently rejected. The code "ought to work" with any block
332 * size that is an integral power of 2. 'zfod' states whether we
333 * can assume that the buffer is zero-filled (or paged-in zero-fill-on-demand).
336 tnfw_b_init_buffer(char *buf
, int blocks
, int block_size
, boolean_t zfod
)
339 int block_shift
, gen_shift
;
343 tnf_block_header_t
*block
;
344 /* LINTED pointer cast may result in improper alignment */
345 tnf_buf_file_header_t
*fh
= (tnf_buf_file_header_t
*)buf
;
348 fprintf(stderr
, "tnfw_b_init_buffer: \n");
351 /* Check for 512 could go away. */
352 if (block_size
!= 512 || block_size
< sizeof (tnf_buf_file_header_t
))
353 return (TNFW_B_BAD_BLOCK_SIZE
);
355 * Check to see if block size is a power of 2, and get
358 for (b
= (unsigned)block_size
, block_shift
= 0; (b
& 1) == 0; b
>>= 1)
361 return (TNFW_B_BAD_BLOCK_SIZE
);
367 /* reserve first two words for file header tag and block header tag */
368 forwarding_ptrs
.fw_file_header
= (char *)fh
+ block_size
;
369 forwarding_ptrs
.fw_block_header
= (char *)fh
+ block_size
+
370 sizeof (tnf_ref32_t
);
371 forwarding_ptrs
.fw_root
= (char *)fh
+ block_size
+
372 (2 * sizeof (tnf_ref32_t
));
373 /* LINTED size of tnf_ref_32_t known to be 32 */
374 fh
->next_fw_alloc
= block_size
+ (3 * sizeof (tnf_ref32_t
));
375 /* fill in rest of file header */
376 fh
->magic
= TNF_MAGIC
;
377 /* Self relative pointer to tag */
378 /* LINTED pointer subtraction casted to 32 bits */
379 fh
->com
.tag
= TNFW_B_TAG_DIFF(forwarding_ptrs
.fw_file_header
, fh
);
380 fh
->com
.file_version
= TNF_FILE_VERSION
;
381 fh
->com
.file_header_size
= sizeof (tnf_file_header_t
);
382 /* fill in fh->com.file_log_size */
384 file_size
= blocks
* block_size
;
385 fh
->com
.file_log_size
= 0;
386 while (b
< file_size
) {
388 ++fh
->com
.file_log_size
;
391 fh
->com
.block_header_size
= sizeof (tnf_block_header_t
);
392 fh
->com
.block_size
= block_size
;
393 fh
->com
.directory_size
= TNFW_B_FW_ZONE
;
394 fh
->com
.block_count
= blocks
;
395 fh
->com
.blocks_valid
= TNFW_B_FW_ZONE
>> block_shift
;
396 if (fh
->com
.blocks_valid
== 0)
397 fh
->com
.blocks_valid
= 1;
398 fh
->next_tag_alloc
= TNFW_B_FW_ZONE
;
399 fh
->next_alloc
.hi
= 0;
400 fh
->next_alloc
.lo
[0] =
401 (1 << gen_shift
) | (TNFW_B_DATA_BLOCK_BEGIN
>> block_shift
);
403 fprintf(stderr
, "gen_shift = %d, blocks_valid = %d\n",
404 gen_shift
, fh
->com
.blocks_valid
);
405 fprintf(stderr
, "alloc hint initialized to (%d, %d, %d)\n",
406 fh
->next_alloc
.hi
, fh
->next_alloc
.lo
[0], fh
->next_alloc
.lo
[1]);
409 for (i
= 1; i
< (TNFW_B_FW_ZONE
>> block_shift
); ++i
) {
411 bzero(buf
+ (i
<< block_shift
), block_size
);
413 (void) memset(buf
+ (i
<< block_shift
), 0, block_size
);
416 for (; i
!= blocks
; ++i
) {
417 block
= (tnf_block_header_t
*)
418 /* LINTED pointer cast */
419 (buf
+ (i
<< block_shift
));
421 block
->generation
= 0;
422 tnfw_b_clear_lock(&block
->A_lock
);
423 tnfw_b_clear_lock(&block
->B_lock
);
427 mutex_init(&hintlock
, "tnf buffer hint lock", MUTEX_SPIN_DEFAULT
,
428 (void *) ipltospl(LOCK_LEVEL
));
437 tnfw_b_alloc(TNFW_B_WCB
*wcb
, size_t size
, enum tnf_alloc_mode istag
)
442 volatile tnf_buf_file_header_t
*fh
;
443 tnf_block_header_t
*block
, *new_block
;
446 fprintf(stderr
, "tnfw_b_alloc: \n");
449 if (_tnfw_b_control
->tnf_state
!= TNFW_B_RUNNING
) {
450 if (TNFW_B_IS_STOPPED(_tnfw_b_control
->tnf_state
))
452 if (_tnfw_b_control
->tnf_state
== TNFW_B_FORKED
&&
453 _tnfw_b_control
->tnf_pid
!= wcb
->tnfw_w_pid
) {
454 wcb
->tnfw_w_pos
.tnfw_w_block
=
455 wcb
->tnfw_w_pos
.tnfw_w_uncommitted
=
456 wcb
->tnfw_w_tag_pos
.tnfw_w_block
=
457 wcb
->tnfw_w_tag_pos
.tnfw_w_uncommitted
= NULL
;
458 wcb
->tnfw_w_pid
= _tnfw_b_control
->tnf_pid
;
459 _tnfw_b_control
->tnf_fork_callback();
463 /* Round size up to a multiple of 8. */
464 size
= (size
+ 7) & ~7;
466 /* LINTED pointer cast may result in improper alignment */
467 fh
= (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
468 pos
= (istag
) ? &wcb
->tnfw_w_tag_pos
: &wcb
->tnfw_w_pos
;
469 block
= pos
->tnfw_w_block
;
470 /* Check size within range. */
472 if (size
> fh
->com
.block_size
- sizeof (tnf_block_header_t
))
473 /* TNFW_B_RECORD_TOO_BIG */
476 offset
= pos
->tnfw_w_write_off
;
477 #ifdef TNFWB_MAY_RELEASE_A_LOCK
478 if (block
!= NULL
&& wcb
->tnfw_w_a_lock_released
) {
479 /* re-acquire the A-lock for the current block */
480 if (!tnfw_b_get_lock(&block
->A_lock
)) {
481 wcb
->tnfw_w_a_lock_released
= B_FALSE
;
482 if (wcb
->tnfw_w_generation
!= block
->generation
) {
483 tnfw_b_clear_lock(&block
->A_lock
);
484 wcb
->tnfw_w_pos
.tnfw_w_block
= NULL
;
487 wcb
->tnfw_w_pos
.tnfw_w_block
= NULL
;
491 if (block
== NULL
|| offset
+ size
> fh
->com
.block_size
) {
492 new_block
= tnfw_b_alloc_block(wcb
, istag
);
493 if (new_block
== NULL
) {
499 "wcb 0x%x: new block at 0x%x, old block is 0x%x, "
500 "uncommitted is 0x%x\n",
501 wcb
, new_block
, block
, pos
->tnfw_w_uncommitted
);
504 /* XXXX is this what we want for padding? */
506 (void) bzero((char *)block
+ offset
,
507 fh
->com
.block_size
- offset
);
509 (void) memset((char *)block
+ offset
, 0,
510 fh
->com
.block_size
- offset
);
512 if (pos
->tnfw_w_uncommitted
== NULL
) {
513 #ifdef TNFWB_MAY_RELEASE_A_LOCK
514 /* Could still be holding the A-lock on block */
515 if (!wcb
->tnfw_w_a_lock_released
)
516 tnfw_b_clear_lock(&block
->A_lock
);
518 /* Definitely still holding the A-lock */
519 tnfw_b_clear_lock(&block
->A_lock
);
520 #endif /* TNFWB_MAY_RELEASE_A_LOCK */
523 /* Add new_block to the list of uncommitted blocks. */
524 if (pos
->tnfw_w_uncommitted
== NULL
) {
525 pos
->tnfw_w_uncommitted
= new_block
;
527 /* Assert(block != NULL); */
528 block
->next_block
= new_block
;
530 pos
->tnfw_w_block
= new_block
;
531 pos
->tnfw_w_write_off
= new_block
->bytes_valid
;
532 } else if (pos
->tnfw_w_uncommitted
== NULL
) {
533 pos
->tnfw_w_uncommitted
= block
;
535 destp
= (char *)pos
->tnfw_w_block
+ pos
->tnfw_w_write_off
;
536 pos
->tnfw_w_write_off
+= size
;
538 * Unconditionally write a 0 into the last word allocated,
539 * in case we left an alignment gap. (Assume that doing an
540 * unconditional write is cheaper than testing and branching
541 * around the write half the time.)
543 /* LINTED pointer cast may result in improper alignment */
544 *((int *)((char *) destp
+ size
- sizeof (int))) = 0;
547 fprintf(stderr
, "tnfw_b_alloc returning %p\n", destp
);
556 tnfw_b_xcommit(TNFW_B_WCB
*wcb
)
559 tnf_block_header_t
*block
;
560 volatile tnf_buf_file_header_t
*fh
=
561 /* LINTED pointer cast may result in improper alignment */
562 (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
565 fprintf(stderr
, "tnfw_b_xcommit \n");
569 * cope with the normal record block(s) first
572 pos
= &wcb
->tnfw_w_pos
;
573 block
= pos
->tnfw_w_uncommitted
;
574 while (block
&& (block
!= pos
->tnfw_w_block
)) {
576 fprintf(stderr
, "commit %d: block = 0x%x, last = 0x%x\n",
577 block
->generation
, block
, pos
->tnfw_w_block
);
579 block
->bytes_valid
= fh
->com
.block_size
;
580 pos
->tnfw_w_uncommitted
= block
->next_block
;
581 tnfw_b_clear_lock(&block
->A_lock
);
582 block
= pos
->tnfw_w_uncommitted
;
586 fprintf(stderr
, "commit last %d: block = 0x%x, offset = 0x%x\n",
587 block
->generation
, block
, pos
->tnfw_w_write_off
);
589 block
->bytes_valid
= pos
->tnfw_w_write_off
;
591 pos
->tnfw_w_uncommitted
= NULL
;
592 #ifdef TNFWB_MAY_RELEASE_A_LOCK
593 if (0) { /* XXXX Do we or don't we clear this lock? */
594 wcb
->tnfw_w_generation
= block
->generation
;
595 tnfw_b_clear_lock(&block
->A_lock
);
596 wcb
->tnfw_w_a_lock_released
= B_TRUE
;
601 * cope with the tag block(s)
604 pos
= &wcb
->tnfw_w_tag_pos
;
605 block
= pos
->tnfw_w_uncommitted
;
606 while (block
&& (block
!= pos
->tnfw_w_block
)) {
608 fprintf(stderr
, "commit %d: block = 0x%x, last = 0x%x\n",
609 thr_self(), block
, pos
->tnfw_w_block
);
611 block
->bytes_valid
= fh
->com
.block_size
;
612 pos
->tnfw_w_uncommitted
= block
->next_block
;
613 block
= pos
->tnfw_w_uncommitted
;
616 block
->bytes_valid
= pos
->tnfw_w_write_off
;
617 pos
->tnfw_w_uncommitted
= NULL
;
625 tnfw_b_xabort(TNFW_B_WCB
*wcb
)
627 TNFW_B_POS
*pos
= &wcb
->tnfw_w_pos
;
628 tnf_block_header_t
*block
, *next
;
629 volatile tnf_buf_file_header_t
*fh
=
630 /* LINTED pointer cast may result in improper alignment */
631 (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
633 block
= pos
->tnfw_w_block
= pos
->tnfw_w_uncommitted
;
635 pos
->tnfw_w_write_off
= block
->bytes_valid
;
636 #ifdef TNFWB_MAY_RELEASE_A_LOCK
638 tnfw_b_clear_lock(&block
->A_lock
);
639 wcb
->tnfw_w_generation
= block
->generation
;
640 wcb
->tnfw_w_a_lock_released
= B_TRUE
;
643 block
= block
->next_block
;
645 while (block
!= NULL
) {
646 next
= block
->next_block
;
647 tnfw_b_clear_lock(&block
->A_lock
);
650 pos
->tnfw_w_uncommitted
= NULL
;
651 pos
= &wcb
->tnfw_w_tag_pos
;
652 block
= pos
->tnfw_w_uncommitted
;
653 while (block
&& (block
!= pos
->tnfw_w_block
)) {
654 block
->bytes_valid
= fh
->com
.block_size
;
655 pos
->tnfw_w_uncommitted
= block
->next_block
;
656 block
= pos
->tnfw_w_uncommitted
;
659 block
->bytes_valid
= pos
->tnfw_w_write_off
;
660 pos
->tnfw_w_uncommitted
= NULL
;
665 * The kernel version is different because we can use a spin mutex
666 * in the kernel, and not all SPARC systems support the SWAP instruction.
671 tnfw_b_fw_alloc(TNFW_B_WCB
*wcb
)
673 tnf_uint32_t
*ret_val
;
674 volatile tnf_buf_file_header_t
*fh
=
675 /* LINTED pointer cast may result in improper alignment */
676 (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
677 tnf_uint32_t
*zone_end
= (tnf_uint32_t
*)((char *)fh
+ TNFW_B_FW_ZONE
);
678 mutex_enter(&hintlock
);
679 ret_val
= (tnf_uint32_t
*)((char *)fh
+ fh
->next_fw_alloc
);
680 if (ret_val
!= zone_end
)
681 fh
->next_fw_alloc
+= sizeof (tnf_uint32_t
);
682 mutex_exit(&hintlock
);
683 return ((ret_val
!= zone_end
) ? ret_val
: NULL
);
690 tnfw_b_fw_alloc(TNFW_B_WCB
*wcb
)
692 volatile tnf_buf_file_header_t
*fh
=
693 /* LINTED pointer cast may result in improper alignment */
694 (volatile tnf_buf_file_header_t
*)_tnfw_b_control
->tnf_buffer
;
695 /* LINTED pointer cast may result in improper alignment */
696 uint_t
*hint
= (uint_t
*)((uintptr_t)fh
+ fh
->next_fw_alloc
);
697 /* LINTED pointer cast may result in improper alignment */
698 ulong_t
*zone_end
= (ulong_t
*)((uintptr_t)fh
+ TNFW_B_FW_ZONE
);
701 tnf_uint32_t
*retval
;
704 sprintf(tmp_buf
, "tnfw_b_vw_alloc: begin\n");
705 (void) write(2, tmp_buf
, strlen(tmp_buf
));
709 sprintf(tmp_buf
, "tnfw_b_vw_alloc: (1)hint=%p\n", hint
);
710 (void) write(2, tmp_buf
, strlen(tmp_buf
));
713 while ((uintptr_t)hint
!= (uintptr_t)zone_end
) {
715 sprintf(tmp_buf
, "tnfw_b_vw_alloc: (2)hint=%p,zone_end=%p\n",
717 (void) write(2, tmp_buf
, strlen(tmp_buf
));
721 sprintf(tmp_buf
, "tnfw_b_fw_alloc: fh = %p, next->alloc = %d\n",
722 fh
, fh
->next_fw_alloc
);
723 (void) write(2, tmp_buf
, strlen(tmp_buf
));
725 sprintf(tmp_buf
, "tnfw_b_vw_alloc: about to deref hint\n");
726 (void) write(2, tmp_buf
, strlen(tmp_buf
));
728 sprintf(tmp_buf
, "tnfw_b_vw_alloc: *hint=%ld\n", *hint
);
729 (void) write(2, tmp_buf
, strlen(tmp_buf
));
732 swapin
= tnfw_b_atomic_swap(hint
, TNFW_B_FW_INVALID
);
734 if (swapin
!= (unsigned)TNFW_B_FW_INVALID
) {
744 sprintf(tmp_buf
, "tnfw_b_vw_alloc: (3)hint=%p\n", hint
);
745 (void) write(2, tmp_buf
, strlen(tmp_buf
));
749 /* LINTED pointer subtraction casted to 32 bits */
750 fh
->next_fw_alloc
= (uint_t
) ((char *)hint
- (char *)fh
);
751 retval
= (((uintptr_t)hint
!= (uintptr_t)zone_end
) ?
752 (tnf_uint32_t
*)hint
: NULL
);
755 sprintf(tmp_buf
, "tnfw_b_vw_alloc: returning %p", retval
);
756 (void) write(2, tmp_buf
, strlen(tmp_buf
));