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_GLYPH] = "GLYPH", 109 [PRIVATE_GLYPHSET] = "GLYPHSET", 110 [PRIVATE_PICTURE] = "PICTURE", 111 [PRIVATE_SYNC_FENCE] = "SYNC_FENCE", 112}; 113 114static const Bool screen_specific_private[PRIVATE_LAST] = { 115 [PRIVATE_SCREEN] = FALSE, 116 [PRIVATE_CLIENT] = FALSE, 117 [PRIVATE_WINDOW] = TRUE, 118 [PRIVATE_PIXMAP] = TRUE, 119 [PRIVATE_GC] = TRUE, 120 [PRIVATE_CURSOR] = FALSE, 121 [PRIVATE_COLORMAP] = FALSE, 122 [PRIVATE_DEVICE] = FALSE, 123 [PRIVATE_EXTENSION] = FALSE, 124 [PRIVATE_SELECTION] = FALSE, 125 [PRIVATE_PROPERTY] = FALSE, 126 [PRIVATE_PICTURE] = TRUE, 127 [PRIVATE_GLYPHSET] = FALSE, 128}; 129 130typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes); 131 132typedef enum { FixupMove, FixupRealloc } FixupType; 133 134static Bool 135dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes) 136{ 137 void *new_privates; 138 139 new_privates = realloc(*privates, old_offset + bytes); 140 if (!new_privates) 141 return FALSE; 142 memset((char *) new_privates + old_offset, '\0', bytes); 143 *privates = new_privates; 144 return TRUE; 145} 146 147static Bool 148dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes) 149{ 150 memmove((char *) *privates + bytes, *privates, new_offset - bytes); 151 memset(*privates, '\0', bytes); 152 return TRUE; 153} 154 155static Bool 156fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes) 157{ 158 uintptr_t old; 159 char *new; 160 DevPrivateKey *keyp, key; 161 DevPrivateType type; 162 int size; 163 164 old = (uintptr_t) pScreen->devPrivates; 165 size = global_keys[PRIVATE_SCREEN].offset; 166 if (!fixup (&pScreen->devPrivates, size, bytes)) 167 return FALSE; 168 169 /* Screen privates can contain screen-specific private keys 170 * for other types. When they move, the linked list we use to 171 * track them gets scrambled. Fix that by computing the change 172 * in the location of each private adjusting our linked list 173 * pointers to match 174 */ 175 176 new = (char *) pScreen->devPrivates; 177 178 /* Moving means everyone shifts up in the privates by 'bytes' amount, 179 * realloc means the base pointer moves 180 */ 181 if (fixup == dixMovePrivates) 182 new += bytes; 183 184 if ((uintptr_t) new != old) { 185 for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++) 186 187 /* Walk the privates list, being careful as the 188 * pointers are scrambled before we patch them. 189 */ 190 for (keyp = &pScreen->screenSpecificPrivates[type].key; 191 (key = *keyp) != NULL; 192 keyp = &key->next) 193 { 194 195 /* Only mangle things if the private structure 196 * is contained within the allocation. Privates 197 * stored elsewhere will be left alone 198 */ 199 if (old <= (uintptr_t) key && (uintptr_t) key < old + size) 200 { 201 /* Compute new location of key (deriving from the new 202 * allocation to avoid UB) */ 203 key = (DevPrivateKey) (new + ((uintptr_t) key - old)); 204 205 /* Patch the list */ 206 *keyp = key; 207 } 208 } 209 } 210 return TRUE; 211} 212 213static Bool 214fixupScreens(FixupFunc fixup, unsigned bytes) 215{ 216 int s; 217 218 for (s = 0; s < screenInfo.numScreens; s++) 219 if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes)) 220 return FALSE; 221 222 for (s = 0; s < screenInfo.numGPUScreens; s++) 223 if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes)) 224 return FALSE; 225 return TRUE; 226} 227 228static Bool 229fixupServerClient(FixupFunc fixup, unsigned bytes) 230{ 231 if (serverClient) 232 return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset, 233 bytes); 234 return TRUE; 235} 236 237static Bool 238fixupExtensions(FixupFunc fixup, unsigned bytes) 239{ 240 unsigned char major; 241 ExtensionEntry *extension; 242 243 for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); 244 major++) 245 if (!fixup 246 (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes)) 247 return FALSE; 248 return TRUE; 249} 250 251static Bool 252fixupDefaultColormaps(FixupFunc fixup, unsigned bytes) 253{ 254 int s; 255 256 for (s = 0; s < screenInfo.numScreens; s++) { 257 ColormapPtr cmap; 258 259 dixLookupResourceByType((void **) &cmap, 260 screenInfo.screens[s]->defColormap, RT_COLORMAP, 261 serverClient, DixCreateAccess); 262 if (cmap && 263 !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes)) 264 return FALSE; 265 } 266 return TRUE; 267} 268 269static Bool 270fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes) 271{ 272 while (device) { 273 if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes)) 274 return FALSE; 275 device = device->next; 276 } 277 return TRUE; 278} 279 280static Bool 281fixupDevices(FixupFunc fixup, unsigned bytes) 282{ 283 return (fixupDeviceList(inputInfo.devices, fixup, bytes) && 284 fixupDeviceList(inputInfo.off_devices, fixup, bytes)); 285} 286 287static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { 288 [PRIVATE_SCREEN] = fixupScreens, 289 [PRIVATE_CLIENT] = fixupServerClient, 290 [PRIVATE_EXTENSION] = fixupExtensions, 291 [PRIVATE_COLORMAP] = fixupDefaultColormaps, 292 [PRIVATE_DEVICE] = fixupDevices, 293}; 294 295static void 296grow_private_set(DevPrivateSetPtr set, unsigned bytes) 297{ 298 DevPrivateKey k; 299 300 for (k = set->key; k; k = k->next) 301 k->offset += bytes; 302 set->offset += bytes; 303} 304 305static void 306grow_screen_specific_set(DevPrivateType type, unsigned bytes) 307{ 308 int s; 309 310 /* Update offsets for all screen-specific keys */ 311 for (s = 0; s < screenInfo.numScreens; s++) { 312 ScreenPtr pScreen = screenInfo.screens[s]; 313 314 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); 315 } 316 for (s = 0; s < screenInfo.numGPUScreens; s++) { 317 ScreenPtr pScreen = screenInfo.gpuscreens[s]; 318 319 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); 320 } 321} 322 323/* 324 * Register a private key. This takes the type of object the key will 325 * be used with, which may be PRIVATE_ALL indicating that this key 326 * will be used with all of the private objects. If 'size' is 327 * non-zero, then the specified amount of space will be allocated in 328 * the private storage. Otherwise, space for a single pointer will 329 * be allocated which can be set with dixSetPrivate 330 */ 331Bool 332dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) 333{ 334 DevPrivateType t; 335 int offset; 336 unsigned bytes; 337 338 if (key->initialized) { 339 assert(size == key->size); 340 return TRUE; 341 } 342 343 /* Compute required space */ 344 bytes = size; 345 if (size == 0) 346 bytes = sizeof(void *); 347 348 /* align to pointer size */ 349 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 350 351 /* Update offsets for all affected keys */ 352 if (type == PRIVATE_XSELINUX) { 353 354 /* Resize if we can, or make sure nothing's allocated if we can't 355 */ 356 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) 357 if (xselinux_private[t]) { 358 if (!allocated_early[t]) 359 assert(!global_keys[t].created); 360 else if (!allocated_early[t] (dixReallocPrivates, bytes)) 361 return FALSE; 362 } 363 364 /* Move all existing keys up in the privates space to make 365 * room for this new global key 366 */ 367 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 368 if (xselinux_private[t]) { 369 grow_private_set(&global_keys[t], bytes); 370 grow_screen_specific_set(t, bytes); 371 if (allocated_early[t]) 372 allocated_early[t] (dixMovePrivates, bytes); 373 } 374 375 } 376 377 offset = 0; 378 } 379 else { 380 /* Resize if we can, or make sure nothing's allocated if we can't */ 381 if (!allocated_early[type]) 382 assert(!global_keys[type].created); 383 else if (!allocated_early[type] (dixReallocPrivates, bytes)) 384 return FALSE; 385 offset = global_keys[type].offset; 386 global_keys[type].offset += bytes; 387 grow_screen_specific_set(type, bytes); 388 } 389 390 /* Setup this key */ 391 key->offset = offset; 392 key->size = size; 393 key->initialized = TRUE; 394 key->type = type; 395 key->allocated = FALSE; 396 key->next = global_keys[type].key; 397 global_keys[type].key = key; 398 399 return TRUE; 400} 401 402Bool 403dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen, 404 DevPrivateType type, unsigned size) 405{ 406 DevPrivateKey key; 407 408 if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0)) 409 return FALSE; 410 key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey); 411 if (key != NULL) { 412 assert(key->size == size); 413 assert(key->type == type); 414 return TRUE; 415 } 416 key = calloc(sizeof(DevPrivateKeyRec), 1); 417 if (!key) 418 return FALSE; 419 if (!dixRegisterPrivateKey(key, type, size)) { 420 free(key); 421 return FALSE; 422 } 423 key->allocated = TRUE; 424 dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key); 425 return TRUE; 426} 427 428DevPrivateKey 429_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen) 430{ 431 return dixGetPrivate(&pScreen->devPrivates, &key->screenKey); 432} 433 434/* 435 * Initialize privates by zeroing them 436 */ 437void 438_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) 439{ 440 assert (!screen_specific_private[type]); 441 442 global_keys[type].created++; 443 if (xselinux_private[type]) 444 global_keys[PRIVATE_XSELINUX].created++; 445 if (global_keys[type].offset == 0) 446 addr = 0; 447 *privates = addr; 448 if (addr) 449 memset(addr, '\0', global_keys[type].offset); 450} 451 452/* 453 * Clean up privates 454 */ 455void 456_dixFiniPrivates(PrivatePtr privates, DevPrivateType type) 457{ 458 global_keys[type].created--; 459 if (xselinux_private[type]) 460 global_keys[PRIVATE_XSELINUX].created--; 461} 462 463/* 464 * Allocate new object with privates. 465 * 466 * This is expected to be invoked from the 467 * dixAllocateObjectWithPrivates macro 468 */ 469void * 470_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, 471 unsigned offset, DevPrivateType type) 472{ 473 unsigned totalSize; 474 void *object; 475 PrivatePtr privates; 476 PrivatePtr *devPrivates; 477 478 assert(type > PRIVATE_SCREEN); 479 assert(type < PRIVATE_LAST); 480 assert(!screen_specific_private[type]); 481 482 /* round up so that void * is aligned */ 483 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 484 totalSize = baseSize + global_keys[type].offset; 485 object = malloc(totalSize); 486 if (!object) 487 return NULL; 488 489 memset(object, '\0', clear); 490 privates = (PrivatePtr) (((char *) object) + baseSize); 491 devPrivates = (PrivatePtr *) ((char *) object + offset); 492 493 _dixInitPrivates(devPrivates, privates, type); 494 495 return object; 496} 497 498/* 499 * Allocate privates separately from containing object. 500 * Used for clients and screens. 501 */ 502Bool 503dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) 504{ 505 unsigned size; 506 PrivatePtr p; 507 508 assert(type > PRIVATE_XSELINUX); 509 assert(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); 559 assert(type < PRIVATE_LAST); 560 assert (!screen_specific_private[type]); 561 562 return global_keys[type].offset; 563} 564 565/* Table of devPrivates offsets */ 566static const int offsets[] = { 567 -1, /* RT_NONE */ 568 offsetof(WindowRec, devPrivates), /* RT_WINDOW */ 569 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */ 570 offsetof(GC, devPrivates), /* RT_GC */ 571 -1, /* RT_FONT */ 572 offsetof(CursorRec, devPrivates), /* RT_CURSOR */ 573 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */ 574}; 575 576int 577dixLookupPrivateOffset(RESTYPE type) 578{ 579 /* 580 * Special kludge for DBE which registers a new resource type that 581 * points at pixmaps (thanks, DBE) 582 */ 583 if (type & RC_DRAWABLE) { 584 if (type == RT_WINDOW) 585 return offsets[RT_WINDOW & TypeMask]; 586 else 587 return offsets[RT_PIXMAP & TypeMask]; 588 } 589 type = type & TypeMask; 590 if (type < ARRAY_SIZE(offsets)) 591 return offsets[type]; 592 return -1; 593} 594 595/* 596 * Screen-specific privates 597 */ 598 599extern _X_EXPORT Bool 600dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, 601 DevPrivateType type, unsigned size) 602{ 603 int offset; 604 unsigned bytes; 605 606 if (!screen_specific_private[type]) 607 FatalError("Attempt to allocate screen-specific private storage for type %s\n", 608 key_names[type]); 609 610 if (key->initialized) { 611 assert(size == key->size); 612 return TRUE; 613 } 614 615 /* Compute required space */ 616 bytes = size; 617 if (size == 0) 618 bytes = sizeof(void *); 619 620 /* align to void * size */ 621 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 622 623 assert (!allocated_early[type]); 624 assert (!pScreen->screenSpecificPrivates[type].created); 625 offset = pScreen->screenSpecificPrivates[type].offset; 626 pScreen->screenSpecificPrivates[type].offset += bytes; 627 628 /* Setup this key */ 629 key->offset = offset; 630 key->size = size; 631 key->initialized = TRUE; 632 key->type = type; 633 key->allocated = FALSE; 634 key->next = pScreen->screenSpecificPrivates[type].key; 635 pScreen->screenSpecificPrivates[type].key = key; 636 637 return TRUE; 638} 639 640/* Clean up screen-specific privates before CloseScreen */ 641void 642dixFreeScreenSpecificPrivates(ScreenPtr pScreen) 643{ 644 DevPrivateType t; 645 646 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 647 DevPrivateKey key; 648 649 for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) { 650 key->initialized = FALSE; 651 } 652 } 653} 654 655/* Initialize screen-specific privates in AddScreen */ 656void 657dixInitScreenSpecificPrivates(ScreenPtr pScreen) 658{ 659 DevPrivateType t; 660 661 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) 662 pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset; 663} 664 665/* Initialize screen-specific privates in AddScreen */ 666void 667_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type) 668{ 669 int privates_size; 670 assert (screen_specific_private[type]); 671 672 if (pScreen) { 673 privates_size = pScreen->screenSpecificPrivates[type].offset; 674 pScreen->screenSpecificPrivates[type].created++; 675 } 676 else 677 privates_size = global_keys[type].offset; 678 679 global_keys[type].created++; 680 if (xselinux_private[type]) 681 global_keys[PRIVATE_XSELINUX].created++; 682 if (privates_size == 0) 683 addr = 0; 684 *privates = addr; 685 if (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); 703 assert(type < PRIVATE_LAST); 704 assert (screen_specific_private[type]); 705 706 if (pScreen) 707 privates_size = pScreen->screenSpecificPrivates[type].offset; 708 else 709 privates_size = global_keys[type].offset; 710 /* round up so that pointer is aligned */ 711 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); 712 totalSize = baseSize + privates_size; 713 object = malloc(totalSize); 714 if (!object) 715 return NULL; 716 717 memset(object, '\0', clear); 718 privates = (PrivatePtr) (((char *) object) + baseSize); 719 devPrivates = (PrivatePtr *) ((char *) object + offset); 720 721 _dixInitScreenPrivates(pScreen, devPrivates, privates, type); 722 723 return object; 724} 725 726int 727dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type) 728{ 729 assert(type >= PRIVATE_SCREEN); 730 assert(type < PRIVATE_LAST); 731 732 if (screen_specific_private[type]) 733 return pScreen->screenSpecificPrivates[type].offset; 734 else 735 return global_keys[type].offset; 736} 737 738void 739dixPrivateUsage(void) 740{ 741 int objects = 0; 742 int bytes = 0; 743 int alloc = 0; 744 DevPrivateType t; 745 746 for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) { 747 if (global_keys[t].offset) { 748 ErrorF 749 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n", 750 key_names[t], global_keys[t].created, global_keys[t].offset, 751 global_keys[t].created * global_keys[t].offset, global_keys[t].allocated); 752 bytes += global_keys[t].created * global_keys[t].offset; 753 objects += global_keys[t].created; 754 alloc += global_keys[t].allocated; 755 } 756 } 757 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc); 758} 759 760void 761dixResetPrivates(void) 762{ 763 DevPrivateType t; 764 765 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { 766 DevPrivateKey key, next; 767 768 for (key = global_keys[t].key; key; key = next) { 769 next = key->next; 770 key->offset = 0; 771 key->initialized = FALSE; 772 key->size = 0; 773 key->type = 0; 774 if (key->allocated) 775 free(key); 776 } 777 if (global_keys[t].created) { 778 ErrorF("%d %ss still allocated at reset\n", 779 global_keys[t].created, key_names[t]); 780 dixPrivateUsage(); 781 } 782 global_keys[t].key = NULL; 783 global_keys[t].offset = 0; 784 global_keys[t].created = 0; 785 global_keys[t].allocated = 0; 786 } 787} 788 789Bool 790dixPrivatesCreated(DevPrivateType type) 791{ 792 if (global_keys[type].created) 793 return TRUE; 794 else 795 return FALSE; 796} 797