Annotation of researchv9/X11/src/X.V11R1/server/dix/resource.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.