change DEFAULT_MAXPTYS to 256

make all local variables static
use simplelocks - we really need only mutexes, full locks are not necessary
update couple of comments to be more accurate

add function pty_maxptys(), which provides a safe way to get&set maxptys - this
	also supports setting maxptys to lower than current value, if the
	value is lower or equal current number of ptys
This commit is contained in:
jdolecek 2000-09-10 17:26:45 +00:00
parent cd0b41e240
commit 9bdbbbc834

View File

@ -1,4 +1,4 @@
/* $NetBSD: tty_pty.c,v 1.47 2000/09/09 16:42:04 jdolecek Exp $ */ /* $NetBSD: tty_pty.c,v 1.48 2000/09/10 17:26:45 jdolecek Exp $ */
/* /*
* Copyright (c) 1982, 1986, 1989, 1993 * Copyright (c) 1982, 1986, 1989, 1993
@ -58,7 +58,7 @@
#include <sys/malloc.h> #include <sys/malloc.h>
#define DEFAULT_NPTYS 16 /* default number of initial ptys */ #define DEFAULT_NPTYS 16 /* default number of initial ptys */
#define DEFAULT_MAXPTYS 512 /* default maximum number of ptys */ #define DEFAULT_MAXPTYS 256 /* default maximum number of ptys */
/* Macros to clear/set/test flags. */ /* Macros to clear/set/test flags. */
#define SET(t, f) (t) |= (f) #define SET(t, f) (t) |= (f)
@ -79,10 +79,13 @@ struct pt_softc {
u_char pt_ucntl; u_char pt_ucntl;
}; };
struct pt_softc **pt_softc = NULL; /* pty array */ static struct pt_softc **pt_softc = NULL; /* pty array */
int npty = 0; /* for pstat -t */ static int npty = 0; /* for pstat -t */
int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */ static int maxptys = DEFAULT_MAXPTYS; /* maximum number of ptys (sysctable) */
struct lock pt_softc_lock;
#if defined(MULTIPROCESSOR)
static struct simplelock pt_softc_mutex = SIMPLELOCK_INITIALIZER;
#endif
#define PF_PKT 0x08 /* packet mode */ #define PF_PKT 0x08 /* packet mode */
#define PF_STOPPED 0x10 /* user told stopped */ #define PF_STOPPED 0x10 /* user told stopped */
@ -92,15 +95,16 @@ struct lock pt_softc_lock;
void ptyattach __P((int)); void ptyattach __P((int));
void ptcwakeup __P((struct tty *, int)); void ptcwakeup __P((struct tty *, int));
int ptcopen __P((dev_t, int, int, struct proc *)); int ptcopen __P((dev_t, int, int, struct proc *));
struct tty *ptytty __P((dev_t)); struct tty *ptytty __P((dev_t));
void ptsstart __P((struct tty *)); void ptsstart __P((struct tty *));
int pty_maxptys __P((int, int));
static struct pt_softc **ptyarralloc __P((int)); static struct pt_softc **ptyarralloc __P((int));
static int check_pty __P((dev_t)); static int check_pty __P((dev_t));
/* /*
* Allocate array of nelem elements. * Allocate and zero array of nelem elements.
*/ */
static struct pt_softc ** static struct pt_softc **
ptyarralloc(nelem) ptyarralloc(nelem)
@ -122,86 +126,129 @@ check_pty(dev)
dev_t dev; dev_t dev;
{ {
struct pt_softc *pti; struct pt_softc *pti;
int locked = 0;
if (minor(dev) >= maxptys) {
tablefull("pty", "increase kern.maxptys");
return (ENXIO);
}
if (minor(dev) >= npty) { if (minor(dev) >= npty) {
struct pt_softc **newpt; struct pt_softc **newpt;
int newnpty = npty; int newnpty;
while(newnpty <= minor(dev)) /* check if the requested pty can be granted */
newnpty *= 2; if (minor(dev) >= maxptys) {
if (newnpty > maxptys) limit_reached:
newnpty = maxptys; tablefull("pty", "increase kern.maxptys");
simple_unlock(&pt_softc_mutex);
newpt = ptyarralloc(newnpty); return (ENXIO);
}
/* /*
* Now grab the pty array lock. We need to ensure * Now grab the pty array mutex - we need to ensure
* that the pty array is consistent while copying it's * that the pty array is consistent while copying it's
* content to newly allocated, larger space. * content to newly allocated, larger space; we also
* need to be safe against pty_maxptys().
*/ */
lockmgr(&pt_softc_lock, LK_EXCLUSIVE, NULL); simple_lock(&pt_softc_mutex);
locked = 1;
do {
for(newnpty = npty; newnpty <= minor(dev);
newnpty *= 2);
if (newnpty > maxptys)
newnpty = maxptys;
simple_unlock(&pt_softc_mutex);
newpt = ptyarralloc(newnpty);
simple_lock(&pt_softc_mutex);
if (maxptys == npty) {
/* we hold the mutex here */
goto limit_reached;
}
} while(newnpty > maxptys);
/* /*
* If the number of ptys is still not enough, replace * If the pty array was not enlarged while we were waiting
* the old array with the newly allocated one. * for mutex, copy current contents of pt_softc[] to newly
* allocated array and start using the new bigger array.
*/ */
if (minor(dev) >= npty) { if (minor(dev) >= npty) {
/*
* Copy old pt_softc[] contents over, free old
* array and start using new array.
*/
memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *)); memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *));
free(pt_softc, M_DEVBUF); free(pt_softc, M_DEVBUF);
pt_softc = newpt; pt_softc = newpt;
npty = newnpty; npty = newnpty;
} else { } else {
/* has been enlarged while we slept, free space */ /* was enlarged when waited fot lock, free new space */
free(newpt, M_DEVBUF); free(newpt, M_DEVBUF);
} }
simple_unlock(&pt_softc_mutex);
} }
/* /*
* If the entry is not yet allocated, allocate one. The lock is * If the entry is not yet allocated, allocate one. The mutex is
* needed so that the state of pt_softc[] arrat is consistant * needed so that the state of pt_softc[] array is consistant
* should it be longened above. Though we might use shared lock * in case it has been longened above.
* here and use
*
*/ */
if (!pt_softc[minor(dev)]) { if (!pt_softc[minor(dev)]) {
if (!locked) { MALLOC(pti, struct pt_softc *, sizeof(struct pt_softc),
lockmgr(&pt_softc_lock, LK_EXCLUSIVE, NULL); M_DEVBUF, M_WAITOK);
locked = 1;
} pti->pt_tty = ttymalloc();
simple_lock(&pt_softc_mutex);
/* /*
* Check the entry again - the entry might have been * Check the entry again - it might have been
* added while we were waiting for lock. * added while we were waiting for mutex.
*/ */
if (!pt_softc[minor(dev)]) { if (!pt_softc[minor(dev)]) {
MALLOC(pti, struct pt_softc *, sizeof(struct pt_softc),
M_DEVBUF, M_WAITOK);
pti->pt_tty = ttymalloc();
tty_attach(pti->pt_tty); tty_attach(pti->pt_tty);
pt_softc[minor(dev)] = pti; pt_softc[minor(dev)] = pti;
} else {
ttyfree(pti->pt_tty);
FREE(pti, M_DEVBUF);
} }
simple_unlock(&pt_softc_mutex);
} }
if (locked)
lockmgr(&pt_softc_lock, LK_RELEASE, NULL);
return (0); return (0);
} }
/*
* Set maxpty in thread-safe way. Returns 0 in case of error, otherwise
* new value of maxptys.
*/
int
pty_maxptys(newmax, set)
int newmax, set;
{
if (!set)
return (maxptys);
/* the value cannot be set to value lower than current number of ptys */
if (newmax < npty)
return (0);
/* can proceed immediatelly if bigger than current maximum */
if (newmax > maxptys) {
maxptys = newmax;
return (maxptys);
}
/*
* We have to grab the pt_softc lock, so that we would pick correct
* value of npty (might be modified in check_pty()).
*/
simple_lock(&pt_softc_mutex);
if (newmax > npty)
maxptys = newmax;
simple_unlock(&pt_softc_mutex);
return (maxptys);
}
/* /*
* Establish n (or default if n is 1) ptys in the system. * Establish n (or default if n is 1) ptys in the system.
*/ */
@ -214,8 +261,6 @@ ptyattach(n)
n = DEFAULT_NPTYS; n = DEFAULT_NPTYS;
pt_softc = ptyarralloc(n); pt_softc = ptyarralloc(n);
npty = n; npty = n;
lockinit(&pt_softc_lock, PWAIT, "ptyarrlk", 0, 0);
} }
/*ARGSUSED*/ /*ARGSUSED*/