From cb48d880856fd196ab8e8de5eb1f14944a1b4fff Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sun, 13 Apr 2008 19:48:28 +0930 Subject: [PATCH] Xi: store unused classes in devPrivates. Rather than freeing/allocing classes each time the device capabilities need to swap, store them in the devPrivates system. When a class is unused, it is pushed into the devPrivates, and later recovered when needed again. This saves us a lot of memory allocations/frees, admittedly on the cost of some memory. --- Xi/exevents.c | 145 ++++++++++++++++++++++++++++++++++++++------------ dix/devices.c | 10 ++++ 2 files changed, 120 insertions(+), 35 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 2a7afa9d4..d99f609e2 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -96,6 +96,9 @@ Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , static Bool MakeInputMasks(WindowPtr /* pWin */ ); +/* Used to sture classes currently not in use by an MD */ +extern DevPrivateKey UnusedClassesPrivateKey; + void RegisterOtherDevice(DeviceIntPtr device) @@ -416,28 +419,22 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) /** * Copies the CONTENT of the classes of device from into the classes in device * to. From and to are identical after finishing. + * + * If to does not have classes from currenly has, the classes are stored in + * to's devPrivates system. Later, we recover it again from there if needed. + * Saves a few memory allocations. */ _X_EXPORT void DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) { + ClassesPtr classes; + /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the * kbdfeed to be set up properly, so let's do the feedback classes first. */ DeepCopyFeedbackClasses(from, to); -#define ALLOC_COPY_CLASS_IF(field, type) \ - if (from->field)\ - { \ - if (!to->field) \ - { \ - to->field = xcalloc(1, sizeof(type)); \ - if (!to->field) \ - FatalError("[Xi] no memory for class shift.\n"); \ - } \ - memcpy(to->field, from->field, sizeof(type)); \ - } - if (from->key) { KeyCode *oldModKeyMap; @@ -445,15 +442,19 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) #ifdef XKB struct _XkbSrvInfo *oldXkbInfo; #endif - if (!to->key) { - to->key = xcalloc(1, sizeof(KeyClassRec)); + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->key = classes->key; if (!to->key) - FatalError("[Xi] no memory for class shift.\n"); + { + to->key = xcalloc(1, sizeof(KeyClassRec)); + if (!to->key) + FatalError("[Xi] no memory for class shift.\n"); + } } - oldModKeyMap = to->key->modifierKeyMap; oldMap = to->key->curKeySyms.map; #ifdef XKB @@ -480,14 +481,22 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) CopyKeyClass(from, to); } else if (to->key && !from->key) { - FreeDeviceClass(KeyClass, (pointer)&to->key); + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->key = to->key; + to->key = NULL; } if (from->valuator) { ValuatorClassPtr v; - if (to->valuator) - xfree(to->valuator->motion); + if (!to->valuator) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->valuator = classes->valuator; + } + to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) + from->valuator->numAxes * sizeof(AxisInfo) + from->valuator->numAxes * sizeof(unsigned int)); @@ -504,14 +513,28 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) v->axisVal = (int*)(v->axes + from->valuator->numAxes); } else if (to->valuator && !from->valuator) { - FreeDeviceClass(ValuatorClass, (pointer)&to->valuator); + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->valuator = to->valuator; + to->valuator = NULL; } - ALLOC_COPY_CLASS_IF(button, ButtonClassRec); - if (to->button) + if (from->button) { int i; DeviceIntPtr sd; + if (!to->button) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->button = classes->button; + if (!to->button) + { + to->button = xcalloc(1, sizeof(ButtonClassRec)); + if (!to->button) + FatalError("[Xi] no memory for class shift.\n"); + } + } /* merge button states from all attached devices */ for (sd = inputInfo.devices; sd; sd = sd->next) @@ -530,7 +553,10 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) #endif } else if (to->button && !from->button) { - FreeDeviceClass(ButtonClass, (pointer)&to->button); + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->button = to->button; + to->button = NULL; } @@ -544,29 +570,78 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) { if (!to->focus) { - to->focus = xcalloc(1, sizeof(FocusClassRec)); + WindowPtr *oldTrace; + + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->focus = classes->focus; if (!to->focus) - FatalError("[Xi] no memory for class shift.\n"); + { + to->focus = xcalloc(1, sizeof(FocusClassRec)); + if (!to->focus) + FatalError("[Xi] no memory for class shift.\n"); + } + oldTrace = to->focus->trace; + memcpy(to->focus, from->focus, sizeof(FocusClassRec)); + to->focus->trace = xrealloc(oldTrace, + to->focus->traceSize * sizeof(WindowPtr)); + if (!to->focus->trace && to->focus->traceSize) + FatalError("[Xi] no memory for trace.\n"); memcpy(to->focus->trace, from->focus->trace, from->focus->traceSize * sizeof(WindowPtr)); } } else if (to->focus) { - /* properly freeing the class would also free the sprite trace, which - * is still in use by the SD. just xfree the struct. */ - xfree(to->focus); + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->focus = to->focus; + to->focus = NULL; } - ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec); - if (to->proximity && !from->proximity) + if (from->proximity) { - FreeDeviceClass(ProximityClass, (pointer)&to->proximity); + if (!to->proximity) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->proximity = classes->proximity; + if (!to->proximity) + { + to->proximity = xcalloc(1, sizeof(ProximityClassRec)); + if (!to->proximity) + FatalError("[Xi] no memory for class shift.\n"); + } + } + memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); + } else if (to->proximity) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->proximity = to->proximity; + to->proximity = NULL; } - ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec); - if (to->absolute && !from->absolute) + + if (from->absolute) { - xfree(to->absolute); - to->absolute = NULL; + if (!to->absolute) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->absolute = classes->absolute; + if (!to->absolute) + { + to->absolute = xcalloc(1, sizeof(AbsoluteClassRec)); + if (!to->absolute) + FatalError("[Xi] no memory for class shift.\n"); + } + } + memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec)); + } else if (to->absolute) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->absolute = to->absolute; + to->absolute = NULL; } } diff --git a/dix/devices.c b/dix/devices.c index a78a1255d..266a66c61 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -89,6 +89,8 @@ SOFTWARE. /* The client that is allowed to change pointer-keyboard pairings. */ static ClientPtr pairingClient = NULL; DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; +/* Used to sture classes currently not in use by an MD */ +DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKey; /** * Create a new input device and init it to sane values. The device is added @@ -2550,6 +2552,7 @@ AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* { DeviceIntPtr pointer; DeviceIntPtr keyboard; + ClassesPtr classes; *ptr = *keybd = NULL; pointer = AddInputDevice(client, CorePointerProc, TRUE); @@ -2602,6 +2605,13 @@ AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* keyboard->u.lastSlave = NULL; keyboard->isMaster = TRUE; + + /* The ClassesRec stores the device classes currently not used. */ + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&pointer->devPrivates, UnusedClassesPrivateKey, classes); + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&keyboard->devPrivates, UnusedClassesPrivateKey, classes); + *ptr = pointer; *keybd = keyboard;