void _aqwait( AQFIL *f, _f_int *status, _f_int *reply, struct fflistreq *ptr) { struct fflistreq *base, *limit; int ret, max; int indx; base = f->aq_base; limit = f->aq_limit; max = limit - base; /* * Start any queued requests. Locking is done in aqcall, as well as * checking to see if any requests need to be fired. */ _aqcall(f); /* * Wait for completion of all outstanding requests. */ while (f->aq_busy != ptr) { ret = _aqrcl(f, f->aq_busy); indx = f->aq_busy - base; if(ret != 0 && f->aq_told[indx] == 0) { *reply = f->aq_reqid[indx]; f->aq_told[indx] = 1; /* user has been told */ INC_QP(f->aq_busy, limit, max); *status = -ret; return; } INC_QP(f->aq_busy, limit, max); } return; }
void AQSTAT( _f_int *aqp, _f_int *reply, _f_int *reqid, _f_int *status, _f_int *wait) { AQFIL *f; struct fflistreq *base, *limit, *ptr, *busy, *eptr; struct ffsw *istat; struct ffsw dumstat; int indx; int ret; int max; int isbusy; f = (AQFIL *) *aqp; if (f == NULL || f->aq_chk != AQ_CHK) { *status = -FEAQBADH; /* file handle is not valid */ return; } base = f->aq_base; limit = f->aq_limit; max = limit - base; /* * Lock the tail of the queue so no one can stomp on the entry for * which we are searching. */ AQ_LOCK(aq_lknxtq); AQ_LOCK(aq_lkbusy); /* don't nobody move */ busy = f->aq_busy; /* * Examine the entire queue, regardless of pointers */ for (indx = 0 ; indx < max ; indx++) { if ( f->aq_reqid[indx] == *reqid ) { eptr = &base[indx]; istat = base[indx].li_status; ptr = f->aq_ptr; /* Grab stable copy */ /* If it moves, that's OK. */ /* * If the user requested that we wait for this one... */ if (_numargs() > 4 && *wait != 0) { /* * Determine if the entry in question is * between busy and ptr. */ isbusy = NO; if (busy <= ptr) { if (busy <= eptr && eptr < ptr) isbusy = YES; } else { if (eptr < ptr || busy <= eptr) isbusy = YES; } /* * Now pointing to entry in question. * Wait for its completion, if btwn busy and ptr, * Unlock queue head to allow additions * to the queue while waiting. */ AQ_UNLOCK(aq_lknxtq); /* * If the requested reqid has not been fired, * fire the listio before the wait. */ if (isbusy == NO) { _aqcall(f); } goto finish_io2; } /* * If user did not request wait, just return the status, * but first check to see if it is done. If it is, Give * the recall routine a shot at cleanup and finish up as * though a wait had been requested. */ if (f->aq_ffio == YES) { AQPOLL(eptr, &dumstat); if (FFSTAT(*istat) != FFBSY) { goto finish_io1; } } else if ( istat->sw_flag != 0 ) { goto finish_io1; } /* * If the entry is found, but not complete, it is * either QUEUED and active or QUEUED and not yet * activated. * If eptr is between busy and ptr, it is active. */ *status = LQUEUED; /* not yet active */ if (busy <= ptr) { if (busy <= eptr && eptr < ptr) /* queued and active */ *status = QUEUED; } else { if (eptr < ptr || busy <= eptr) /* queued and active */ *status = QUEUED; } goto done; } } *status = NOTFOUND; done: AQ_UNLOCK(aq_lkbusy); AQ_UNLOCK(aq_lknxtq); return; finish_io1: AQ_UNLOCK(aq_lknxtq); finish_io2: /* * Do the 'recall' on the request. */ ret = _aqrcl(f, eptr); /* * The request is now done. Now that we are about to return the status * of the request, check if this entry is at tail of queue. * If the request is at the tail of the queue free up the entry. * This is probably silly. */ if (f->aq_busy == eptr) INC_QP(f->aq_busy, limit, max); /* * Set return status */ *status = IOCOMPLETE; if (ret != 0) { *status = -ret; if (ret == FERDWRER) *reply = eptr->li_status->sw_count; } /* * Flag the status as delivered */ f->aq_told[indx] = 1; /* mark status as having been sent to user */ AQ_UNLOCK(aq_lkbusy); return; }