|
|
1.1 ! root 1: /************************************************************ ! 2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, ! 3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ! 4: ! 5: All Rights Reserved ! 6: ! 7: Permission to use, copy, modify, and distribute this software and its ! 8: documentation for any purpose and without fee is hereby granted, ! 9: provided that the above copyright notice appear in all copies and that ! 10: both that copyright notice and this permission notice appear in ! 11: supporting documentation, and that the names of Digital or MIT not be ! 12: used in advertising or publicity pertaining to distribution of the ! 13: software without specific, written prior permission. ! 14: ! 15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 21: SOFTWARE. ! 22: ! 23: ********************************************************/ ! 24: ! 25: /* $Header: resource.c,v 1.62 87/09/04 11:45:57 toddb Exp $ */ ! 26: ! 27: /* Routines to manage various kinds of resources: ! 28: * ! 29: * CreateNewResourceType, CreateNewResourceClass, InitClientResources, ! 30: * FakeClientID, AddResource, FreeResource, FreeClientResources, ! 31: * FreeAllResources, LookupID ! 32: */ ! 33: ! 34: /* ! 35: * a resource is a 32 bit quantity. the upper 12 bits are client id. ! 36: * client provides a 19 bit resource id. this is "hashed" by me by ! 37: * taking the 10 lower bits and xor'ing with the mid 10 bits. ! 38: * ! 39: * It is sometimes necessary for the server to create an ID that looks ! 40: * like it belongs to a client. This ID, however, must not be one ! 41: * the client actually can create, or we have the potential for conflict. ! 42: * The 20th bit of the ID is resevered for the server's use for this ! 43: * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to ! 44: * 1, and an otherwise unused ID in the low 19 bits, we can create a ! 45: * resource "owned" by the client. ! 46: * ! 47: * The following IDs are currently reserved for siccing on the client: ! 48: * 1 - allocated color to be freed when the client dies ! 49: */ ! 50: ! 51: #include "X.h" ! 52: #include "misc.h" ! 53: #include "os.h" ! 54: #include "resource.h" ! 55: #include "dixstruct.h" ! 56: #include "opaque.h" ! 57: ! 58: #define CACHEDTYPES (RT_WINDOW | RT_PIXMAP | RT_GC) ! 59: #define INITBUCKETS 64 ! 60: #define INITHASHSIZE 6 ! 61: #define MAXHASHSIZE 11 ! 62: ! 63: typedef struct _Resource { ! 64: struct _Resource *next; ! 65: XID id; ! 66: int (*DeleteFunc)(); ! 67: unsigned short type; ! 68: unsigned short class; ! 69: pointer value; ! 70: } ResourceRec, *ResourcePtr; ! 71: #define NullResource ((ResourcePtr)NULL) ! 72: ! 73: typedef struct _ClientResource { ! 74: ResourcePtr *resources; ! 75: int elements; ! 76: int buckets; ! 77: int hashsize; /* log(2)(buckets) */ ! 78: int fakeID; ! 79: } ClientResourceRec; ! 80: ! 81: static unsigned short lastResourceType; ! 82: static unsigned short lastResourceClass; ! 83: ! 84: unsigned short ! 85: CreateNewResourceType() ! 86: { ! 87: if (lastResourceType == 0x8000) /* this is compiler dependent XXX */ ! 88: lastResourceType = 0; ! 89: lastResourceType <<= 1; ! 90: return lastResourceType; ! 91: } ! 92: ! 93: short ! 94: CreateNewResourceClass() ! 95: { ! 96: return ++lastResourceClass; ! 97: } ! 98: ! 99: ClientResourceRec clientTable[MAXCLIENTS]; ! 100: ! 101: /***************** ! 102: * InitClientResources ! 103: * When a new client is created, call this to allocate space ! 104: * in resource table ! 105: *****************/ ! 106: ! 107: InitClientResources(client) ! 108: ClientPtr client; ! 109: { ! 110: register int i, j; ! 111: ! 112: if (client == serverClient) ! 113: { ! 114: lastResourceType = RT_LASTPREDEF; ! 115: lastResourceClass = RC_LASTPREDEF; ! 116: } ! 117: clientTable[i = client->index].resources = ! 118: (ResourcePtr *)Xalloc(INITBUCKETS*sizeof(ResourcePtr)); ! 119: clientTable[i].buckets = INITBUCKETS; ! 120: clientTable[i].elements = 0; ! 121: clientTable[i].hashsize = INITHASHSIZE; ! 122: clientTable[i].fakeID = 100; ! 123: for (j=0; j<INITBUCKETS; j++) ! 124: { ! 125: clientTable[i].resources[j] = NullResource; ! 126: } ! 127: } ! 128: ! 129: static int ! 130: Hash(client, id) ! 131: int client; ! 132: register int id; ! 133: { ! 134: id &= RESOURCE_ID_MASK; ! 135: switch (clientTable[client].hashsize) ! 136: { ! 137: case 6: ! 138: return 0x03F & (id ^ (id>>6) ^ (id>>12)); ! 139: case 7: ! 140: return 0x07F & (id ^ (id>>7) ^ (id>>13)); ! 141: case 8: ! 142: return 0x0FF & (id ^ (id>>8) ^ (id>>16)); ! 143: case 9: ! 144: return 0x1FF & (id ^ (id>>9)); ! 145: case 10: ! 146: return 0x3FF & (id ^ (id>>10)); ! 147: case 11: ! 148: return 0x7FF & (id ^ (id>>11)); ! 149: } ! 150: return -1; ! 151: } ! 152: ! 153: int ! 154: FakeClientID(client) ! 155: int client; ! 156: { ! 157: return ( ! 158: (client<<CLIENTOFFSET) + (SERVER_BIT) + ! 159: ((clientTable[client].fakeID++) & RESOURCE_ID_MASK)); ! 160: } ! 161: ! 162: void ! 163: AddResource(id, type, value, func, class) ! 164: int id; ! 165: unsigned short type, class; ! 166: pointer value; ! 167: int (* func)(); ! 168: { ! 169: int client, j; ! 170: ResourcePtr res, next, *head; ! 171: ! 172: client = CLIENT_ID(id); ! 173: if (!clientTable[client].buckets) ! 174: { ! 175: ErrorF("AddResource(%x, %d, %x, %d), client=%d \n", ! 176: id, type, value, class, client); ! 177: FatalError("client not in use\n"); ! 178: } ! 179: if (!func) ! 180: { ! 181: ErrorF("AddResource(%x, %d, %x, %d), client=%d \n", ! 182: id, type, value, class, client); ! 183: FatalError("No delete function given to AddResource \n"); ! 184: } ! 185: if ((clientTable[client].elements >= 4*clientTable[client].buckets) && ! 186: (clientTable[client].hashsize <= MAXHASHSIZE)) ! 187: { ! 188: register ResourcePtr *resources = (ResourcePtr *) ! 189: Xalloc(2*clientTable[client].buckets*sizeof(ResourcePtr)); ! 190: for (j = 0; j < clientTable[client].buckets*2; j++) ! 191: resources[j] = NullResource; ! 192: clientTable[client].hashsize++; ! 193: for (j = 0; j < clientTable[client].buckets; j++) ! 194: { ! 195: for (res = clientTable[client].resources[j]; res; res = next) ! 196: { ! 197: next = res->next; ! 198: head = &resources[Hash(client, res->id)]; ! 199: res->next = *head; ! 200: *head = res; ! 201: } ! 202: } ! 203: clientTable[client].buckets *= 2; ! 204: Xfree(clientTable[client].resources); ! 205: clientTable[client].resources = resources; ! 206: } ! 207: head = &clientTable[client].resources[Hash(client, id)]; ! 208: res = (ResourcePtr)Xalloc(sizeof(ResourceRec)); ! 209: res->next = *head; ! 210: res->id = id; ! 211: res->DeleteFunc = func; ! 212: res->type = type; ! 213: res->class = class; ! 214: res->value = value; ! 215: *head = res; ! 216: clientTable[client].elements++; ! 217: } ! 218: ! 219: void ! 220: FreeResource(id, skipDeleteFuncClass) ! 221: int id, skipDeleteFuncClass; ! 222: ! 223: { ! 224: unsigned cid; ! 225: register ResourcePtr res; ! 226: ResourcePtr * head; ! 227: Bool gotOne = FALSE; ! 228: ! 229: if (((cid = CLIENT_ID(id)) < MaxClients) && clientTable[cid].buckets) ! 230: { ! 231: head = &clientTable[cid].resources[Hash(cid, id)]; ! 232: ! 233: for (res = *head; res; res = *head) ! 234: { ! 235: if (res->id == id) ! 236: { ! 237: *head = res->next; ! 238: clientTable[cid].elements--; ! 239: if (res->type & CACHEDTYPES) ! 240: FlushClientCaches(res->id); ! 241: if (skipDeleteFuncClass != res->class) ! 242: (*res->DeleteFunc) (res->value, res->id); ! 243: Xfree(res); ! 244: gotOne = TRUE; ! 245: break; ! 246: } ! 247: else ! 248: head = &res->next; ! 249: } ! 250: if(clients[cid] && (id == clients[cid]->lastDrawableID)) ! 251: clients[cid]->lastDrawableID = INVALID; ! 252: } ! 253: if (!gotOne) ! 254: FatalError("Freeing resource id=%X which isn't there", id); ! 255: } ! 256: ! 257: void ! 258: FreeClientResources(client) ! 259: ClientPtr client; ! 260: { ! 261: register ResourcePtr *resources; ! 262: register ResourcePtr this; ! 263: int j; ! 264: ! 265: /* This routine shouldn't be called with a null client, but just in ! 266: case ... */ ! 267: ! 268: if (!client) ! 269: return; ! 270: ! 271: HandleSaveSet(client); ! 272: ! 273: resources = clientTable[client->index].resources; ! 274: for (j=0; j < clientTable[client->index].buckets; j++) ! 275: { ! 276: /* It may seem silly to update the head of this resource list as ! 277: we delete the members, since the entire list will be deleted any way, ! 278: but there are some resource deletion functions "FreeClientPixels" for ! 279: one which do a LookupID on another resource id (a Colormap id in this ! 280: case), so the resource list must be kept valid up to the point that ! 281: it is deleted, so every time we delete a resource, we must update the ! 282: head, just like in FreeResource. I hope that this doesn't slow down ! 283: mass deletion appreciably. PRH */ ! 284: ! 285: ResourcePtr *head; ! 286: ! 287: head = &resources[j]; ! 288: ! 289: for (this = *head; this; this = *head) ! 290: { ! 291: *head = this->next; ! 292: if (this->type & CACHEDTYPES) ! 293: FlushClientCaches(this->id); ! 294: (*this->DeleteFunc)(this->value, this->id); ! 295: Xfree(this); ! 296: } ! 297: } ! 298: Xfree(clientTable[client->index].resources); ! 299: clientTable[client->index].buckets = 0; ! 300: } ! 301: ! 302: FreeAllResources() ! 303: { ! 304: int i; ! 305: ! 306: for (i=0; i<currentMaxClients; i++) ! 307: { ! 308: if (clientTable[i].buckets) ! 309: FreeClientResources(clients[i]); ! 310: } ! 311: } ! 312: ! 313: /* ! 314: * LookupID returns the value field in the resource or NULL ! 315: * if an illegal id was handed to it or given type doesn't match the ! 316: * type for this id and class. ! 317: */ ! 318: pointer ! 319: LookupID(id, rType, class) ! 320: unsigned int id; ! 321: unsigned short rType, class; ! 322: { ! 323: unsigned cid; ! 324: register ResourcePtr res; ! 325: ! 326: if (((cid = CLIENT_ID(id)) < MaxClients) && clientTable[cid].buckets) ! 327: { ! 328: res = clientTable[cid].resources[Hash(cid, id)]; ! 329: ! 330: for (; res; res = res->next) ! 331: if ((res->id == id) && (res->class == class)) ! 332: if (res->type & rType) ! 333: return res->value; ! 334: else ! 335: return(pointer) NULL; ! 336: } ! 337: return(pointer) NULL; ! 338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.