configurable maximum number of clients
Make the maximum number of clients user configurable, either from the command line or from xorg.conf This patch works by using the MAXCLIENTS (raised to 512) as the maximum allowed number of clients, but allowing the actual limit to be set by the user to a lower value (keeping the default of 256). There is a limit size of 29 bits to be used to store both the client ID and the X resources ID, so by reducing the number of clients allowed to connect to the X server, the user can increase the number of X resources per client or vice-versa. Parts of this patch are based on a similar patch from Adam Jackson <ajax@redhat.com> This now requires at least xproto 7.0.28 Signed-off-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
7ecdfbf0af
commit
d206c240c0
|
@ -400,7 +400,7 @@ case $host_os in
|
|||
AC_DEFINE(CSRG_BASED, 1, [System is BSD-like])
|
||||
;;
|
||||
cygwin*|mingw*)
|
||||
CFLAGS="$CFLAGS -DFD_SETSIZE=256"
|
||||
CFLAGS="$CFLAGS -DFD_SETSIZE=512"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -771,7 +771,7 @@ APPLEWMPROTO="applewmproto >= 1.4"
|
|||
LIBXSHMFENCE="xshmfence >= 1.1"
|
||||
|
||||
dnl Required modules
|
||||
XPROTO="xproto >= 7.0.26"
|
||||
XPROTO="xproto >= 7.0.28"
|
||||
RANDRPROTO="randrproto >= 1.5.0"
|
||||
RENDERPROTO="renderproto >= 0.11"
|
||||
XEXTPROTO="xextproto >= 7.2.99.901"
|
||||
|
|
|
@ -252,7 +252,7 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
|
|||
|
||||
size = pVisual->ColormapEntries;
|
||||
sizebytes = (size * sizeof(Entry)) +
|
||||
(MAXCLIENTS * sizeof(Pixel *)) + (MAXCLIENTS * sizeof(int));
|
||||
(LimitClients * sizeof(Pixel *)) + (LimitClients * sizeof(int));
|
||||
if ((class | DynamicClass) == DirectColor)
|
||||
sizebytes *= 3;
|
||||
sizebytes += sizeof(ColormapRec);
|
||||
|
@ -277,7 +277,7 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
|
|||
sizebytes = size * sizeof(Entry);
|
||||
pmap->clientPixelsRed = (Pixel **) ((char *) pmap->red + sizebytes);
|
||||
pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
|
||||
(MAXCLIENTS * sizeof(Pixel *)));
|
||||
(LimitClients * sizeof(Pixel *)));
|
||||
pmap->mid = mid;
|
||||
pmap->flags = 0; /* start out with all flags clear */
|
||||
if (mid == pScreen->defColormap)
|
||||
|
@ -289,8 +289,8 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
|
|||
size = NUMRED(pVisual);
|
||||
pmap->freeRed = size;
|
||||
memset((char *) pmap->red, 0, (int) sizebytes);
|
||||
memset((char *) pmap->numPixelsRed, 0, MAXCLIENTS * sizeof(int));
|
||||
for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
|
||||
memset((char *) pmap->numPixelsRed, 0, LimitClients * sizeof(int));
|
||||
for (pptr = &pmap->clientPixelsRed[LimitClients];
|
||||
--pptr >= pmap->clientPixelsRed;)
|
||||
*pptr = (Pixel *) NULL;
|
||||
if (alloc == AllocAll) {
|
||||
|
@ -313,26 +313,26 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
|
|||
if ((class | DynamicClass) == DirectColor) {
|
||||
pmap->freeGreen = NUMGREEN(pVisual);
|
||||
pmap->green = (EntryPtr) ((char *) pmap->numPixelsRed +
|
||||
(MAXCLIENTS * sizeof(int)));
|
||||
(LimitClients * sizeof(int)));
|
||||
pmap->clientPixelsGreen = (Pixel **) ((char *) pmap->green + sizebytes);
|
||||
pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
|
||||
(MAXCLIENTS * sizeof(Pixel *)));
|
||||
(LimitClients * sizeof(Pixel *)));
|
||||
pmap->freeBlue = NUMBLUE(pVisual);
|
||||
pmap->blue = (EntryPtr) ((char *) pmap->numPixelsGreen +
|
||||
(MAXCLIENTS * sizeof(int)));
|
||||
(LimitClients * sizeof(int)));
|
||||
pmap->clientPixelsBlue = (Pixel **) ((char *) pmap->blue + sizebytes);
|
||||
pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
|
||||
(MAXCLIENTS * sizeof(Pixel *)));
|
||||
(LimitClients * sizeof(Pixel *)));
|
||||
|
||||
memset((char *) pmap->green, 0, (int) sizebytes);
|
||||
memset((char *) pmap->blue, 0, (int) sizebytes);
|
||||
|
||||
memmove((char *) pmap->clientPixelsGreen,
|
||||
(char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
|
||||
(char *) pmap->clientPixelsRed, LimitClients * sizeof(Pixel *));
|
||||
memmove((char *) pmap->clientPixelsBlue,
|
||||
(char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
|
||||
memset((char *) pmap->numPixelsGreen, 0, MAXCLIENTS * sizeof(int));
|
||||
memset((char *) pmap->numPixelsBlue, 0, MAXCLIENTS * sizeof(int));
|
||||
(char *) pmap->clientPixelsRed, LimitClients * sizeof(Pixel *));
|
||||
memset((char *) pmap->numPixelsGreen, 0, LimitClients * sizeof(int));
|
||||
memset((char *) pmap->numPixelsBlue, 0, LimitClients * sizeof(int));
|
||||
|
||||
/* If every cell is allocated, mark its refcnt */
|
||||
if (alloc == AllocAll) {
|
||||
|
@ -416,7 +416,7 @@ FreeColormap(void *value, XID mid)
|
|||
(*pmap->pScreen->DestroyColormap) (pmap);
|
||||
|
||||
if (pmap->clientPixelsRed) {
|
||||
for (i = 0; i < MAXCLIENTS; i++)
|
||||
for (i = 0; i < LimitClients; i++)
|
||||
free(pmap->clientPixelsRed[i]);
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ FreeColormap(void *value, XID mid)
|
|||
}
|
||||
}
|
||||
if ((pmap->class | DynamicClass) == DirectColor) {
|
||||
for (i = 0; i < MAXCLIENTS; i++) {
|
||||
for (i = 0; i < LimitClients; i++) {
|
||||
free(pmap->clientPixelsGreen[i]);
|
||||
free(pmap->clientPixelsBlue[i]);
|
||||
}
|
||||
|
|
|
@ -3484,7 +3484,7 @@ NextAvailableClient(void *ospriv)
|
|||
xReq data;
|
||||
|
||||
i = nextFreeClientID;
|
||||
if (i == MAXCLIENTS)
|
||||
if (i == LimitClients)
|
||||
return (ClientPtr) NULL;
|
||||
clients[i] = client =
|
||||
dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
|
||||
|
@ -3504,7 +3504,7 @@ NextAvailableClient(void *ospriv)
|
|||
}
|
||||
if (i == currentMaxClients)
|
||||
currentMaxClients++;
|
||||
while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
|
||||
while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
|
||||
nextFreeClientID++;
|
||||
|
||||
/* Enable client ID tracking. This must be done before
|
||||
|
|
|
@ -165,7 +165,7 @@ dix_main(int argc, char *argv[], char *envp[])
|
|||
OsInit();
|
||||
if (serverGeneration == 1) {
|
||||
CreateWellKnownSockets();
|
||||
for (i = 1; i < MAXCLIENTS; i++)
|
||||
for (i = 1; i < LimitClients; i++)
|
||||
clients[i] = NullClient;
|
||||
serverClient = calloc(sizeof(ClientRec), 1);
|
||||
if (!serverClient)
|
||||
|
|
|
@ -600,6 +600,29 @@ CreateNewResourceClass(void)
|
|||
|
||||
static ClientResourceRec clientTable[MAXCLIENTS];
|
||||
|
||||
static unsigned int
|
||||
ilog2(int val)
|
||||
{
|
||||
int bits;
|
||||
|
||||
if (val <= 0)
|
||||
return 0;
|
||||
for (bits = 0; val != 0; bits++)
|
||||
val >>= 1;
|
||||
return bits - 1;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* ResourceClientBits
|
||||
* Returns the client bit offset in the client + resources ID field
|
||||
*****************/
|
||||
|
||||
unsigned int
|
||||
ResourceClientBits(void)
|
||||
{
|
||||
return (ilog2(LimitClients));
|
||||
}
|
||||
|
||||
/*****************
|
||||
* InitClientResources
|
||||
* When a new client is created, call this to allocate space
|
||||
|
@ -883,7 +906,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType)
|
|||
int *eltptr;
|
||||
int elements;
|
||||
|
||||
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
|
||||
if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
|
||||
head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
|
||||
eltptr = &clientTable[cid].elements;
|
||||
|
||||
|
@ -917,7 +940,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
|
|||
ResourcePtr res;
|
||||
ResourcePtr *prev, *head;
|
||||
|
||||
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
|
||||
if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
|
||||
head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
|
||||
|
||||
prev = head;
|
||||
|
@ -952,7 +975,7 @@ ChangeResourceValue(XID id, RESTYPE rtype, void *value)
|
|||
int cid;
|
||||
ResourcePtr res;
|
||||
|
||||
if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
|
||||
if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
|
||||
res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
|
||||
|
||||
for (; res; res = res->next)
|
||||
|
@ -1190,7 +1213,7 @@ dixLookupResourceByType(void **result, XID id, RESTYPE rtype,
|
|||
if ((rtype & TypeMask) > lastResourceType)
|
||||
return BadImplementation;
|
||||
|
||||
if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
|
||||
if ((cid < LimitClients) && clientTable[cid].buckets) {
|
||||
res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
|
||||
|
||||
for (; res; res = res->next)
|
||||
|
@ -1223,7 +1246,7 @@ dixLookupResourceByClass(void **result, XID id, RESTYPE rclass,
|
|||
|
||||
*result = NULL;
|
||||
|
||||
if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
|
||||
if ((cid < LimitClients) && clientTable[cid].buckets) {
|
||||
res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
|
||||
|
||||
for (; res; res = res->next)
|
||||
|
|
|
@ -347,7 +347,7 @@ GlxExtensionInit(void)
|
|||
/*
|
||||
** Initialize table of client state. There is never a client 0.
|
||||
*/
|
||||
for (i = 1; i <= MAXCLIENTS; i++) {
|
||||
for (i = 1; i <= LimitClients; i++) {
|
||||
__glXClients[i] = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -703,6 +703,7 @@ typedef enum {
|
|||
FLAG_DRI2,
|
||||
FLAG_USE_SIGIO,
|
||||
FLAG_AUTO_ADD_GPU,
|
||||
FLAG_MAX_CLIENTS,
|
||||
} FlagValues;
|
||||
|
||||
/**
|
||||
|
@ -762,6 +763,8 @@ static OptionInfoRec FlagOptions[] = {
|
|||
{0}, FALSE},
|
||||
{FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
|
||||
{0}, FALSE},
|
||||
{FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
|
||||
{0}, FALSE },
|
||||
{-1, NULL, OPTV_NONE,
|
||||
{0}, FALSE},
|
||||
};
|
||||
|
@ -1052,6 +1055,19 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
|
|||
xf86Info.dri2From = X_CONFIG;
|
||||
}
|
||||
#endif
|
||||
|
||||
from = X_DEFAULT;
|
||||
if (LimitClients != LIMITCLIENTS)
|
||||
from = X_CMDLINE;
|
||||
i = -1;
|
||||
if (xf86GetOptValInteger(FlagOptions, FLAG_MAX_CLIENTS, &i)) {
|
||||
if (i != 64 && i != 128 && i != 256 && i != 512)
|
||||
ErrorF("MaxClients must be one of 64, 128, 256 or 512\n");
|
||||
from = X_CONFIG;
|
||||
LimitClients = i;
|
||||
}
|
||||
xf86Msg(from, "Max clients allowed: %i, resource mask: 0x%x\n",
|
||||
LimitClients, RESOURCE_ID_MASK);
|
||||
}
|
||||
|
||||
Bool
|
||||
|
|
|
@ -621,6 +621,10 @@ It is only enabled for screens that have the
|
|||
.B \*qDPMS\*q
|
||||
option set (see the MONITOR section below).
|
||||
.TP 7
|
||||
.BI "Option \*qMaxClients\*q \*q" integer \*q
|
||||
Set the maximum number of clients allowed to connect to the X server.
|
||||
Acceptable values are 64, 128, 256 or 512.
|
||||
.TP 7
|
||||
.BI "Option \*qPixmap\*q \*q" bpp \*q
|
||||
This sets the pixmap format to use for depth 24.
|
||||
Allowed values for
|
||||
|
|
|
@ -86,7 +86,8 @@ OF THIS SOFTWARE.
|
|||
#ifndef MAXGPUSCREENS
|
||||
#define MAXGPUSCREENS 16
|
||||
#endif
|
||||
#define MAXCLIENTS 256
|
||||
#define MAXCLIENTS 512
|
||||
#define LIMITCLIENTS 256 /* Must be a power of 2 and <= MAXCLIENTS */
|
||||
#define MAXEXTENSIONS 128
|
||||
#define MAXFORMATS 8
|
||||
#define MAXDEVICES 40 /* input devices */
|
||||
|
|
|
@ -36,6 +36,7 @@ from The Open Group.
|
|||
extern _X_EXPORT const char *defaultTextFont;
|
||||
extern _X_EXPORT const char *defaultCursorFont;
|
||||
extern _X_EXPORT int MaxClients;
|
||||
extern _X_EXPORT int LimitClients;
|
||||
extern _X_EXPORT volatile char isItTimeToYield;
|
||||
extern _X_EXPORT volatile char dispatchException;
|
||||
|
||||
|
|
|
@ -85,21 +85,10 @@ typedef uint32_t RESTYPE;
|
|||
#define RT_LASTPREDEF ((RESTYPE)9)
|
||||
#define RT_NONE ((RESTYPE)0)
|
||||
|
||||
extern unsigned int ResourceClientBits(void);
|
||||
/* bits and fields within a resource id */
|
||||
#define RESOURCE_AND_CLIENT_COUNT 29 /* 29 bits for XIDs */
|
||||
#if MAXCLIENTS == 64
|
||||
#define RESOURCE_CLIENT_BITS 6
|
||||
#endif
|
||||
#if MAXCLIENTS == 128
|
||||
#define RESOURCE_CLIENT_BITS 7
|
||||
#endif
|
||||
#if MAXCLIENTS == 256
|
||||
#define RESOURCE_CLIENT_BITS 8
|
||||
#endif
|
||||
#if MAXCLIENTS == 512
|
||||
#define RESOURCE_CLIENT_BITS 9
|
||||
#endif
|
||||
/* client field offset */
|
||||
#define RESOURCE_CLIENT_BITS ResourceClientBits() /* client field offset */
|
||||
#define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS)
|
||||
/* resource field */
|
||||
#define RESOURCE_ID_MASK ((1 << CLIENTOFFSET) - 1)
|
||||
|
|
|
@ -320,6 +320,11 @@ sets the stack space limit of the server to the specified number of kilobytes.
|
|||
A value of zero makes the stack size as large as possible. The default value
|
||||
of \-1 leaves the stack space limit unchanged.
|
||||
.TP 8
|
||||
.B \-maxclients
|
||||
.BR 64 | 128 | 256 | 512
|
||||
Set the maximum number of clients allowed to connect to the X server.
|
||||
Acceptable values are 64, 128, 256 or 512.
|
||||
.TP 8
|
||||
.B \-render
|
||||
.BR default | mono | gray | color
|
||||
sets the color allocation policy that will be used by the render extension.
|
||||
|
|
|
@ -161,9 +161,9 @@ int *ConnectionTranslation = NULL;
|
|||
*/
|
||||
|
||||
#undef MAXSOCKS
|
||||
#define MAXSOCKS 500
|
||||
#define MAXSOCKS 512
|
||||
#undef MAXSELECT
|
||||
#define MAXSELECT 500
|
||||
#define MAXSELECT 512
|
||||
|
||||
struct _ct_node {
|
||||
struct _ct_node *next;
|
||||
|
@ -299,7 +299,7 @@ InitConnectionLimits(void)
|
|||
if (lastfdesc > MAXCLIENTS) {
|
||||
lastfdesc = MAXCLIENTS;
|
||||
if (debug_conns)
|
||||
ErrorF("REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
|
||||
ErrorF("REACHED MAXIMUM CLIENTS LIMIT %d\n", LimitClients);
|
||||
}
|
||||
MaxClients = lastfdesc;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ SOFTWARE.
|
|||
|
||||
#ifndef OPEN_MAX
|
||||
#ifdef SVR4
|
||||
#define OPEN_MAX 256
|
||||
#define OPEN_MAX 512
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
#ifndef OPEN_MAX
|
||||
|
@ -75,7 +75,7 @@ SOFTWARE.
|
|||
#if !defined(WIN32)
|
||||
#define OPEN_MAX NOFILES_MAX
|
||||
#else
|
||||
#define OPEN_MAX 256
|
||||
#define OPEN_MAX 512
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -89,10 +89,10 @@ SOFTWARE.
|
|||
* like sysconf(_SC_OPEN_MAX) is not supported.
|
||||
*/
|
||||
|
||||
#if OPEN_MAX <= 256
|
||||
#if OPEN_MAX <= 512
|
||||
#define MAXSOCKS (OPEN_MAX - 1)
|
||||
#else
|
||||
#define MAXSOCKS 256
|
||||
#define MAXSOCKS 512
|
||||
#endif
|
||||
|
||||
/* MAXSELECT is the number of fds that select() can handle */
|
||||
|
|
|
@ -86,6 +86,9 @@ int limitStackSpace = -1;
|
|||
int limitNoFile = -1;
|
||||
#endif
|
||||
|
||||
/* The actual user defined max number of clients */
|
||||
int LimitClients = LIMITCLIENTS;
|
||||
|
||||
static OsSigWrapperPtr OsSigWrapper = NULL;
|
||||
|
||||
OsSigWrapperPtr
|
||||
|
|
14
os/utils.c
14
os/utils.c
|
@ -557,6 +557,7 @@ UseMsg(void)
|
|||
#ifdef LOCK_SERVER
|
||||
ErrorF("-nolock disable the locking mechanism\n");
|
||||
#endif
|
||||
ErrorF("-maxclients n set maximum number of clients (power of two)\n");
|
||||
ErrorF("-nolisten string don't listen on protocol\n");
|
||||
ErrorF("-listen string listen on protocol\n");
|
||||
ErrorF("-noreset don't reset after last client exists\n");
|
||||
|
@ -861,6 +862,19 @@ ProcessCommandLine(int argc, char *argv[])
|
|||
nolock = TRUE;
|
||||
}
|
||||
#endif
|
||||
else if ( strcmp( argv[i], "-maxclients") == 0)
|
||||
{
|
||||
if (++i < argc) {
|
||||
LimitClients = atoi(argv[i]);
|
||||
if (LimitClients != 64 &&
|
||||
LimitClients != 128 &&
|
||||
LimitClients != 256 &&
|
||||
LimitClients != 512) {
|
||||
FatalError("maxclients must be one of 64, 128, 256 or 512\n");
|
||||
}
|
||||
} else
|
||||
UseMsg();
|
||||
}
|
||||
else if (strcmp(argv[i], "-nolisten") == 0) {
|
||||
if (++i < argc) {
|
||||
if (_XSERVTransNoListen(argv[i]))
|
||||
|
|
Loading…
Reference in New Issue