GameSource/xqueue.c

/*
    xqueue
    ------
    Hairy  queue manager
    disables interrupts both in enqueue and dequeue
    to prevent list mangling and contention between
    the Time Manager and the application.
    
    This code is dependant upon the implementation
    of the xthing structure, since it only queues them up
    could be changed to queue up anything though, just
    watch those qLink fields.
    
    7:17:22 PM  10/28/92
    By Brigham Stevens
    Apple Computer, Inc.
    Developer Technical Support
*/
 
#include "xthing.h"
#include "ZAMProtos.h"
 
 
// uncomment out the line below to disable interrupts when playing in
// the queue.  However, the rest of ZAM does not need this anymore,
// but you might like to do it for kicks or your own uses.
// #define DISABLE_INTERRUPTS 1
 
/* set the processor to disable other interrupts */
/* don't do much while interrupts are disabled */
/* or the whole system will go to hell */
short disableInterrupts(void)
{
    asm {
            move    SR,d0           ; return old IntMask
            ori.w   #0x0700,SR
    }
}
 
/* restore previous interrupt level returned from disable above*/
void enableInterrupts(short level)
{
    asm {
            move.w  level,-(sp)         ; push old mask
            move    (sp)+,SR            ; restore that puppy
    }
}
 
void xPanic(short stackFrameGeneratorRequiredToSeeName)
/*
    Maybe you can make the debugger jump here if you are in a hairy death situation
*/
{
    enableInterrupts(0);
    ExitToShell();
}
 
void xInitQueueHeader(xQHdr *queue)
/*
    init one of my queue headers
*/
{
    queue->qFlags = 0L;
    queue->qHead = nil;
    queue->qTail = nil;
    queue->qEntries = 0;
}
 
void xEnqueue(xthing *qel, xQHdr *queue)
/*
    enqueue a an xthing task
*/
{
    short       oldIntMask;
 
    if(!qel)    return;
    
#ifdef DISABLE_INTERRUPTS   
    oldIntMask = disableInterrupts();
#endif
 
    qel->next =  nil;               /* make sure no bad doggies on the end */
    queue->qEntries++;
    
    if(queue->qTail) {              /* add to the end */
        queue->qTail->next = qel;   /* add to queue */
        queue->qTail = qel;         /* placeholder for end */
    } else {                        /* only item in the queue */
        queue->qHead = queue->qTail = qel;
    }
    
#ifdef DISABLE_INTERRUPTS
    enableInterrupts(oldIntMask);
#endif
}
 
void xDequeue(xthing *qel, xQHdr *queue)
/*
    Remove an xthing task from the queue
*/
{
    xthing  *curs;
    short   oldIntMask;
    
    if(!qel)    return;
    
#ifdef DISABLE_INTERRUPTS
    oldIntMask = disableInterrupts();
#endif
    
    if(qel == queue->qHead) {
        /* special case if the one */
        /* to be removed is the first item */
        queue->qHead = qel->next;
        queue->qEntries--;
        qel->next = nil;
        if(queue->qTail == qel) {
            queue->qTail = nil;
        }
    } else {
    
        /* nope, so now search the queue */
        curs = queue->qHead;
        while(curs) {
            if(curs->next == qel) {
                curs->next = qel->next;
                queue->qEntries--;
                return;
            }
            curs = curs->next;
        }
        
    }
 
#ifdef DISABLE_INTERRRUPTS  
    enableInterrupts(oldIntMask);
#endif
 
}