📄 tty_subr.c
字号:
/* * Copyright (c) 1994, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $\Id: tty_subr.c,v 1.10.4.4 1996/04/08 01:28:10 davidg Exp $ *//* * clist support routines */#include <sys/param.h>#include <sys/systm.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/clist.h>#include <sys/malloc.h>struct cblock *cfreelist = 0;int cfreecount = 0;static int cslushcount;static int ctotcount;#ifndef INITIAL_CBLOCKS#define INITIAL_CBLOCKS 50#endifstatic void cblock_alloc_cblocks __P((int number));static void cblock_free_cblocks __P((int number));#define CBLOCK_DIAG#ifdef CBLOCK_DIAGstatic voidcbstat(){ printf( "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n", ctotcount * CBSIZE, ctotcount * CBSIZE - cfreecount, cfreecount, cfreecount - cslushcount * CBSIZE, cslushcount * CBSIZE);}#endif/* * Called from init_main.c */voidclist_init(){ /* * Allocate an initial base set of cblocks as a 'slush'. * We allocate non-slush cblocks with each initial ttyopen() and * deallocate them with each ttyclose(). * We should adjust the slush allocation. This can't be done in * the i/o routines because they are sometimes called from * interrupt handlers when it may be unsafe to call malloc(). */ cblock_alloc_cblocks(cslushcount = INITIAL_CBLOCKS);}/* * Remove a cblock from the cfreelist queue and return a pointer * to it. */static inline struct cblock *cblock_alloc(){ struct cblock *cblockp; cblockp = cfreelist; if (cblockp == NULL) panic("clist reservation botch"); cfreelist = cblockp->c_next; cblockp->c_next = NULL; cfreecount -= CBSIZE; return (cblockp);}/* * Add a cblock to the cfreelist queue. */static inline voidcblock_free(cblockp) struct cblock *cblockp;{ if (isset(cblockp->c_quote, CBQSIZE * NBBY - 1)) bzero(cblockp->c_quote, sizeof cblockp->c_quote); cblockp->c_next = cfreelist; cfreelist = cblockp; cfreecount += CBSIZE;}/* * Allocate some cblocks for the cfreelist queue. */static voidcblock_alloc_cblocks(number) int number;{ int i; struct cblock *cbp; for (i = 0; i < number; ++i) { cbp = malloc(sizeof *cbp, M_TTYS, M_WAITOK); /* * Freed cblocks have zero quotes and garbage elsewhere. * Set the may-have-quote bit to force zeroing the quotes. */ setbit(cbp->c_quote, CBQSIZE * NBBY - 1); cblock_free(cbp); } ctotcount += number;}/* * Set the cblock allocation policy for a a clist. * Must be called in process context at spltty(). */voidclist_alloc_cblocks(clistp, ccmax, ccreserved) struct clist *clistp; int ccmax; int ccreserved;{ int dcbr; /* * Allow for wasted space at the head. */ if (ccmax != 0) ccmax += CBSIZE - 1; if (ccreserved != 0) ccreserved += CBSIZE - 1; clistp->c_cbmax = roundup(ccmax, CBSIZE) / CBSIZE; dcbr = roundup(ccreserved, CBSIZE) / CBSIZE - clistp->c_cbreserved; if (dcbr >= 0) cblock_alloc_cblocks(dcbr); else { if (clistp->c_cbreserved + dcbr < clistp->c_cbcount) dcbr = clistp->c_cbcount - clistp->c_cbreserved; cblock_free_cblocks(-dcbr); } clistp->c_cbreserved += dcbr;}/* * Free some cblocks from the cfreelist queue back to the * system malloc pool. */static voidcblock_free_cblocks(number) int number;{ int i; for (i = 0; i < number; ++i) free(cblock_alloc(), M_TTYS); ctotcount -= number;}/* * Free the cblocks reserved for a clist. * Must be called at spltty(). */voidclist_free_cblocks(clistp) struct clist *clistp;{ if (clistp->c_cbcount != 0) panic("freeing active clist cblocks"); cblock_free_cblocks(clistp->c_cbreserved); clistp->c_cbmax = 0; clistp->c_cbreserved = 0;}/* * Get a character from the head of a clist. */intgetc(clistp) struct clist *clistp;{ int chr = -1; int s; struct cblock *cblockp; s = spltty(); /* If there are characters in the list, get one */ if (clistp->c_cc) { cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); chr = (u_char)*clistp->c_cf; /* * If this char is quoted, set the flag. */ if (isset(cblockp->c_quote, clistp->c_cf - (char *)cblockp->c_info)) chr |= TTY_QUOTE; /* * Advance to next character. */ clistp->c_cf++; clistp->c_cc--; /* * If we have advanced the 'first' character pointer * past the end of this cblock, advance to the next one. * If there are no more characters, set the first and * last pointers to NULL. In either case, free the * current cblock. */ if ((clistp->c_cf >= (char *)(cblockp+1)) || (clistp->c_cc == 0)) { if (clistp->c_cc > 0) { clistp->c_cf = cblockp->c_next->c_info; } else { clistp->c_cf = clistp->c_cl = NULL; } cblock_free(cblockp); if (--clistp->c_cbcount >= clistp->c_cbreserved) ++cslushcount; } } splx(s); return (chr);}/* * Copy 'amount' of chars, beginning at head of clist 'clistp' to * destination linear buffer 'dest'. Return number of characters * actually copied. */intq_to_b(clistp, dest, amount) struct clist *clistp; char *dest; int amount;{ struct cblock *cblockp; struct cblock *cblockn; char *dest_orig = dest; int numc; int s; s = spltty(); while (clistp && amount && (clistp->c_cc > 0)) { cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); cblockn = cblockp + 1; /* pointer arithmetic! */ numc = min(amount, (char *)cblockn - clistp->c_cf); numc = min(numc, clistp->c_cc); bcopy(clistp->c_cf, dest, numc); amount -= numc; clistp->c_cf += numc; clistp->c_cc -= numc; dest += numc; /* * If this cblock has been emptied, advance to the next * one. If there are no more characters, set the first * and last pointer to NULL. In either case, free the * current cblock. */ if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) { if (clistp->c_cc > 0) { clistp->c_cf = cblockp->c_next->c_info; } else { clistp->c_cf = clistp->c_cl = NULL; } cblock_free(cblockp); if (--clistp->c_cbcount >= clistp->c_cbreserved) ++cslushcount; } } splx(s); return (dest - dest_orig);}/* * Flush 'amount' of chars, beginning at head of clist 'clistp'. */voidndflush(clistp, amount) struct clist *clistp; int amount;{ struct cblock *cblockp; struct cblock *cblockn; int numc; int s; s = spltty(); while (amount && (clistp->c_cc > 0)) { cblockp = (struct cblock *)((long)clistp->c_cf & ~CROUND); cblockn = cblockp + 1; /* pointer arithmetic! */ numc = min(amount, (char *)cblockn - clistp->c_cf); numc = min(numc, clistp->c_cc); amount -= numc; clistp->c_cf += numc; clistp->c_cc -= numc; /* * If this cblock has been emptied, advance to the next * one. If there are no more characters, set the first * and last pointer to NULL. In either case, free the * current cblock. */ if ((clistp->c_cf >= (char *)cblockn) || (clistp->c_cc == 0)) { if (clistp->c_cc > 0) { clistp->c_cf = cblockp->c_next->c_info; } else { clistp->c_cf = clistp->c_cl = NULL; } cblock_free(cblockp); if (--clistp->c_cbcount >= clistp->c_cbreserved) ++cslushcount; } } splx(s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -