void AQWAIT( _f_int *aqp, _f_int *status, _f_int *reply) { AQFIL *f; struct fflistreq *nxtq; _f_int dummy, *lreply; /* * UNICOS 8.0 and previous quietly permitted fewer than 2 arguments, * even though our documentatiokn for AQWAIT has required >= 2 args * for some time. Do the service of printing an error message if a * dusty deck code happens to use < 2 arguments. */ if (_numargs() < 2) _lerror(_LELVL_ABORT, FEARGCNT, "AQWAIT", _numargs(), "2 or 3"); /* * reply is an optional argument. */ lreply = reply; if (_numargs() < 3) lreply = &dummy; f = (AQFIL *) *aqp; if (f == NULL || f->aq_chk != AQ_CHK) { *status = -FEAQBADH; /* file handle is not valid */ return; } if (f->aq_busy == f->aq_nxtq) { *status = IDLE; return; } *status = OK; AQ_LOCK(aq_lkbusy); nxtq = f->aq_nxtq; _aqwait(f, status, lreply, nxtq); AQ_UNLOCK(aq_lkbusy); if (*status < 0 && _numargs() <= 1) _lerror(_LELVL_ABORT, -(*status)); 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; }
void AQRECALL( _f_int *aqp, _f_int *status, _f_int *reqid, _f_int *reply) { AQFIL *f; struct fflistreq *base, *limit, *nxtq, *busy, *eptr; int i; int max; int inside; if (_numargs() < 4) _lerror(_LELVL_ABORT, FEARGCNT, "AQRECALL", _numargs(), "4"); 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_lkbusy); busy = f->aq_busy; /* * Examine the entire queue, regardless of pointers */ for (i = 0 ; i < max ; i++) { if ( f->aq_reqid[i] == *reqid ) { eptr = &base[i]; /* * Determine if the entry in question is * between busy and nxtq. */ nxtq = f->aq_nxtq; /* Grab stable copy */ inside = NO; if (busy < nxtq) { if (busy <= eptr && eptr < nxtq) inside = YES; } else { if (eptr < nxtq || busy <= eptr) inside = YES; } /* * Now pointing to entry in question. * Wait for its completion, _aqwait will set status * appropriately. If not between nxtq and busy, * assume that if we found it, it must be done. */ *status = IOCOMPLETE; if (inside) { INC_QP(eptr, limit, max); _aqwait(f, status, reply, eptr); } AQ_UNLOCK(aq_lkbusy); return; } } AQ_UNLOCK(aq_lkbusy); *status = NOTFOUND; return; }