Beispiel #1
0
//----------------------------------------------------------------
fifocell* fifoflush (fifo* ff) 
{
	fifocell* next, *cur;
	fifocell* first;
		
	first = fifoget(ff);
	if (first==0) return 0;	
	cur = first;	
	while ((next = fifoget(ff))) {
		cur->link = next;
		cur = next;
	}
	cur->link = 0;
	return first;
}
Beispiel #2
0
//----------------------------------------------------------------
fifocell * fifoget (fifo * ff) 
{
	fifocell * volatile head;
	fifocell * next;
	short done = 0;
	
	do {
		LWARX (&ff->head);
        head = ff->head;				/* read the head cell */
		next = head->link;				/* read the next cell */
		/*
		  WARNING: the next pointer still needs to be checked before reading its value 
		*/
		if (head == ff->tail) {			/* is queue empty or tail falling behind? */
			if (head->link == fifo_end(ff) && STWCX (&ff->head, (void *)head, (void *)head)) /* is queue really empty? */
				return 0;				/* queue is empty; return NULL */
			/* tail is pointing to head in a non empty queue, */
			/* try to set tail to the next cell               */
			CASLNE (&ff->tail, (void *)head, fifo_end(ff));
		}
		else if (next != fifo_end(ff)) { /* if we are not competing on the dummy cell */
			/* and we try to set head to the next cell */
			done = STWCX (&ff->head, (void *)head, next);
		}
	} while (!done);
	msAtomicDec (&ff->count);
	if (head == &ff->dummy) {
		fifoput(ff,head);
		head = fifoget(ff);
	}
	return (fifocell *)head;
}
Beispiel #3
0
//----------------------------------------------------------------
fifocell *  fifoget(fifo * ff)
{
    fifocell * volatile head;
    fifocell * next;
    unsigned long ic, oc;
    short done = 0;

    do {
        oc = ff->oc;					/* read the head modification count */
        ic = ff->ic;					/* read the tail modification count */
        head = ff->head;				/* read the head cell */
        next = head->link;				/* read the next cell */
        if (oc == ff->oc) {				/* ensures that next is a valid pointer */
            /* to avoid failure when reading next value */
            if (head == ff->tail) {			/* is queue empty or tail falling behind? */
                if (next == fifo_end(ff))	/* is queue empty?             */
                    return 0;				/* queue is empty; return NULL */
                /* tail is pointing to head in a non empty queue, */
                /* try to set tail to the next cell               */
                CAS2 (&ff->tail, head, ic, next, ic+1);
            }
            else if (next != fifo_end(ff)) { /* if we are not competing on the dummy cell */
                /* and we try to set head to the next cell */
                done = CAS2 (&ff->head, head, oc, next, oc+1);
            }
        }
    } while (!done);
    msAtomicDec (&ff->count);
    if (head == &ff->dummy) {
        fifoput(ff,head);
        head = fifoget(ff);
    }
    return (fifocell *)head;
}
Beispiel #4
0
// We dequeue in two stages.  First we get the element, and then we
// "cleanup" to free the element we got.
void* wsfifoget(wsfifo* ff) {
    void* ptr = fifoget(& ff->ff);
    if (! ptr) { // Doesn't need to be while.
      //sleep(1); printf(".");
      pthread_mutex_lock(& ff->mut);
      ptr = fifoget(& ff->ff);
      // If there is STILL nothing while we have the lock then we need to block.
      if (!ptr) {
        pthread_cond_wait(& ff->cond, & ff->mut);
        ptr = fifoget(& ff->ff); // Now we better get something.
      }
      // Do this before we unlock?
      pthread_mutex_unlock(& ff->mut);
    }
    //printf("  got val off queue #%d, %p : %p %p %d %d\n", 
    //       index, queue_table[index], ptr, (void**)ptr+1, *((int*)((void**)ptr+1)), *((char*)((void**)ptr+1)));
    ff->last_cell = ptr;
    return ((void**)ptr)+1;
}