Annotation of researchv9/X11/src/X.V11R1/server/dix/resource.c, revision 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.