1、main函数位于dix/stubmain.c
cpp
int dix_main(int argc, char *argv[], char *envp[]);
/*
A default implementation of main, which can be overridden by the DDX
*/
int
main(int argc, char *argv[], char *envp[])
{
return dix_main(argc, argv, envp);
}
dix_main()按"server generation"运行;这意味着收到 reset 时,Xorg 可以清理当前客户端与屏幕状态后重新初始化,而不必立即退出
2、dix_main函数
dix_main()
├─ InitOutput() 初始化显示子系统
│ ├─ 读取配置、探测设备、加载驱动
│ ├─ 驱动 PreInit() 确定能力、颜色格式、显示模式
│ └─ 驱动 ScreenInit() 建立屏幕和绘制基础设施
├─ InitExtensions() 注册 GLX、RANDR、RENDER 等扩展
├─ CreateScreenResources() 建立屏幕 pixmap 等资源
├─ InitInput() 初始化输入子系统
└─ Dispatch() 处理客户端请求与事件
cpp
int
dix_main(int argc, char *argv[], char *envp[])
{
int i;
HWEventQueueType alwaysCheckForInput[2];
display = "0";
InitRegions();
// 校验权限、解析参数
CheckUserParameters(argc, argv, envp);
CheckUserAuthorization();
ProcessCommandLine(argc, argv);
alwaysCheckForInput[0] = 0;
alwaysCheckForInput[1] = 1;
while (1) {
serverGeneration++;
ScreenSaverTime = defaultScreenSaverTime;
ScreenSaverInterval = defaultScreenSaverInterval;
ScreenSaverBlanking = defaultScreenSaverBlanking;
ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
InitBlockAndWakeupHandlers();
// OS 初始化并创建 X11 监听 socket
OsInit();
if (serverGeneration == 1) {
CreateWellKnownSockets();
for (i = 1; i < LimitClients; i++)
clients[i] = NullClient;
serverClient = calloc(1, sizeof(ClientRec));
if (!serverClient)
FatalError("couldn't create server client");
InitClient(serverClient, 0, (void *) NULL);
}
else
ResetWellKnownSockets();
clients[0] = serverClient;
currentMaxClients = 1;
// 初始化服务端内部 client、资源系统、Atom、事件、字体。
/* clear any existing selections */
InitSelections();
/* 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();
xfont2_init_glyph_caching();
dixResetRegistry();
InitFonts();
InitCallbackManager();
// 显示硬件抽象为一个或多个 Screen
InitOutput(&screenInfo, argc, argv);
if (screenInfo.numScreens < 1)
FatalError("no screens found");
InitExtensions(argc, argv); // 初始化 X11 扩展
for (i = 0; i < screenInfo.numGPUScreens; i++) {
ScreenPtr pScreen = screenInfo.gpuscreens[i];
if (!PixmapScreenInit(pScreen))
FatalError("failed to create screen pixmap properties");
if (pScreen->CreateScreenResources &&
!(*pScreen->CreateScreenResources) (pScreen))
FatalError("failed to create screen resources");
}
for (i = 0; i < screenInfo.numScreens; i++) {
ScreenPtr pScreen = screenInfo.screens[i];
if (!PixmapScreenInit(pScreen))
FatalError("failed to create screen pixmap properties");
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");
CallCallbacks(&RootWindowFinalizeCallback, pScreen);
}
if (SetDefaultFontPath(defaultFontPath) != Success) {
ErrorF("[dix] failed to set default font path '%s'",
defaultFontPath);
}
if (!SetDefaultFont("fixed")) {
FatalError("could not open default font");
}
if (!(rootCursor = CreateRootCursor())) {
FatalError("could not open default cursor font");
}
rootCursor = RefCursor(rootCursor);
#ifdef PANORAMIX
/*
* Consolidate window and colourmap information for each screen
*/
if (!noPanoramiXExtension)
PanoramiXConsolidate();
#endif
for (i = 0; i < screenInfo.numScreens; i++)
InitRootWindow(screenInfo.screens[i]->root);
// 初始化核心输入设备和 DDX 输入
InitCoreDevices();
InitInput(argc, argv);
InitAndStartDevices();
ReserveClientIds(serverClient);
dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
dixCloseRegistry();
#ifdef PANORAMIX
if (!noPanoramiXExtension) {
if (!PanoramiXCreateConnectionBlock()) {
FatalError("could not create connection block info");
}
}
else
#endif
{
if (!CreateConnectionBlock()) {
FatalError("could not create connection block info");
}
}
NotifyParentProcess();
InputThreadInit();
// 整个服务器的核心循环
Dispatch();
// 退出
UnrefCursor(rootCursor);
UndisplayDevices();
DisableAllDevices();
/* Now free up whatever must be freed */
if (screenIsSaved == SCREEN_SAVER_ON)
dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
FreeScreenSaverTimer();
CloseDownExtensions();
#ifdef PANORAMIX
{
Bool remember_it = noPanoramiXExtension;
noPanoramiXExtension = TRUE;
FreeAllResources();
noPanoramiXExtension = remember_it;
}
#else
FreeAllResources();
#endif
CloseInput();
InputThreadFini();
for (i = 0; i < screenInfo.numScreens; i++)
screenInfo.screens[i]->root = NullWindow;
CloseDownDevices();
CloseDownEvents();
for (i = screenInfo.numGPUScreens - 1; i >= 0; i--) {
ScreenPtr pScreen = screenInfo.gpuscreens[i];
dixFreeScreenSpecificPrivates(pScreen);
(*pScreen->CloseScreen) (pScreen);
dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
free(pScreen);
screenInfo.numGPUScreens = i;
}
for (i = screenInfo.numScreens - 1; i >= 0; i--) {
FreeGCperDepth(i);
FreeDefaultStipple(i);
dixFreeScreenSpecificPrivates(screenInfo.screens[i]);
(*screenInfo.screens[i]->CloseScreen) (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;
dixFreeRegistry();
FreeFonts();
FreeAllAtoms();
FreeAuditTimer();
DeleteCallbackManager();
ClearWorkQueue();
if (dispatchException & DE_TERMINATE) {
CloseWellKnownConnections();
}
OsCleanup((dispatchException & DE_TERMINATE) != 0);
if (dispatchException & DE_TERMINATE) {
ddxGiveUp(EXIT_NO_ERROR);
break;
}
free(ConnectionInfo);
ConnectionInfo = NULL;
}
return 0;
}
3、初始化output,位于hw/xfree86/common/xf86Init.c
配置 + 设备
↓ 加载驱动
DriverRec
↓ Probe:发现可管理的设备实例
ScrnInfoRec
↓ PreInit:确定配置和能力
配置可用的 ScrnInfoRec
↓ AddScreen + ScreenInit
ScreenRec,与 ScrnInfoRec 关联
cpp
void
InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
{
int i, j, k, scr_index;
const char **modulelist;
void **optionlist;
Bool autoconfig = FALSE;
Bool sigio_blocked = FALSE;
Bool want_hw_access = FALSE;
GDevPtr configured_device;
xf86Initialising = TRUE;
config_pre_init();
if (serverGeneration == 1) {
xf86PrintBanner();
LogPrintMarkers();
if (xf86LogFile) {
time_t t;
const char *ct;
t = time(NULL);
ct = ctime(&t);
xf86MsgVerb(xf86LogFileFrom, 0, "Log file: \"%s\", Time: %s", xf86LogFile, ct);
}
/* Read and parse the config file */
if (!xf86DoConfigure && !xf86DoShowOptions) {
switch (xf86HandleConfigFile(FALSE)) {
case CONFIG_OK:
break;
case CONFIG_PARSE_ERROR:
xf86Msg(X_ERROR, "Error parsing the config file\n");
return;
case CONFIG_NOFILE:
autoconfig = TRUE;
break;
}
}
/* Initialise the loader */
LoaderInit();
/* Tell the loader the default module search path */
LoaderSetPath(xf86ModulePath);
if (xf86Info.ignoreABI) {
LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL);
}
if (xf86DoShowOptions)
DoShowOptions();
dbus_core_init();
systemd_logind_init();
/* Do a general bus probe. This will be a PCI probe for x86 platforms */
xf86BusProbe();
if (xf86DoConfigure)
DoConfigure();
if (autoconfig) {
if (!xf86AutoConfig()) {
xf86Msg(X_ERROR, "Auto configuration failed\n");
return;
}
}
xf86OSPMClose = xf86OSPMOpen();
xf86ExtensionInit();
/* Load all modules specified explicitly in the config file */
if ((modulelist = xf86ModulelistFromConfig(&optionlist))) {
xf86LoadModules(modulelist, optionlist);
free(modulelist);
free(optionlist);
}
/* Load all driver modules specified in the config file */
/* If there aren't any specified in the config file, autoconfig them */
/* FIXME: Does not handle multiple active screen sections, but I'm not
* sure if we really want to handle that case*/
configured_device = xf86ConfigLayout.screens->screen->device;
if ((!configured_device) || (!configured_device->driver)) {
if (!autoConfigDevice(configured_device)) {
xf86Msg(X_ERROR, "Automatic driver configuration failed\n");
return;
}
}
if ((modulelist = xf86DriverlistFromConfig())) {
xf86LoadModules(modulelist, NULL);
free(modulelist);
}
/* Load all input driver modules specified in the config file. */
if ((modulelist = xf86InputDriverlistFromConfig())) {
xf86LoadModules(modulelist, NULL);
free(modulelist);
}
/*
* It is expected that xf86AddDriver()/xf86AddInputDriver will be
* called for each driver as it is loaded. Those functions save the
* module pointers for drivers.
* XXX Nothing keeps track of them for other modules.
*/
/* XXX What do we do if not all of these could be loaded? */
/*
* At this point, xf86DriverList[] is all filled in with entries for
* each of the drivers to try and xf86NumDrivers has the number of
* drivers. If there are none, return now.
*/
if (xf86NumDrivers == 0) {
xf86Msg(X_ERROR, "No drivers available.\n");
return;
}
/*
* Call each of the Identify functions and call the driverFunc to check
* if HW access is required. The Identify functions print out some
* identifying information, and anything else that might be
* needed at this early stage.
*/
for (i = 0; i < xf86NumDrivers; i++) {
xorgHWFlags flags = HW_IO;
if (xf86DriverList[i]->Identify != NULL)
xf86DriverList[i]->Identify(0);
if (xf86DriverList[i]->driverFunc)
xf86DriverList[i]->driverFunc(NULL, GET_REQUIRED_HW_INTERFACES, &flags);
if (NEED_IO_ENABLED(flags))
want_hw_access = TRUE;
/* Non-seat0 X servers should not open console */
if (!(flags & HW_SKIP_CONSOLE) && !ServerIsNotSeat0() && xf86HasTTYs())
xorgHWOpenConsole = TRUE;
}
if (xorgHWOpenConsole)
xf86OpenConsole();
else
xf86Info.dontVTSwitch = TRUE;
/* Enable full I/O access */
if (want_hw_access)
xorgHWAccess = xf86EnableIO();
if (xf86BusConfig() == FALSE)
return;
xf86PostProbe();
/*
* Sort the drivers to match the requested ordering. Using a slow
* bubble sort.
*/
for (j = 0; j < xf86NumScreens - 1; j++) {
for (i = 0; i < xf86NumScreens - j - 1; i++) {
if (xf86Screens[i + 1]->confScreen->screennum < xf86Screens[i]->confScreen->screennum) {
ScrnInfoPtr tmpScrn = xf86Screens[i + 1];
xf86Screens[i + 1] = xf86Screens[i];
xf86Screens[i] = tmpScrn;
}
}
}
/* Fix up the indexes */
for (i = 0; i < xf86NumScreens; i++) {
xf86Screens[i]->scrnIndex = i;
}
/*
* Call the driver's PreInit()'s to complete initialisation for the first
* generation.
*/
for (i = 0; i < xf86NumScreens; i++) {
xf86VGAarbiterScrnInit(xf86Screens[i]);
xf86VGAarbiterLock(xf86Screens[i]);
if (xf86Screens[i]->PreInit && xf86Screens[i]->PreInit(xf86Screens[i], 0))
xf86Screens[i]->configured = TRUE;
xf86VGAarbiterUnlock(xf86Screens[i]);
}
for (i = 0; i < xf86NumScreens; i++)
if (!xf86Screens[i]->configured)
xf86DeleteScreen(xf86Screens[i--]);
for (i = 0; i < xf86NumGPUScreens; i++) {
xf86VGAarbiterScrnInit(xf86GPUScreens[i]);
xf86VGAarbiterLock(xf86GPUScreens[i]);
if (xf86GPUScreens[i]->PreInit && xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0))
xf86GPUScreens[i]->configured = TRUE;
xf86VGAarbiterUnlock(xf86GPUScreens[i]);
}
for (i = 0; i < xf86NumGPUScreens; i++)
if (!xf86GPUScreens[i]->configured)
xf86DeleteScreen(xf86GPUScreens[i--]);
/*
* If no screens left, return now.
*/
if (xf86NumScreens == 0) {
xf86Msg(X_ERROR, "Screen(s) found, but none have a usable configuration.\n");
return;
}
/* Remove (unload) drivers that are not required */
for (i = 0; i < xf86NumDrivers; i++)
if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0)
xf86DeleteDriver(i);
/*
* At this stage we know how many screens there are.
*/
for (i = 0; i < xf86NumScreens; i++)
xf86InitViewport(xf86Screens[i]);
/*
* Collect all pixmap formats and check for conflicts at the display
* level. Should we die here? Or just delete the offending screens?
*/
for (i = 0; i < xf86NumScreens; i++) {
if (xf86Screens[i]->imageByteOrder !=
xf86Screens[0]->imageByteOrder)
FatalError("Inconsistent display bitmapBitOrder. Exiting\n");
if (xf86Screens[i]->bitmapScanlinePad !=
xf86Screens[0]->bitmapScanlinePad)
FatalError
("Inconsistent display bitmapScanlinePad. Exiting\n");
if (xf86Screens[i]->bitmapScanlineUnit !=
xf86Screens[0]->bitmapScanlineUnit)
FatalError
("Inconsistent display bitmapScanlineUnit. Exiting\n");
if (xf86Screens[i]->bitmapBitOrder !=
xf86Screens[0]->bitmapBitOrder)
FatalError("Inconsistent display bitmapBitOrder. Exiting\n");
}
/* Collect additional formats */
for (i = 0; i < xf86NumScreens; i++) {
for (j = 0; j < xf86Screens[i]->numFormats; j++) {
for (k = 0;; k++) {
if (k >= numFormats) {
if (k >= MAXFORMATS)
FatalError("Too many pixmap formats! Exiting\n");
formats[k] = xf86Screens[i]->formats[j];
numFormats++;
break;
}
if (formats[k].depth == xf86Screens[i]->formats[j].depth) {
if ((formats[k].bitsPerPixel ==
xf86Screens[i]->formats[j].bitsPerPixel) &&
(formats[k].scanlinePad ==
xf86Screens[i]->formats[j].scanlinePad))
break;
FatalError("Inconsistent pixmap format for depth %d. Exiting\n", formats[k].depth);
}
}
}
}
formatsDone = TRUE;
}
else {
/*
* serverGeneration != 1; some OSs have to do things here, too.
*/
if (xorgHWOpenConsole)
xf86OpenConsole();
/*
should we reopen it here? We need to deal with an already opened
device. We could leave this to the OS layer. For now we simply
close it here
*/
if (xf86OSPMClose)
xf86OSPMClose();
if ((xf86OSPMClose = xf86OSPMOpen()) != NULL)
xf86MsgVerb(X_INFO, 3, "APM registered successfully\n");
/* Make sure full I/O access is enabled */
if (xorgHWAccess)
xf86EnableIO();
}
if (xf86Info.vtno >= 0)
AddCallback(&RootWindowFinalizeCallback, AddVTAtoms, NULL);
if (SeatId)
AddCallback(&RootWindowFinalizeCallback, AddSeatId, SeatId);
/*
* Use the previously collected parts to setup pScreenInfo
*/
pScreenInfo->imageByteOrder = xf86Screens[0]->imageByteOrder;
pScreenInfo->bitmapScanlinePad = xf86Screens[0]->bitmapScanlinePad;
pScreenInfo->bitmapScanlineUnit = xf86Screens[0]->bitmapScanlineUnit;
pScreenInfo->bitmapBitOrder = xf86Screens[0]->bitmapBitOrder;
pScreenInfo->numPixmapFormats = numFormats;
for (i = 0; i < numFormats; i++)
pScreenInfo->formats[i] = formats[i];
/* Make sure the server's VT is active */
if (serverGeneration != 1) {
xf86Resetting = TRUE;
/* All screens are in the same state, so just check the first */
if (!xf86VTOwner()) {
#ifdef HAS_USL_VTS
ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ);
#endif
input_lock();
sigio_blocked = TRUE;
}
}
for (i = 0; i < xf86NumScreens; i++)
if (!xf86ColormapAllocatePrivates(xf86Screens[i]))
FatalError("Cannot register DDX private keys");
if (!dixRegisterPrivateKey(&xf86ScreenKeyRec, PRIVATE_SCREEN, 0))
FatalError("Cannot register DDX private keys");
for (i = 0; i < xf86NumScreens; i++) {
xf86VGAarbiterLock(xf86Screens[i]);
/*
* Almost everything uses these defaults, and many of those that
* don't, will wrap them.
*/
xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess;
#ifdef XFreeXDGA
xf86Screens[i]->SetDGAMode = xf86SetDGAMode;
#endif
// AddScreen是 DIX 提供的桥梁:它创建 ScreenRec,然后回调具体显卡驱动的 ScreenInit。
scr_index = AddScreen(xf86ScreenInit, argc, argv);
xf86VGAarbiterUnlock(xf86Screens[i]);
if (scr_index == i) {
/*
* Hook in our ScrnInfoRec, and initialise some other pScreen
* fields.
*/
dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates,
xf86ScreenKey, xf86Screens[i]);
xf86Screens[i]->pScreen = screenInfo.screens[scr_index];
/* The driver should set this, but make sure it is set anyway */
xf86Screens[i]->vtSema = TRUE;
}
else {
/* This shouldn't normally happen */
FatalError("AddScreen/ScreenInit failed for driver %d\n", i);
}
if (PictureGetSubpixelOrder(xf86Screens[i]->pScreen) == SubPixelUnknown) {
xf86MonPtr DDC = (xf86MonPtr) (xf86Screens[i]->monitor->DDC);
PictureSetSubpixelOrder(xf86Screens[i]->pScreen, DDC ? (DDC->features.input_type ? SubPixelHorizontalRGB : SubPixelNone) : SubPixelUnknown);
}
/*
* If the driver hasn't set up its own RANDR support, install the
* fallback support.
*/
xf86EnsureRANDR(xf86Screens[i]->pScreen);
}
for (i = 0; i < xf86NumGPUScreens; i++) {
ScrnInfoPtr pScrn = xf86GPUScreens[i];
xf86VGAarbiterLock(pScrn);
/*
* Almost everything uses these defaults, and many of those that
* don't, will wrap them.
*/
pScrn->EnableDisableFBAccess = xf86EnableDisableFBAccess;
#ifdef XFreeXDGA
pScrn->SetDGAMode = xf86SetDGAMode;
#endif
scr_index = AddGPUScreen(xf86ScreenInit, argc, argv);
xf86VGAarbiterUnlock(pScrn);
if (scr_index == i) {
dixSetPrivate(&screenInfo.gpuscreens[scr_index]->devPrivates, xf86ScreenKey, xf86GPUScreens[i]);
pScrn->pScreen = screenInfo.gpuscreens[scr_index];
/* The driver should set this, but make sure it is set anyway */
pScrn->vtSema = TRUE;
} else {
FatalError("AddScreen/ScreenInit failed for gpu driver %d %d\n", i, scr_index);
}
}
for (i = 0; i < xf86NumGPUScreens; i++) {
int scrnum = xf86GPUScreens[i]->confScreen->screennum;
AttachUnboundGPU(xf86Screens[scrnum]->pScreen, xf86GPUScreens[i]->pScreen);
}
xf86AutoConfigOutputDevices();
xf86VGAarbiterWrapFunctions();
if (sigio_blocked)
input_unlock();
xf86InitOrigins();
xf86Resetting = FALSE;
xf86Initialising = FALSE;
RegisterBlockAndWakeupHandlers((ServerBlockHandlerProcPtr) NoopDDA, xf86Wakeup, NULL);
}
4、initInput
libinput / 具体输入驱动
→ QueuePointerEvents / QueueKeyboardEvents
→ mieqEnqueue
→ ProcessInputEvents
→ mieqProcessInputEvents
→ ProcessPointerEvent / ProcessKeyboardEvent
→ 命中测试、focus、grab、事件掩码与冒泡
→ DeliverEventsToWindow
→ WriteToClient
cpp
void
InitInput(int argc, char **argv)
{
InputInfoPtr *pInfo;
DeviceIntPtr dev;
xf86Info.vtRequestsPending = FALSE;
/* Enable threaded input */
InputThreadPreInit();
mieqInit();
/* Initialize all configured input devices */
for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) {
(*pInfo)->options =
xf86AddNewOption((*pInfo)->options, "driver", (*pInfo)->driver);
(*pInfo)->options =
xf86AddNewOption((*pInfo)->options, "identifier", (*pInfo)->name);
/* If one fails, the others will too */
if (NewInputDeviceRequest((*pInfo)->options, NULL, &dev) == BadAlloc)
break;
}
config_init();
}
5、dispatch函数
它是 X server 初始化完成后的主循环,核心职责是:
等待工作 → 处理输入事件 → 选择客户端 → 读取并执行 X 协议请求 → 发出响应,再进入下一轮。
cpp
void
Dispatch(void)
{
int result;
ClientPtr client;
long start_tick;
nextFreeClientID = 1;
nClients = 0;
SmartScheduleSlice = SmartScheduleInterval;
init_client_ready();
while (!dispatchException) {
// 有硬件输入
if (InputCheckPending()) {
ProcessInputEvents();
FlushIfCriticalOutputPending();
}
// 统一处理网络、work queue、定时器、screen 的 block/wakeup hook、socket 与输入 FD
if (!WaitForSomething(clients_are_ready()))
continue;
/*****************
* Handle events in round robin fashion, doing input between
* each round
*****************/
if (!dispatchException && clients_are_ready()) {
client = SmartScheduleClient();
isItTimeToYield = FALSE;
start_tick = SmartScheduleTime;
while (!isItTimeToYield) {
if (InputCheckPending())
ProcessInputEvents();
FlushIfCriticalOutputPending();
if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
{
/* Penalize clients which consume ticks */
if (client->smart_priority > SMART_MIN_PRIORITY)
client->smart_priority--;
break;
}
/* now, finally, deal with client requests */
result = ReadRequestFromClient(client);
if (result == 0)
break;
else if (result == -1) {
CloseDownClient(client);
break;
}
client->sequence++;
client->majorOp = ((xReq *) client->requestBuffer)->reqType;
client->minorOp = 0;
if (client->majorOp >= EXTENSION_BASE) {
ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
if (ext)
client->minorOp = ext->MinorOpcode(client);
}
#ifdef XSERVER_DTRACE
if (XSERVER_REQUEST_START_ENABLED())
XSERVER_REQUEST_START(LookupMajorName(client->majorOp),client->majorOp, ((xReq *) client->requestBuffer)->length, client->index, client->requestBuffer);
#endif
if (result < 0 || result > (maxBigRequestSize << 2))
result = BadLength;
else {
result = XaceHookDispatch(client, client->majorOp);
if (result == Success) {
currentClient = client;
result = (*client->requestVector[client->majorOp]) (client);
currentClient = NULL;
}
}
if (!SmartScheduleSignalEnable)
SmartScheduleTime = GetTimeInMillis();
#ifdef XSERVER_DTRACE
if (XSERVER_REQUEST_DONE_ENABLED())
XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), client->majorOp, client->sequence, client->index, result);
#endif
if (client->noClientException != Success) {
CloseDownClient(client);
break;
}
else if (result != Success) {
SendErrorToClient(client, client->majorOp, client->minorOp, client->errorValue, result);
break;
}
}
FlushAllOutput();
if (client == SmartLastClient)
client->smart_stop_tick = SmartScheduleTime;
}
dispatchException &= ~DE_PRIORITYCHANGE;
}
#if defined(DDXBEFORERESET)
ddxBeforeReset();
#endif
KillAllClients();
dispatchException &= ~DE_RESET;
SmartScheduleLatencyLimited = 0;
ResetOsBuffers();
}