diff options
author | Jamey Sharp <jamey@minilop.net> | 2011-11-20 03:21:58 -0800 |
---|---|---|
committer | Jamey Sharp <jamey@minilop.net> | 2011-11-20 03:21:58 -0800 |
commit | 8fd86ed43310863d7c3321c007d9cf6419b8c120 (patch) | |
tree | 8936d2e6e896996b8d48fbf81b0cd95bff0ea29b | |
parent | c70ce992a358e22f8c69b35b64f35ee2f8eaa47c (diff) |
Reset only what the protocol requires, instead of full regeneration.no-regen
It's difficult to get regeneration correct in all the drivers,
extensions, and everywhere else it's currently required--and there's no
significant advantage to doing full regeneration. So instead, make DIX
reset exactly the things required by the protocol specification, and set
serverGeneration to a constant 1.
Eliminating all the ugly code that's conditional on serverGeneration is
left as a later exercise. This patch should simply improve reliability
when the server resets.
Signed-off-by: Jamey Sharp <jamey@minilop.net>
-rw-r--r-- | dix/atom.c | 30 | ||||
-rw-r--r-- | dix/devices.c | 22 | ||||
-rw-r--r-- | dix/globals.c | 1 | ||||
-rw-r--r-- | dix/main.c | 372 | ||||
-rw-r--r-- | dix/property.c | 21 | ||||
-rw-r--r-- | dix/resource.c | 3 | ||||
-rw-r--r-- | dix/window.c | 13 | ||||
-rw-r--r-- | include/dix.h | 7 | ||||
-rw-r--r-- | include/misc.h | 2 | ||||
-rw-r--r-- | include/property.h | 2 | ||||
-rw-r--r-- | include/propertyst.h | 1 | ||||
-rw-r--r-- | include/window.h | 3 |
12 files changed, 298 insertions, 179 deletions
diff --git a/dix/atom.c b/dix/atom.c index 88b40db65..5eb1d55c4 100644 --- a/dix/atom.c +++ b/dix/atom.c @@ -68,6 +68,7 @@ typedef struct _Node { } NodeRec, *NodePtr; static Atom lastAtom = None; +static Atom lastServerAtom = None; static NodePtr atomRoot = NULL; static unsigned long tableLength; static NodePtr *nodeTable; @@ -201,6 +202,7 @@ FreeAllAtoms(void) free(nodeTable); nodeTable = NULL; lastAtom = None; + lastServerAtom = None; } void @@ -216,3 +218,31 @@ InitAtoms(void) if (lastAtom != XA_LAST_PREDEFINED) AtomError(); } + +void +SaveServerAtoms(void) +{ + lastServerAtom = lastAtom; +} + +static void +ResetAtom(NodePtr *patom) +{ + if (!*patom) + return; + if ((*patom)->a > lastServerAtom) + { + FreeAtom(*patom); + *patom = NULL; + return; + } + ResetAtom(&(*patom)->left); + ResetAtom(&(*patom)->right); +} + +void +ResetAtoms(void) +{ + lastAtom = lastServerAtom; + ResetAtom(&atomRoot); +} diff --git a/dix/devices.c b/dix/devices.c index da817a8af..7d91416a1 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -2645,3 +2645,25 @@ void valuator_set_mode(DeviceIntPtr dev, int axis, int mode) dev->valuator->axes[i].mode = mode; } } + +void ResetInput(void) +{ + BITS32 mask = KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration | KBAutoRepeatMode; + XID attrs[] = { -1, -1, -1, -1, AutoRepeatModeDefault }; + DeviceIntPtr dev; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + /* TODO: reset keyboard and pointer mappings */ + if (dev->focus) + { + dev->focus->win = PointerRootWin; + dev->focus->revert = None; + dev->focus->time = currentTime; + dev->focus->traceGood = 0; + } + if (dev->kbdfeed) + DoChangeKeyboardControl(serverClient, dev, attrs, mask); + if (dev->ptrfeed) + dev->ptrfeed->ctrl = defaultPointerControl; + } +} diff --git a/dix/globals.c b/dix/globals.c index 0a6b17085..28f9dbd12 100644 --- a/dix/globals.c +++ b/dix/globals.c @@ -84,7 +84,6 @@ int currentMaxClients; /* current size of clients array */ long maxBigRequestSize = MAX_BIG_REQUEST_SIZE; unsigned long globalSerialNumber = 0; -unsigned long serverGeneration = 0; /* these next four are initialized in main.c */ CARD32 ScreenSaverTime; diff --git a/dix/main.c b/dix/main.c index 16575ceba..745fe050a 100644 --- a/dix/main.c +++ b/dix/main.c @@ -132,7 +132,7 @@ int dix_main(int argc, char *argv[], char *envp[]) int main(int argc, char *argv[], char *envp[]) #endif { - int i; + int i; HWEventQueueType alwaysCheckForInput[2]; display = "0"; @@ -149,211 +149,239 @@ int main(int argc, char *argv[], char *envp[]) alwaysCheckForInput[0] = 0; alwaysCheckForInput[1] = 1; - while(1) - { - serverGeneration++; - ScreenSaverTime = defaultScreenSaverTime; - ScreenSaverInterval = defaultScreenSaverInterval; - ScreenSaverBlanking = defaultScreenSaverBlanking; - ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + + ScreenSaverTime = defaultScreenSaverTime; + ScreenSaverInterval = defaultScreenSaverInterval; + ScreenSaverBlanking = defaultScreenSaverBlanking; + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; #ifdef DPMSExtension - DPMSStandbyTime = DPMSSuspendTime = DPMSOffTime = ScreenSaverTime; - DPMSEnabled = TRUE; - DPMSPowerLevel = 0; + DPMSStandbyTime = DPMSSuspendTime = DPMSOffTime = ScreenSaverTime; + DPMSEnabled = TRUE; + DPMSPowerLevel = 0; #endif - InitBlockAndWakeupHandlers(); - /* Perform any operating system dependent initializations you'd like */ - OsInit(); - if(serverGeneration == 1) - { - CreateWellKnownSockets(); - for (i=1; i<MAXCLIENTS; i++) - clients[i] = NullClient; - serverClient = calloc(sizeof(ClientRec), 1); - if (!serverClient) - FatalError("couldn't create server client"); - InitClient(serverClient, 0, (pointer)NULL); - } - else - ResetWellKnownSockets (); - clients[0] = serverClient; - currentMaxClients = 1; - - /* Initialize privates before first allocation */ - dixResetPrivates(); - - /* Initialize server client devPrivates, to be reallocated as - * more client privates are registered - */ - if (!dixAllocatePrivates(&serverClient->devPrivates, PRIVATE_CLIENT)) - FatalError("failed to create server client privates"); - - if (!InitClientResources(serverClient)) /* for root resources */ - FatalError("couldn't init server resources"); - - SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); - screenInfo.numScreens = 0; - - InitAtoms(); - InitEvents(); - InitSelections(); - InitGlyphCaching(); - dixResetRegistry(); - ResetFontPrivateIndex(); - InitCallbackManager(); - InitOutput(&screenInfo, argc, argv); - - if (screenInfo.numScreens < 1) - FatalError("no screens found"); - InitExtensions(argc, argv); - - for (i = 0; i < screenInfo.numScreens; i++) - { - ScreenPtr pScreen = screenInfo.screens[i]; - if (!CreateScratchPixmapsForScreen(i)) - FatalError("failed to create scratch pixmaps"); - if (pScreen->CreateScreenResources && - !(*pScreen->CreateScreenResources)(pScreen)) - FatalError("failed to create screen resources"); - if (!CreateGCperDepth(i)) - FatalError("failed to create scratch GCs"); - if (!CreateDefaultStipple(i)) - FatalError("failed to create default stipple"); - if (!CreateRootWindow(pScreen)) - FatalError("failed to create root window"); - } - - InitFonts(); - if (SetDefaultFontPath(defaultFontPath) != Success) { - ErrorF("[dix] failed to set default font path '%s'", defaultFontPath); - } - if (!SetDefaultFont(defaultTextFont)) { - FatalError("could not open default font '%s'", defaultTextFont); - } - - if (!(rootCursor = CreateRootCursor(NULL, 0))) { - FatalError("could not open default cursor font '%s'", - defaultCursorFont); - } + InitBlockAndWakeupHandlers(); + /* Perform any operating system dependent initializations you'd like */ + OsInit(); + CreateWellKnownSockets(); + + for (i=1; i<MAXCLIENTS; i++) + clients[i] = NullClient; + serverClient = calloc(sizeof(ClientRec), 1); + if (!serverClient) + FatalError("couldn't create server client"); + InitClient(serverClient, 0, (pointer)NULL); + clients[0] = serverClient; + currentMaxClients = 1; + + /* Initialize privates before first allocation */ + dixResetPrivates(); + + /* Initialize server client devPrivates, to be reallocated as + * more client privates are registered + */ + if (!dixAllocatePrivates(&serverClient->devPrivates, PRIVATE_CLIENT)) + FatalError("failed to create server client privates"); + + if (!InitClientResources(serverClient)) /* for root resources */ + FatalError("couldn't init server resources"); + + SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); + screenInfo.numScreens = 0; + + InitAtoms(); + InitEvents(); + InitSelections(); + InitGlyphCaching(); + dixResetRegistry(); + ResetFontPrivateIndex(); + InitCallbackManager(); + InitOutput(&screenInfo, argc, argv); + + if (screenInfo.numScreens < 1) + FatalError("no screens found"); + InitExtensions(argc, argv); + + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + if (!CreateScratchPixmapsForScreen(i)) + FatalError("failed to create scratch pixmaps"); + if (pScreen->CreateScreenResources && + !(*pScreen->CreateScreenResources)(pScreen)) + FatalError("failed to create screen resources"); + if (!CreateGCperDepth(i)) + FatalError("failed to create scratch GCs"); + if (!CreateDefaultStipple(i)) + FatalError("failed to create default stipple"); + if (!CreateRootWindow(pScreen)) + FatalError("failed to create root window"); + } + + InitFonts(); + if (SetDefaultFontPath(defaultFontPath) != Success) { + ErrorF("[dix] failed to set default font path '%s'", defaultFontPath); + } + if (!SetDefaultFont(defaultTextFont)) { + FatalError("could not open default font '%s'", defaultTextFont); + } + + if (!(rootCursor = CreateRootCursor(NULL, 0))) { + FatalError("could not open default cursor font '%s'", + defaultCursorFont); + } #ifdef DPMSExtension - /* check all screens, looking for DPMS Capabilities */ - DPMSCapableFlag = DPMSSupported(); - if (!DPMSCapableFlag) - DPMSEnabled = FALSE; + /* check all screens, looking for DPMS Capabilities */ + DPMSCapableFlag = DPMSSupported(); + if (!DPMSCapableFlag) + DPMSEnabled = FALSE; #endif #ifdef PANORAMIX - /* - * Consolidate window and colourmap information for each screen - */ - if (!noPanoramiXExtension) - PanoramiXConsolidate(); + /* + * Consolidate window and colourmap information for each screen + */ + if (!noPanoramiXExtension) + PanoramiXConsolidate(); #endif - for (i = 0; i < screenInfo.numScreens; i++) - InitRootWindow(screenInfo.screens[i]->root); + for (i = 0; i < screenInfo.numScreens; i++) + InitRootWindow(screenInfo.screens[i]->root); - InitCoreDevices(); - InitInput(argc, argv); - InitAndStartDevices(); - ReserveClientIds(serverClient); + InitCoreDevices(); + InitInput(argc, argv); + InitAndStartDevices(); + ReserveClientIds(serverClient); - dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); #ifdef PANORAMIX - if (!noPanoramiXExtension) { - if (!PanoramiXCreateConnectionBlock()) { - FatalError("could not create connection block info"); - } - } else -#endif - { - if (!CreateConnectionBlock()) { - FatalError("could not create connection block info"); - } - } - -#ifdef XQUARTZ - /* Let the other threads know the server is done with its init */ - pthread_mutex_lock(&serverRunningMutex); - serverRunning = TRUE; - pthread_cond_broadcast(&serverRunningCond); - pthread_mutex_unlock(&serverRunningMutex); + if (!noPanoramiXExtension) { + if (!PanoramiXCreateConnectionBlock()) { + FatalError("could not create connection block info"); + } + } else #endif - - NotifyParentProcess(); + { + if (!CreateConnectionBlock()) { + FatalError("could not create connection block info"); + } + } - Dispatch(); + SaveServerAtoms(); #ifdef XQUARTZ - /* Let the other threads know the server is no longer running */ - pthread_mutex_lock(&serverRunningMutex); - serverRunning = FALSE; - pthread_mutex_unlock(&serverRunningMutex); + /* Let the other threads know the server is done with its init */ + pthread_mutex_lock(&serverRunningMutex); + serverRunning = TRUE; + pthread_cond_broadcast(&serverRunningCond); + pthread_mutex_unlock(&serverRunningMutex); #endif - UndisplayDevices(); - - /* Now free up whatever must be freed */ - if (screenIsSaved == SCREEN_SAVER_ON) - dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); - FreeScreenSaverTimer(); - CloseDownExtensions(); + NotifyParentProcess(); + while ((dispatchException & DE_TERMINATE) == 0) + { + Dispatch(); + + /* As specified in "X Window System Protocol" chapter 10, + * "Connection Close": + * + * At every transition to the state of having no connections as + * a result of a connection closing with a Destroy close-down + * mode, the server resets its state as if it had just been + * started. */ + + /* - This starts by destroying all lingering resources from + * clients that have terminated in RetainPermanent or + * RetainTemporary mode. */ #ifdef PANORAMIX - { - Bool remember_it = noPanoramiXExtension; - noPanoramiXExtension = TRUE; - FreeAllResources(); - noPanoramiXExtension = remember_it; - } + { + Bool remember_it = noPanoramiXExtension; + noPanoramiXExtension = TRUE; + FreeAllResources(); + noPanoramiXExtension = remember_it; + } #else - FreeAllResources(); + FreeAllResources(); #endif - CloseInput(); + /* - It additionally includes deleting all but the predefined + * atom identifiers, */ + ResetAtoms(); + + for (i = 0; i < screenInfo.numScreens; i++) + { + /* - deleting all properties on all root windows, */ + ResetProperties(screenInfo.screens[i]->root); + + /* - restoring the standard root tiles and cursors, */ + ResetRootWindow(screenInfo.screens[i]->root); + } + + /* - resetting the access control list, */ + ResetWellKnownSockets(); - for (i = 0; i < screenInfo.numScreens; i++) - screenInfo.screens[i]->root = NullWindow; - CloseDownDevices(); - CloseDownEvents(); + /* - restoring the default font path, */ + if (SetDefaultFontPath(defaultFontPath) != Success) + ErrorF("[dix] failed to set default font path '%s'", defaultFontPath); - for (i = screenInfo.numScreens - 1; i >= 0; i--) - { - FreeScratchPixmapsForScreen(i); - FreeGCperDepth(i); - FreeDefaultStipple(i); - (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); - dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN); - free(screenInfo.screens[i]); - screenInfo.numScreens = i; - } + /* - resetting all device maps and attributes (key click, bell + * volume, acceleration), + * - and restoring the input focus to state PointerRoot. */ + ResetInput(); + } - ReleaseClientIds(serverClient); - dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); - serverClient->devPrivates = NULL; +#ifdef XQUARTZ + /* Let the other threads know the server is no longer running */ + pthread_mutex_lock(&serverRunningMutex); + serverRunning = FALSE; + pthread_mutex_unlock(&serverRunningMutex); +#endif - FreeFonts(); + UndisplayDevices(); - FreeAuditTimer(); + /* Now free up whatever must be freed */ + if (screenIsSaved == SCREEN_SAVER_ON) + dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); + FreeScreenSaverTimer(); + CloseDownExtensions(); - if (dispatchException & DE_TERMINATE) - { - CloseWellKnownConnections(); - } + FreeClientResources(serverClient); - OsCleanup((dispatchException & DE_TERMINATE) != 0); + CloseInput(); - if (dispatchException & DE_TERMINATE) - { - ddxGiveUp(EXIT_NO_ERROR); - break; - } + for (i = 0; i < screenInfo.numScreens; i++) + screenInfo.screens[i]->root = NullWindow; + CloseDownDevices(); + CloseDownEvents(); - free(ConnectionInfo); - ConnectionInfo = NULL; + for (i = screenInfo.numScreens - 1; i >= 0; i--) + { + FreeScratchPixmapsForScreen(i); + FreeGCperDepth(i); + FreeDefaultStipple(i); + (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); + dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN); + free(screenInfo.screens[i]); + screenInfo.numScreens = i; } + + ReleaseClientIds(serverClient); + dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); + serverClient->devPrivates = NULL; + + FreeFonts(); + + FreeAuditTimer(); + + CloseWellKnownConnections(); + + OsCleanup(TRUE); + + free(ConnectionInfo); + + ddxGiveUp(EXIT_NO_ERROR); return 0; } diff --git a/dix/property.c b/dix/property.c index a1ae5305d..87b8fe3c6 100644 --- a/dix/property.c +++ b/dix/property.c @@ -284,6 +284,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, pProp->format = format; pProp->data = data; pProp->size = len; + pProp->retain = (pClient == serverClient); rc = XaceHookPropertyAccess(pClient, pWin, &pProp, DixCreateAccess|DixWriteAccess); if (rc != Success) { @@ -429,6 +430,26 @@ DeleteAllWindowProperties(WindowPtr pWin) pWin->optional->userProps = NULL; } +void +ResetProperties(WindowPtr pWin) +{ + PropertyPtr tmp, *pProp; + if (!pWin->optional) + return; + + for (pProp = &pWin->optional->userProps; (tmp = *pProp); ) + { + if (tmp->retain && ValidAtom(tmp->propertyName) && ValidAtom(tmp->type)) + { + pProp = &tmp->next; + continue; + } + *pProp = tmp->next; + free(tmp->data); + dixFreeObjectWithPrivates(tmp, PRIVATE_PROPERTY); + } +} + static int NullPropertyReply( ClientPtr client, diff --git a/dix/resource.c b/dix/resource.c index eb9f0492a..efe196459 100644 --- a/dix/resource.c +++ b/dix/resource.c @@ -863,7 +863,8 @@ FreeAllResources(void) { int i; - for (i = currentMaxClients; --i >= 0; ) + /* don't free serverClient's resources */ + for (i = currentMaxClients; --i > 0; ) { if (clientTable[i].buckets) FreeClientResources(clients[i]); diff --git a/dix/window.c b/dix/window.c index c87020dff..987bb3327 100644 --- a/dix/window.c +++ b/dix/window.c @@ -543,16 +543,21 @@ void InitRootWindow(WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; - int mask = CWBackPixmap | CWBackingStore | CWCursor; - XID attrs[] = { None, defaultBackingStore, None }; - if (!(*pScreen->CreateWindow)(pWin)) return; /* XXX */ (*pScreen->PositionWindow)(pWin, 0, 0); - ChangeWindowAttributes(pWin, mask, attrs, serverClient); + ResetRootWindow(pWin); MapWindow(pWin, serverClient); } +void +ResetRootWindow(WindowPtr pWin) +{ + int mask = CWBackPixmap | CWBackingStore | CWCursor; + XID attrs[] = { None, defaultBackingStore, None }; + ChangeWindowAttributes(pWin, mask, attrs, serverClient); +} + /* Set the region to the intersection of the rectangle and the * window's winSize. The window is typically the parent of the * window from which the region came. diff --git a/include/dix.h b/include/dix.h index 34661f3b6..7a931c3ac 100644 --- a/include/dix.h +++ b/include/dix.h @@ -306,12 +306,19 @@ extern _X_EXPORT void FreeAllAtoms(void); extern _X_EXPORT void InitAtoms(void); +extern void SaveServerAtoms(void); +extern void ResetAtoms(void); + /* main.c */ extern _X_EXPORT void SetVendorRelease(int release); extern _X_EXPORT void SetVendorString(char *string); +/* devices.c */ + +extern void ResetInput(void); + /* events.c */ extern void SetMaskForEvent( diff --git a/include/misc.h b/include/misc.h index dc039113d..10970506f 100644 --- a/include/misc.h +++ b/include/misc.h @@ -357,6 +357,6 @@ typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ #endif extern _X_EXPORT unsigned long globalSerialNumber; -extern _X_EXPORT unsigned long serverGeneration; +#define serverGeneration 1 #endif /* MISC_H */ diff --git a/include/property.h b/include/property.h index 075eb4a0d..01379ed11 100644 --- a/include/property.h +++ b/include/property.h @@ -88,4 +88,6 @@ extern _X_EXPORT int DeleteProperty( extern _X_EXPORT void DeleteAllWindowProperties( WindowPtr /*pWin*/); +extern void ResetProperties(WindowPtr /*pWin*/); + #endif /* PROPERTY_H */ diff --git a/include/propertyst.h b/include/propertyst.h index 1edd11d5d..73ccce65d 100644 --- a/include/propertyst.h +++ b/include/propertyst.h @@ -61,6 +61,7 @@ typedef struct _Property { uint32_t format; /* format of data for swapping - 8,16,32 */ uint32_t size; /* size of data in (format/8) bytes */ pointer data; /* private to client */ + unsigned int retain : 1; /* should this property be retained across server reset? */ PrivateRec *devPrivates; } PropertyRec; diff --git a/include/window.h b/include/window.h index e13598b88..1bb51e7ce 100644 --- a/include/window.h +++ b/include/window.h @@ -93,6 +93,9 @@ extern _X_EXPORT Bool CreateRootWindow( extern _X_EXPORT void InitRootWindow( WindowPtr /*pWin*/); +extern void ResetRootWindow( + WindowPtr /*pWin*/); + typedef WindowPtr (* RealChildHeadProc) (WindowPtr pWin); extern _X_EXPORT void RegisterRealChildHeadProc (RealChildHeadProc proc); |