privates.c revision 35c4bbdf
1/* 2 3Copyright 1993, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28/* 29 * Copyright © 2010, Keith Packard 30 * Copyright © 2010, Jamey Sharp 31 * 32 * Permission to use, copy, modify, distribute, and sell this software and its 33 * documentation for any purpose is hereby granted without fee, provided that 34 * the above copyright notice appear in all copies and that both that copyright 35 * notice and this permission notice appear in supporting documentation, and 36 * that the name of the copyright holders not be used in advertising or 37 * publicity pertaining to distribution of the software without specific, 38 * written prior permission. The copyright holders make no representations 39 * about the suitability of this software for any purpose. It is provided "as 40 * is" without express or implied warranty. 41 * 42 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 44 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 46 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 47 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 48 * OF THIS SOFTWARE. 49 */ 50 51#ifdef HAVE_DIX_CONFIG_H 52#include <dix-config.h> 53#endif 54 55#include <stddef.h> 56#include "windowstr.h" 57#include "resource.h" 58#include "privates.h" 59#include "gcstruct.h" 60#include "cursorstr.h" 61#include "colormapst.h" 62#include "inputstr.h" 63#include "scrnintstr.h" 64#include "extnsionst.h" 65#include "inputstr.h" 66 67static DevPrivateSetRec global_keys[PRIVATE_LAST]; 68 69static const Bool xselinux_private[PRIVATE_LAST] = { 70 [PRIVATE_SCREEN] = TRUE, 71 [PRIVATE_CLIENT] = TRUE, 72 [PRIVATE_WINDOW] = TRUE, 73 [PRIVATE_PIXMAP] = TRUE, 74 [PRIVATE_GC] = TRUE, 75 [PRIVATE_CURSOR] = TRUE, 76 [PRIVATE_COLORMAP] = TRUE, 77 [PRIVATE_DEVICE] = TRUE, 78 [PRIVATE_EXTENSION] = TRUE, 79 [PRIVATE_SELECTION] = TRUE, 80 [PRIVATE_PROPERTY] = TRUE, 81 [PRIVATE_PICTURE] = TRUE, 82 [PRIVATE_GLYPHSET] = TRUE, 83}; 84 85static const char *key_names[PRIVATE_LAST] = { 86 /* XSELinux uses the same private keys for numerous objects */ 87 [PRIVATE_XSELINUX] = "XSELINUX", 88 89 /* Otherwise, you get a private in just the requested structure 90 */ 91 /* These can have objects created before all of the keys are registered */ 92 [PRIVATE_SCREEN] = "SCREEN", 93 [PRIVATE_EXTENSION] = "EXTENSION", 94 [PRIVATE_COLORMAP] = "COLORMAP", 95 [PRIVATE_DEVICE] = "DEVICE", 96 97 /* These cannot have any objects before all relevant keys are registered */ 98 [PRIVATE_CLIENT] = "CLIENT", 99 [PRIVATE_PROPERTY] = "PROPERTY", 100 [PRIVATE_SELECTION] = "SELECTION", 101 [PRIVATE_WINDOW] = "WINDOW", 102 [PRIVATE_PIXMAP] = "PIXMAP", 103 [PRIVATE_GC] = "GC", 104 [PRIVATE_CURSOR] = "CURSOR", 105 [PRIVATE_CURSOR_BITS] = "CURSOR_BITS", 106 107 /* extension privates */ 108 [PRIVATE_DAMAGE] = "DAMAGE", 109 [PRIVATE_GLYPH] = "GLYPH", 110 [PRIVATE_GLYPHSET] = "GLYPHSET", 111 [PRIVATE_PICTURE] = "PICTURE", 112 [PRIVATE_SYNC_FENCE] = "SYNC_FENCE", 113}; 114 115static const Bool screen_specific_private[PRIVATE_LAST] = { 116 [PRIVATE_SCREEN] = FALSE, 117 [PRIVATE_CLIENT] = FALSE, 118 [PRIVATE_WINDOW] = TRUE, 119 [PRIVATE_PIXMAP] = TRUE, 120 [PRIVATE_GC] = TRUE, 121 [PRIVATE_CURSOR] = FALSE, 122 [PRIVATE_COLORMAP] = FALSE, 123 [PRIVATE_DEVICE] = FALSE, 124 [PRIVATE_EXTENSION] = FALSE, 125 [PRIVATE_SELECTION] = FALSE, 126 [PRIVATE_PROPERTY] = FALSE, 127 [PRIVATE_PICTURE] = TRUE, 128 [PRIVATE_GLYPHSET] = FALSE, 129}; 130 131typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes); 132 133typedef enum { FixupMove, FixupRealloc } FixupType; 134 135static Bool 136dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes) 137{ 138 void *new_privates; 139 140 new_privates = realloc(*privates, old_offset + bytes); 141 if (!new_privates) 142 return FALSE; 143 memset((char *) new_privates + old_offset, '\0', bytes); 144 *privates = new_privates; 145 return TRUE; 146} 147 148static Bool 149dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes) 150{ 151 memmove((char *) *privates + bytes, *privates, new_offset - bytes); 152 memset(*privates, '\0', bytes); 153 return TRUE; 154} 155 156static Bool 157fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes) 158{ 159 intptr_t dist; 160 char *old; 161 char *new; 162 DevPrivateKey *keyp, key; 163 DevPrivateType type; 164 int size; 165 166 old = (char *) pScreen->devPrivates; 167 size = global_keys[PRIVATE_SCREEN].offset; 168 if (!fixup (&pScreen->devPrivates, size, bytes)) 169 return FALSE; 170 171 /* Screen privates can contain screen-specific private keys 172 * for other types. When they move, the linked list we use to 173 * track them gets scrambled. Fix that by computing the change 174 * in the location of each private adjusting our linked list 175 * pointers to match 176 */ 177 178 new = (char *) pScreen->devPrivates; 179 180 /* Moving means everyone shifts up in the privates by 'bytes' amount, 181 * realloc means the base pointer moves 182 */ 183 if (fixup == dixMovePrivates) 184 new += bytes; 185 186 dist = new - old; 187 188 if (dist) { 189 for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++) 190 191 /* Walk the privates list, being careful as the 192 * pointers are scrambled before we patch them. 193 */ 194 for (keyp = &pScreen->screenSpecificPrivates[type].key; 195 (key = *keyp) != NULL; 196 keyp = &key->next) 197 { 198 199 /* Only mangle things if the private structure 200 * is contained within the allocation. Privates 201 * stored elsewhere will be left alone 202 */ 203 if (old <= (char *) key && (char *) key < old + size) 204 { 205 /* Compute new location of key */ 206 key = (DevPrivateKey) ((char *) key + dist); 207 208 /* Patch the list */ 209 *keyp = key; 210 } 211 } 212 } 213 return TRUE; 214} 215 216static Bool 217fixupScreens(FixupFunc fixup, unsigned bytes) 218{ 219 int s; 220 221 for (s = 0; s < screenInfo.numScreens; s++) 222 if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes)) 223 return FALSE; 224 225 for (s = 0; s < screenInfo.numGPUScreens; s++) 226 if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes)) 227 return FALSE; 228 return TRUE; 229} 230 231static Bool 232fixupServerClient(FixupFunc fixup, unsigned bytes) 233{ 234 if (serverClient) 235 return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset, 236 bytes); 237 return TRUE; 238} 239 240static Bool 241fixupExtensions(FixupFunc fixup, unsigned bytes) 242{ 243 unsigned char major; 244 ExtensionEntry *extension; 245 246 for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); 247 major++) 248 if (!fixup 249 (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes)) 250 return FALSE; 251 return TRUE; 252} 253 254static Bool 255fixupDefaultColormaps(FixupFunc fixup, unsigned bytes) 256{ 257 int s; 258 259 for (s = 0; s < screenInfo.numScreens; s++) { 260 ColormapPtr cmap; 261 262 dixLookupResourceByType((void **) &cmap, 263 screenInfo.screens[s]->defColormap, RT_COLORMAP, 264 serverClient, DixCreateAccess); 265 if (cmap && 266 !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes)) 267 return FALSE; 268 } 269 return TRUE; 270} 271 272static Bool 273fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes) 274{ 275 while (device) { 276 if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes)) 277 return FALSE; 278 device = device->next; 279 } 280 return TRUE; 281} 282 283static Bool 284fixupDevices(FixupFunc fixup, unsigned bytes) 285{ 286 return (fixupDeviceList(inputInfo.devices, fixup, bytes) && 287 fixupDeviceList(inputInfo.off_devices, fixup, bytes)); 288} 289 290static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { 291 [PRIVATE_SCREEN] = fixupScreens, 292 [PRIVATE_CLIENT] = fixupServerClient, 293 [PRIVATE_EXTENSION] = fixupExtensions, 294 [PRIVATE_COLORMAP] = fixupDefaultColormaps, 295 [PRIVATE_DEVICE] = fixupDevices, 296}; 297 298static void 299grow_private_set(DevPrivateSetPtr set, unsigned bytes) 300{ 301 DevPrivateKey k; 302 303 for (k = set->key; k; k = k->next) 304 k->offset += bytes; 305 set->offset += bytes; 306} 307 308static void 309grow_screen_specific_set(DevPrivateType type, unsigned bytes) 310{ 311 int s; 312 313 /* Update offsets for all screen-specific keys */ 314 for (s = 0; s < screenInfo.numScreens; s++) { 315 ScreenPtr pScreen = screenInfo.screens[s]; 316 317 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); 318 } 319 for (s = 0; s < screenInfo.numGPUScreens; s++) { 320 ScreenPtr pScreen = screenInfo.gpuscreens[s]; 321 322 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); 323 } 324} 325 326/* 327 * Register a private key. This takes the type of object the key will 328 * be used with, which may be PRIVATE_ALL indicating that this key 329 * will be used with all of the private objects. If 'size' is 330 * non-zero, then the specified amount of space will be allocated in 331 * the private storage. Otherwise, space for a single pointer will 332 * be allocated which can be set with dixSetPrivate 333 */ 334Bool 335dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) 336{ 337 DevPrivateType t; 338 int offset; 339 unsigned bytes; 340 341 if (key->initialized) { 342 assert(size == key->size); 343 return TRUE; 344 } 345 346 /* Compute required space */ 347 bytes = size; 348 if (size == 0) 349 bytes = sizeof(void *); 350 351 /* align to pointer size */ 352 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 353 354 /* Update offsets for all affected keys */ 355 if (type == PRIVATE_XSELINUX) { 356 357 /* Resize if we can, or make sure nothing's allocated if we can't 358 */ 359 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) 360 if (xselinux_private[t]) { 361 if (!allocated_early[t]) 362 assert(!global_keys[t].created); 363 else if (!allocated_early[t] (dixReallocPrivates, bytes)) 364 return FALSE; 365 } 366 367 /* Move all existing keys up in the privates space to make 368 * room for this new global key 369 */ 370 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 371 if (xselinux_private[t]) { 372 grow_private_set(&global_keys[t], bytes); 373 grow_screen_specific_set(t, bytes); 374 if (allocated_early[t]) 375 allocated_early[t] (dixMovePrivates, bytes); 376 } 377 378 } 379 380 offset = 0; 381 } 382 else { 383 /* Resize if we can, or make sure nothing's allocated if we can't */ 384 if (!allocated_early[type]) 385 assert(!global_keys[type].created); 386 else if (!allocated_early[type] (dixReallocPrivates, bytes)) 387 return FALSE; 388 offset = global_keys[type].offset; 389 global_keys[type].offset += bytes; 390 grow_screen_specific_set(type, bytes); 391 } 392 393 /* Setup this key */ 394 key->offset = offset; 395 key->size = size; 396 key->initialized = TRUE; 397 key->type = type; 398 key->allocated = FALSE; 399 key->next = global_keys[type].key; 400 global_keys[type].key = key; 401 402 return TRUE; 403} 404 405Bool 406dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen, 407 DevPrivateType type, unsigned size) 408{ 409 DevPrivateKey key; 410 411 if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0)) 412 return FALSE; 413 key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey); 414 if (key != NULL) { 415 assert(key->size == size); 416 assert(key->type == type); 417 return TRUE; 418 } 419 key = calloc(sizeof(DevPrivateKeyRec), 1); 420 if (!key) 421 return FALSE; 422 if (!dixRegisterPrivateKey(key, type, size)) { 423 free(key); 424 return FALSE; 425 } 426 key->allocated = TRUE; 427 dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key); 428 return TRUE; 429} 430 431DevPrivateKey 432_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen) 433{ 434 return dixGetPrivate(&pScreen->devPrivates, &key->screenKey); 435} 436 437/* 438 * Initialize privates by zeroing them 439 */ 440void 441_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) 442{ 443 assert (!screen_specific_private[type]); 444 445 global_keys[type].created++; 446 if (xselinux_private[type]) 447 global_keys[PRIVATE_XSELINUX].created++; 448 if (global_keys[type].offset == 0) 449 addr = 0; 450 *privates = addr; 451 memset(addr, '\0', global_keys[type].offset); 452} 453 454/* 455 * Clean up privates 456 */ 457void 458_dixFiniPrivates(PrivatePtr privates, DevPrivateType type) 459{ 460 global_keys[type].created--; 461 if (xselinux_private[type]) 462 global_keys[PRIVATE_XSELINUX].created--; 463} 464 465/* 466 * Allocate new object with privates. 467 * 468 * This is expected to be invoked from the 469 * dixAllocateObjectWithPrivates macro 470 */ 471void * 472_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, 473 unsigned offset, DevPrivateType type) 474{ 475 unsigned totalSize; 476 void *object; 477 PrivatePtr privates; 478 PrivatePtr *devPrivates; 479 480 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); 481 assert(!screen_specific_private[type]); 482 483 /* round up so that void * is aligned */ 484 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 485 totalSize = baseSize + global_keys[type].offset; 486 object = malloc(totalSize); 487 if (!object) 488 return NULL; 489 490 memset(object, '\0', clear); 491 privates = (PrivatePtr) (((char *) object) + baseSize); 492 devPrivates = (PrivatePtr *) ((char *) object + offset); 493 494 _dixInitPrivates(devPrivates, privates, type); 495 496 return object; 497} 498 499/* 500 * Allocate privates separately from containing object. 501 * Used for clients and screens. 502 */ 503Bool 504dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) 505{ 506 unsigned size; 507 PrivatePtr p; 508 509 assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST); 510 assert(!screen_specific_private[type]); 511 512 size = global_keys[type].offset; 513 if (!size) { 514 p = NULL; 515 } 516 else { 517 if (!(p = malloc(size))) 518 return FALSE; 519 } 520 521 _dixInitPrivates(privates, p, type); 522 ++global_keys[type].allocated; 523 524 return TRUE; 525} 526 527/* 528 * Free an object that has privates 529 * 530 * This is expected to be invoked from the 531 * dixFreeObjectWithPrivates macro 532 */ 533void 534_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, 535 DevPrivateType type) 536{ 537 _dixFiniPrivates(privates, type); 538 free(object); 539} 540 541/* 542 * Called to free screen or client privates 543 */ 544void 545dixFreePrivates(PrivatePtr privates, DevPrivateType type) 546{ 547 _dixFiniPrivates(privates, type); 548 --global_keys[type].allocated; 549 free(privates); 550} 551 552/* 553 * Return size of privates for the specified type 554 */ 555extern _X_EXPORT int 556dixPrivatesSize(DevPrivateType type) 557{ 558 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); 559 assert (!screen_specific_private[type]); 560 561 return global_keys[type].offset; 562} 563 564/* Table of devPrivates offsets */ 565static const int offsets[] = { 566 -1, /* RT_NONE */ 567 offsetof(WindowRec, devPrivates), /* RT_WINDOW */ 568 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */ 569 offsetof(GC, devPrivates), /* RT_GC */ 570 -1, /* RT_FONT */ 571 offsetof(CursorRec, devPrivates), /* RT_CURSOR */ 572 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */ 573}; 574 575#define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0])) 576 577int 578dixLookupPrivateOffset(RESTYPE type) 579{ 580 /* 581 * Special kludge for DBE which registers a new resource type that 582 * points at pixmaps (thanks, DBE) 583 */ 584 if (type & RC_DRAWABLE) { 585 if (type == RT_WINDOW) 586 return offsets[RT_WINDOW & TypeMask]; 587 else 588 return offsets[RT_PIXMAP & TypeMask]; 589 } 590 type = type & TypeMask; 591 if (type < NUM_OFFSETS) 592 return offsets[type]; 593 return -1; 594} 595 596/* 597 * Screen-specific privates 598 */ 599 600extern _X_EXPORT Bool 601dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, 602 DevPrivateType type, unsigned size) 603{ 604 int offset; 605 unsigned bytes; 606 607 if (!screen_specific_private[type]) 608 FatalError("Attempt to allocate screen-specific private storage for type %s\n", 609 key_names[type]); 610 611 if (key->initialized) { 612 assert(size == key->size); 613 return TRUE; 614 } 615 616 /* Compute required space */ 617 bytes = size; 618 if (size == 0) 619 bytes = sizeof(void *); 620 621 /* align to void * size */ 622 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 623 624 assert (!allocated_early[type]); 625 assert (!pScreen->screenSpecificPrivates[type].created); 626 offset = pScreen->screenSpecificPrivates[type].offset; 627 pScreen->screenSpecificPrivates[type].offset += bytes; 628 629 /* Setup this key */ 630 key->offset = offset; 631 key->size = size; 632 key->initialized = TRUE; 633 key->type = type; 634 key->allocated = FALSE; 635 key->next = pScreen->screenSpecificPrivates[type].key; 636 pScreen->screenSpecificPrivates[type].key = key; 637 638 return TRUE; 639} 640 641/* Clean up screen-specific privates before CloseScreen */ 642void 643dixFreeScreenSpecificPrivates(ScreenPtr pScreen) 644{ 645 DevPrivateType t; 646 647 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 648 DevPrivateKey key; 649 650 for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) { 651 key->initialized = FALSE; 652 } 653 } 654} 655 656/* Initialize screen-specific privates in AddScreen */ 657void 658dixInitScreenSpecificPrivates(ScreenPtr pScreen) 659{ 660 DevPrivateType t; 661 662 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) 663 pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset; 664} 665 666/* Initialize screen-specific privates in AddScreen */ 667void 668_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type) 669{ 670 int privates_size; 671 assert (screen_specific_private[type]); 672 673 if (pScreen) { 674 privates_size = pScreen->screenSpecificPrivates[type].offset; 675 pScreen->screenSpecificPrivates[type].created++; 676 } 677 else 678 privates_size = global_keys[type].offset; 679 680 global_keys[type].created++; 681 if (xselinux_private[type]) 682 global_keys[PRIVATE_XSELINUX].created++; 683 if (privates_size == 0) 684 addr = 0; 685 *privates = addr; 686 memset(addr, '\0', privates_size); 687} 688 689void * 690_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen, 691 unsigned baseSize, 692 unsigned clear, 693 unsigned offset, 694 DevPrivateType type) 695{ 696 unsigned totalSize; 697 void *object; 698 PrivatePtr privates; 699 PrivatePtr *devPrivates; 700 int privates_size; 701 702 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); 703 assert (screen_specific_private[type]); 704 705 if (pScreen) 706 privates_size = pScreen->screenSpecificPrivates[type].offset; 707 else 708 privates_size = global_keys[type].offset; 709 /* round up so that pointer is aligned */ 710 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 711 totalSize = baseSize + privates_size; 712 object = malloc(totalSize); 713 if (!object) 714 return NULL; 715 716 memset(object, '\0', clear); 717 privates = (PrivatePtr) (((char *) object) + baseSize); 718 devPrivates = (PrivatePtr *) ((char *) object + offset); 719 720 _dixInitScreenPrivates(pScreen, devPrivates, privates, type); 721 722 return object; 723} 724 725int 726dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type) 727{ 728 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); 729 730 if (screen_specific_private[type]) 731 return pScreen->screenSpecificPrivates[type].offset; 732 else 733 return global_keys[type].offset; 734} 735 736void 737dixPrivateUsage(void) 738{ 739 int objects = 0; 740 int bytes = 0; 741 int alloc = 0; 742 DevPrivateType t; 743 744 for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) { 745 if (global_keys[t].offset) { 746 ErrorF 747 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n", 748 key_names[t], global_keys[t].created, global_keys[t].offset, 749 global_keys[t].created * global_keys[t].offset, global_keys[t].allocated); 750 bytes += global_keys[t].created * global_keys[t].offset; 751 objects += global_keys[t].created; 752 alloc += global_keys[t].allocated; 753 } 754 } 755 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc); 756} 757 758void 759dixResetPrivates(void) 760{ 761 DevPrivateType t; 762 763 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 764 DevPrivateKey key, next; 765 766 for (key = global_keys[t].key; key; key = next) { 767 next = key->next; 768 key->offset = 0; 769 key->initialized = FALSE; 770 key->size = 0; 771 key->type = 0; 772 if (key->allocated) 773 free(key); 774 } 775 if (global_keys[t].created) { 776 ErrorF("%d %ss still allocated at reset\n", 777 global_keys[t].created, key_names[t]); 778 dixPrivateUsage(); 779 } 780 global_keys[t].key = NULL; 781 global_keys[t].offset = 0; 782 global_keys[t].created = 0; 783 global_keys[t].allocated = 0; 784 } 785} 786