2 * Copyright (c) 1994, David Greenman
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/kern/tty_subr.c,v 1.32 1999/08/28 00:46:21 peter Exp $
28 * $DragonFly: src/sys/kern/tty_subr.c,v 1.10 2006/12/23 01:35:04 swildner Exp $
32 * clist support routines
34 * NOTE on cblock->c_cf: This pointer may point at the base of a cblock,
35 * which is &cblock->c_info[0], but will never
36 * point at the end of a cblock (char *)(cblk + 1)
38 * NOTE on cblock->c_cl: This pointer will never point at the base of
39 * a block but may point at the end of one.
41 * These routines may be used by more then just ttys, so a critical section
42 * must be used to access the free list, and for general safety.
45 #include <sys/param.h>
46 #include <sys/kernel.h>
47 #include <sys/systm.h>
48 #include <sys/malloc.h>
50 #include <sys/clist.h>
51 #include <sys/thread2.h>
53 static void clist_init (void *);
54 SYSINIT(clist
, SI_SUB_CLIST
, SI_ORDER_FIRST
, clist_init
, NULL
)
56 static struct cblock
*cfreelist
= 0;
58 static int cslushcount
;
61 #ifndef INITIAL_CBLOCKS
62 #define INITIAL_CBLOCKS 50
65 static struct cblock
*cblock_alloc (void);
66 static void cblock_alloc_cblocks (int number
);
67 static void cblock_free (struct cblock
*cblockp
);
68 static void cblock_free_cblocks (int number
);
74 DB_SHOW_COMMAND(cbstat
, cbstat
)
79 "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n",
80 ctotcount
* cbsize
, ctotcount
* cbsize
- cfreecount
, cfreecount
,
81 cfreecount
- cslushcount
* cbsize
, cslushcount
* cbsize
);
86 * Called from init_main.c
90 clist_init(void *dummy
)
93 * Allocate an initial base set of cblocks as a 'slush'.
94 * We allocate non-slush cblocks with each initial ttyopen() and
95 * deallocate them with each ttyclose().
96 * We should adjust the slush allocation. This can't be done in
97 * the i/o routines because they are sometimes called from
98 * interrupt handlers when it may be unsafe to call kmalloc().
100 cblock_alloc_cblocks(cslushcount
= INITIAL_CBLOCKS
);
101 KKASSERT(sizeof(struct cblock
) == CBLOCK
);
105 * Remove a cblock from the cfreelist queue and return a pointer
110 static struct cblock
*
113 struct cblock
*cblockp
;
117 panic("clist reservation botch");
118 KKASSERT(cblockp
->c_head
.ch_magic
== CLIST_MAGIC_FREE
);
119 cfreelist
= cblockp
->c_head
.ch_next
;
120 cblockp
->c_head
.ch_next
= NULL
;
121 cblockp
->c_head
.ch_magic
= CLIST_MAGIC_USED
;
122 cfreecount
-= CBSIZE
;
127 * Add a cblock to the cfreelist queue.
129 * May not block, must be called in a critical section
132 cblock_free(struct cblock
*cblockp
)
134 if (isset(cblockp
->c_quote
, CBQSIZE
* NBBY
- 1))
135 bzero(cblockp
->c_quote
, sizeof cblockp
->c_quote
);
136 KKASSERT(cblockp
->c_head
.ch_magic
== CLIST_MAGIC_USED
);
137 cblockp
->c_head
.ch_next
= cfreelist
;
138 cblockp
->c_head
.ch_magic
= CLIST_MAGIC_FREE
;
140 cfreecount
+= CBSIZE
;
144 * Allocate some cblocks for the cfreelist queue.
146 * This routine may block, but still must be called in a critical section
149 cblock_alloc_cblocks(int number
)
154 for (i
= 0; i
< number
; ++i
) {
155 cbp
= kmalloc(sizeof *cbp
, M_TTYS
, M_NOWAIT
);
158 "clist_alloc_cblocks: M_NOWAIT kmalloc failed, trying M_WAITOK\n");
159 cbp
= kmalloc(sizeof *cbp
, M_TTYS
, M_WAITOK
);
161 KKASSERT(((intptr_t)cbp
& CROUND
) == 0);
163 * Freed cblocks have zero quotes and garbage elsewhere.
164 * Set the may-have-quote bit to force zeroing the quotes.
166 setbit(cbp
->c_quote
, CBQSIZE
* NBBY
- 1);
167 cbp
->c_head
.ch_magic
= CLIST_MAGIC_USED
;
174 * Set the cblock allocation policy for a clist.
177 clist_alloc_cblocks(struct clist
*clistp
, int ccmax
, int ccreserved
)
182 * Allow for wasted space at the head.
187 ccreserved
+= CBSIZE
- 1;
190 clistp
->c_cbmax
= roundup(ccmax
, CBSIZE
) / CBSIZE
;
191 dcbr
= roundup(ccreserved
, CBSIZE
) / CBSIZE
- clistp
->c_cbreserved
;
193 clistp
->c_cbreserved
+= dcbr
; /* atomic w/c_cbmax */
194 cblock_alloc_cblocks(dcbr
); /* may block */
196 KKASSERT(clistp
->c_cbcount
<= clistp
->c_cbreserved
);
197 if (clistp
->c_cbreserved
+ dcbr
< clistp
->c_cbcount
)
198 dcbr
= clistp
->c_cbcount
- clistp
->c_cbreserved
;
199 clistp
->c_cbreserved
+= dcbr
; /* atomic w/c_cbmax */
200 cblock_free_cblocks(-dcbr
); /* may block */
202 KKASSERT(clistp
->c_cbreserved
>= 0);
207 * Free some cblocks from the cfreelist queue back to the
208 * system malloc pool.
210 * Must be called from within a critical section. May block.
213 cblock_free_cblocks(int number
)
217 for (i
= 0; i
< number
; ++i
)
218 kfree(cblock_alloc(), M_TTYS
);
223 * Free the cblocks reserved for a clist.
226 clist_free_cblocks(struct clist
*clistp
)
231 if (clistp
->c_cbcount
!= 0)
232 panic("freeing active clist cblocks");
233 cbreserved
= clistp
->c_cbreserved
;
235 clistp
->c_cbreserved
= 0;
236 cblock_free_cblocks(cbreserved
); /* may block */
241 * Get a character from the head of a clist.
244 clist_getc(struct clist
*clistp
)
247 struct cblock
*cblockp
;
251 KKASSERT(((intptr_t)clistp
->c_cf
& CROUND
) != 0);
252 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cf
& ~CROUND
);
253 chr
= (u_char
)*clistp
->c_cf
;
256 * If this char is quoted, set the flag.
258 if (isset(cblockp
->c_quote
, clistp
->c_cf
- (char *)cblockp
->c_info
))
262 * Advance to next character.
267 * If we have advanced the 'first' character pointer
268 * past the end of this cblock, advance to the next one.
269 * If there are no more characters, set the first and
270 * last pointers to NULL. In either case, free the
273 KKASSERT(clistp
->c_cf
<= (char *)(cblockp
+ 1));
274 if ((clistp
->c_cf
== (char *)(cblockp
+ 1)) ||
275 (clistp
->c_cc
== 0)) {
276 if (clistp
->c_cc
> 0) {
277 clistp
->c_cf
= cblockp
->c_head
.ch_next
->c_info
;
279 clistp
->c_cf
= clistp
->c_cl
= NULL
;
281 cblock_free(cblockp
);
282 if (--clistp
->c_cbcount
>= clistp
->c_cbreserved
)
291 * Copy 'amount' of chars, beginning at head of clist 'clistp' to
292 * destination linear buffer 'dest'. Return number of characters
296 q_to_b(struct clist
*clistp
, char *dest
, int amount
)
298 struct cblock
*cblockp
;
299 struct cblock
*cblockn
;
300 char *dest_orig
= dest
;
304 while (clistp
&& amount
&& (clistp
->c_cc
> 0)) {
305 KKASSERT(((intptr_t)clistp
->c_cf
& CROUND
) != 0);
306 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cf
& ~CROUND
);
307 cblockn
= cblockp
+ 1; /* pointer arithmetic! */
308 numc
= min(amount
, (char *)cblockn
- clistp
->c_cf
);
309 numc
= min(numc
, clistp
->c_cc
);
310 bcopy(clistp
->c_cf
, dest
, numc
);
312 clistp
->c_cf
+= numc
;
313 clistp
->c_cc
-= numc
;
316 * If this cblock has been emptied, advance to the next
317 * one. If there are no more characters, set the first
318 * and last pointer to NULL. In either case, free the
321 KKASSERT(clistp
->c_cf
<= (char *)cblockn
);
322 if ((clistp
->c_cf
== (char *)cblockn
) || (clistp
->c_cc
== 0)) {
323 if (clistp
->c_cc
> 0) {
324 KKASSERT(cblockp
->c_head
.ch_next
!= NULL
);
325 clistp
->c_cf
= cblockp
->c_head
.ch_next
->c_info
;
327 clistp
->c_cf
= clistp
->c_cl
= NULL
;
329 cblock_free(cblockp
);
330 if (--clistp
->c_cbcount
>= clistp
->c_cbreserved
)
335 return (dest
- dest_orig
);
339 * Flush 'amount' of chars, beginning at head of clist 'clistp'.
342 ndflush(struct clist
*clistp
, int amount
)
344 struct cblock
*cblockp
;
345 struct cblock
*cblockn
;
349 while (amount
&& (clistp
->c_cc
> 0)) {
350 KKASSERT(((intptr_t)clistp
->c_cf
& CROUND
) != 0);
351 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cf
& ~CROUND
);
352 cblockn
= cblockp
+ 1; /* pointer arithmetic! */
353 numc
= min(amount
, (char *)cblockn
- clistp
->c_cf
);
354 numc
= min(numc
, clistp
->c_cc
);
356 clistp
->c_cf
+= numc
;
357 clistp
->c_cc
-= numc
;
359 * If this cblock has been emptied, advance to the next
360 * one. If there are no more characters, set the first
361 * and last pointer to NULL. In either case, free the
364 KKASSERT(clistp
->c_cf
<= (char *)cblockn
);
365 if (clistp
->c_cf
== (char *)cblockn
|| clistp
->c_cc
== 0) {
366 if (clistp
->c_cc
> 0) {
367 KKASSERT(cblockp
->c_head
.ch_next
!= NULL
);
368 clistp
->c_cf
= cblockp
->c_head
.ch_next
->c_info
;
370 clistp
->c_cf
= clistp
->c_cl
= NULL
;
372 cblock_free(cblockp
);
373 if (--clistp
->c_cbcount
>= clistp
->c_cbreserved
)
381 * Add a character to the end of a clist. Return -1 is no
382 * more clists, or 0 for success.
385 clist_putc(int chr
, struct clist
*clistp
)
387 struct cblock
*cblockp
;
392 * Note: this section may point c_cl at the base of a cblock. This
393 * is a temporary violation of the requirements for c_cl, we
394 * increment it before returning.
396 if (clistp
->c_cl
== NULL
) {
397 if (clistp
->c_cbreserved
< 1) {
399 kprintf("putc to a clist with no reserved cblocks\n");
400 return (-1); /* nothing done */
402 cblockp
= cblock_alloc();
403 clistp
->c_cbcount
= 1;
404 clistp
->c_cf
= clistp
->c_cl
= cblockp
->c_info
;
407 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cl
& ~CROUND
);
408 if (((intptr_t)clistp
->c_cl
& CROUND
) == 0) {
409 struct cblock
*prev
= (cblockp
- 1);
411 if (clistp
->c_cbcount
>= clistp
->c_cbreserved
) {
412 if (clistp
->c_cbcount
>= clistp
->c_cbmax
413 || cslushcount
<= 0) {
419 cblockp
= cblock_alloc();
421 prev
->c_head
.ch_next
= cblockp
;
422 clistp
->c_cl
= cblockp
->c_info
;
427 * If this character is quoted, set the quote bit, if not, clear it.
429 if (chr
& TTY_QUOTE
) {
430 setbit(cblockp
->c_quote
, clistp
->c_cl
- (char *)cblockp
->c_info
);
432 * Use one of the spare quote bits to record that something
435 setbit(cblockp
->c_quote
, CBQSIZE
* NBBY
- 1);
437 clrbit(cblockp
->c_quote
, clistp
->c_cl
- (char *)cblockp
->c_info
);
440 *clistp
->c_cl
++ = chr
;
448 * Copy data from linear buffer to clist chain. Return the
449 * number of characters not copied.
452 b_to_q(char *src
, int amount
, struct clist
*clistp
)
454 struct cblock
*cblockp
;
455 char *firstbyte
, *lastbyte
;
456 u_char startmask
, endmask
;
457 int startbit
, endbit
, num_between
, numc
;
460 * Avoid allocating an initial cblock and then not using it.
461 * c_cc == 0 must imply c_cbount == 0.
469 * Note: this section may point c_cl at the base of a cblock. This
470 * is a temporary violation of the requirements for c_cl. Since
471 * amount is non-zero we will not return with it in that state.
473 if (clistp
->c_cl
== NULL
) {
474 if (clistp
->c_cbreserved
< 1) {
476 kprintf("b_to_q to a clist with no reserved cblocks.\n");
477 return (amount
); /* nothing done */
479 cblockp
= cblock_alloc();
480 clistp
->c_cbcount
= 1;
481 clistp
->c_cf
= clistp
->c_cl
= cblockp
->c_info
;
485 * c_cl may legally point past the end of the block, which
486 * falls through to the 'get another cblock' code below.
488 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cl
& ~CROUND
);
493 * Get another cblock if needed.
495 if (((intptr_t)clistp
->c_cl
& CROUND
) == 0) {
496 struct cblock
*prev
= cblockp
- 1;
498 if (clistp
->c_cbcount
>= clistp
->c_cbreserved
) {
499 if (clistp
->c_cbcount
>= clistp
->c_cbmax
500 || cslushcount
<= 0) {
506 cblockp
= cblock_alloc();
508 prev
->c_head
.ch_next
= cblockp
;
509 clistp
->c_cl
= cblockp
->c_info
;
513 * Copy a chunk of the linear buffer up to the end
516 numc
= min(amount
, (char *)(cblockp
+ 1) - clistp
->c_cl
);
517 bcopy(src
, clistp
->c_cl
, numc
);
520 * Clear quote bits if they aren't known to be clear.
521 * The following could probably be made into a separate
522 * "bitzero()" routine, but why bother?
524 if (isset(cblockp
->c_quote
, CBQSIZE
* NBBY
- 1)) {
525 startbit
= clistp
->c_cl
- (char *)cblockp
->c_info
;
526 endbit
= startbit
+ numc
- 1;
528 firstbyte
= (u_char
*)cblockp
->c_quote
+ (startbit
/ NBBY
);
529 lastbyte
= (u_char
*)cblockp
->c_quote
+ (endbit
/ NBBY
);
532 * Calculate mask of bits to preserve in first and
535 startmask
= NBBY
- (startbit
% NBBY
);
536 startmask
= 0xff >> startmask
;
537 endmask
= (endbit
% NBBY
);
538 endmask
= 0xff << (endmask
+ 1);
540 if (firstbyte
!= lastbyte
) {
541 *firstbyte
&= startmask
;
542 *lastbyte
&= endmask
;
544 num_between
= lastbyte
- firstbyte
- 1;
546 bzero(firstbyte
+ 1, num_between
);
548 *firstbyte
&= (startmask
| endmask
);
553 * ...and update pointer for the next chunk.
556 clistp
->c_cl
+= numc
;
557 clistp
->c_cc
+= numc
;
560 * If we go through the loop again, it's always
561 * for data in the next cblock, so by adding one (cblock),
562 * (which makes the pointer 1 beyond the end of this
563 * cblock) we prepare for the assignment of 'prev'
573 * Get the next character in the clist. Store it at dst. Don't
574 * advance any clist pointers, but return a pointer to the next
575 * character position.
577 * Must be called at spltty(). This routine may not run in a critical
578 * section and so may not call the cblock allocator/deallocator.
581 nextc(struct clist
*clistp
, char *cp
, int *dst
)
583 struct cblock
*cblockp
;
587 * See if the next character is beyond the end of
590 if (clistp
->c_cc
&& (cp
!= clistp
->c_cl
)) {
592 * If the next character is beyond the end of this
593 * cblock, advance to the next cblock.
595 if (((intptr_t)cp
& CROUND
) == 0)
596 cp
= ((struct cblock
*)cp
- 1)->c_head
.ch_next
->c_info
;
597 cblockp
= (struct cblock
*)((intptr_t)cp
& ~CROUND
);
600 * Get the character. Set the quote flag if this character
603 *dst
= (u_char
)*cp
| (isset(cblockp
->c_quote
, cp
- (char *)cblockp
->c_info
) ? TTY_QUOTE
: 0);
612 * "Unput" a character from a clist.
615 clist_unputc(struct clist
*clistp
)
617 struct cblock
*cblockp
= 0, *cbp
= 0;
624 * note that clistp->c_cl will never point at the base
625 * of a cblock (cblock->c_info) (see assert this later on),
626 * but it may point past the end of one. We temporarily
627 * violate this in the decrement below but then we fix it up.
632 chr
= (u_char
)*clistp
->c_cl
;
634 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cl
& ~CROUND
);
637 * Set quote flag if this character was quoted.
639 if (isset(cblockp
->c_quote
, (u_char
*)clistp
->c_cl
- cblockp
->c_info
))
643 * If all of the characters have been unput in this
644 * cblock, then find the previous one and free this
647 * if c_cc is 0 clistp->c_cl may end up pointing at
648 * cblockp->c_info, which is illegal, but the case will be
649 * taken care of near the end of the routine. Otherwise
650 * there *MUST* be another cblock, find it.
652 KKASSERT(clistp
->c_cl
>= (char *)cblockp
->c_info
);
653 if (clistp
->c_cc
&& (clistp
->c_cl
== (char *)cblockp
->c_info
)) {
654 cbp
= (struct cblock
*)((intptr_t)clistp
->c_cf
& ~CROUND
);
656 while (cbp
->c_head
.ch_next
!= cblockp
)
657 cbp
= cbp
->c_head
.ch_next
;
658 cbp
->c_head
.ch_next
= NULL
;
661 * When the previous cblock is at the end, the 'last'
662 * pointer always points (invalidly) one past.
664 clistp
->c_cl
= (char *)(cbp
+ 1);
665 cblock_free(cblockp
);
666 if (--clistp
->c_cbcount
>= clistp
->c_cbreserved
)
672 * If there are no more characters on the list, then
673 * free the last cblock. It should not be possible for c->cl
674 * to be pointing past the end of a block due to our decrement
677 if (clistp
->c_cc
== 0 && clistp
->c_cl
) {
678 KKASSERT(((intptr_t)clistp
->c_cl
& CROUND
) != 0);
679 cblockp
= (struct cblock
*)((intptr_t)clistp
->c_cl
& ~CROUND
);
680 cblock_free(cblockp
);
681 if (--clistp
->c_cbcount
>= clistp
->c_cbreserved
)
683 clistp
->c_cf
= clistp
->c_cl
= NULL
;
691 * Move characters in source clist to destination clist,
692 * preserving quote bits.
695 catq(struct clist
*src_clistp
, struct clist
*dest_clistp
)
701 * If the destination clist is empty (has no cblocks atttached),
702 * and there are no possible complications with the resource counters,
703 * then we simply assign the current clist to the destination.
705 if (!dest_clistp
->c_cf
706 && src_clistp
->c_cbcount
<= src_clistp
->c_cbmax
707 && src_clistp
->c_cbcount
<= dest_clistp
->c_cbmax
) {
708 dest_clistp
->c_cf
= src_clistp
->c_cf
;
709 dest_clistp
->c_cl
= src_clistp
->c_cl
;
710 src_clistp
->c_cf
= src_clistp
->c_cl
= NULL
;
712 dest_clistp
->c_cc
= src_clistp
->c_cc
;
713 src_clistp
->c_cc
= 0;
714 dest_clistp
->c_cbcount
= src_clistp
->c_cbcount
;
715 src_clistp
->c_cbcount
= 0;
723 * XXX This should probably be optimized to more than one
724 * character at a time.
726 while ((chr
= clist_getc(src_clistp
)) != -1)
727 clist_putc(chr
, dest_clistp
);