Exemplo n.º 1
0
/*
 * exec_qio()
 *	Do the actions specified by a qio operation
 */
static void
exec_qio(struct buf *b, int op)
{
	ASSERT_DEBUG(BUSY(b), "exec_qio: !busy");
	switch (op) {
	case Q_FILLBUF:
		if (b->b_flags & B_SEC0) {
			read_secs(b->b_start + 1,
				(char *)b->b_data + SECSZ,
				b->b_nsec - 1);
		} else {
			read_secs(b->b_start,
				b->b_data, b->b_nsec);
		}
		b->b_flags |= (B_SEC0|B_SECS);
		break;

	case Q_FLUSHBUF:
		_sync_buf(b, 1);
		break;

	default:
		ASSERT_DEBUG(0, "bg_thread: qio");
		break;
	}
	ASSERT_DEBUG(BUSY(b), "exec_qio: went !busy");
}
Exemplo n.º 2
0
/*
 * age_buf()
 *	Find the next available buf header, flush and free it
 *
 * Since this is basically a paging algorithm, it can become arbitrarily
 * complex.  The algorithm here tries to be simple, yet somewhat fair.
 */
static void
age_buf(void)
{
	struct llist *l;
	struct buf *b;

	/*
	 * Pick the oldest buf which isn't locked.
	 */
	for (l = allbufs.l_back; l != &allbufs; l = l->l_back) {
		/*
		 * Only skip if wired or active
		 */
		b = l->l_data;
		if (b->b_locks || BUSY(b)) {
			continue;
		}

		ASSERT_DEBUG(b->b_lock == 0, "age_buf: lock");
		if (!(b->b_flags & B_DIRTY)) {
			/*
			 * Remove from list, update data structures
			 */
			free_buf(b);
			return;
		}

		/*
		 * Sync out data in background
		 */
		qio(b, Q_FLUSHBUF);
	}
	ASSERT_DEBUG(bufsize <= coresec, "age_buf: buffers too large");
}
Exemplo n.º 3
0
int
meta2_filter_check_events_not_stalled (struct gridd_filter_ctx_s *ctx,
		struct gridd_reply_ctx_s *reply)
{
	(void) reply;
	TRACE_FILTER ();

	struct meta2_backend_s *m2b = meta2_filter_ctx_get_backend(ctx);
	if (m2b->notifier && meta2_backend_initiated (m2b)) {
		if (oio_events_queue__is_stalled (m2b->notifier)) {
			meta2_filter_ctx_set_error(ctx, BUSY("Too many pending events"));
			return FILTER_KO;
		}
	}

	return FILTER_OK;
}
Exemplo n.º 4
0
/*
 * qio()
 *	Queue an operation for the BG thread
 */
static void
qio(struct buf *b, uint op)
{
	struct qio *q;
	uint next;

	/*
	 * This buffer is busy until op complete
	 */
	ASSERT_DEBUG(!BUSY(b), "qio: busy");
	b->b_flags |= B_BUSY;

	/*
	 * Get next ring element
	 */
	next = qnext;
	q = &qios[next];
	if (++next >= NQIO) {
		next = 0;
	}
	qnext = next;

	/*
	 * Wait for it to be ready
	 */
	busywait(&q->q_op);

	/*
	 * Fill it in
	 */
	q->q_buf = b;
	q->q_op = op;

	/*
	 * Release BG to do its thing
	 */
	mutex_thread(bg_pid);
}
static
VOID
CALLBACK
UnparkCallback (
    __inout_opt PVOID Context,
    __in ULONG WaitStatus
)
{
    PST_REGISTERED_WAIT RegisteredWait;
    PST_PARKER OldState;
    PST_PARKER MyBusy;
    ULONG Ignored;

    _ASSERTE(WaitStatus == WAIT_SUCCESS || WaitStatus == WAIT_TIMEOUT ||
             WaitStatus == WAIT_UNREGISTERED);

    //
    // If the registered wait was disposed (externally unregistered), cancel
    // the acquire attempt and return immediately.
    //

    RegisteredWait = (PST_REGISTERED_WAIT)Context;
    if (WaitStatus == WAIT_UNREGISTERED) {
        CANCEL_ACQUIRE(RegisteredWait->Waitable, &RegisteredWait->WaitBlock);
        return;
    }

    //
    // Set state to *our busy* grabing the current state and execute
    // the unpark callback processing.
    //

    MyBusy = BUSY(&MyBusy);
    OldState = (PST_PARKER)InterlockedExchangePointer(&RegisteredWait->State, MyBusy);

    //
    // ...
    //

    do {

        //
        // If the acquire operation was cancelled, cancel the acquire
        // attempt on the waitable.
        //

        if (WaitStatus != WAIT_SUCCESS) {
            CANCEL_ACQUIRE(RegisteredWait->Waitable, &RegisteredWait->WaitBlock);
        }

        //
        // Execute the user callback routine.
        //

        RegisteredWait->ThreadId = GetCurrentThreadId();
        (*RegisteredWait->UserCallback)(RegisteredWait->UserCallbackContext, WaitStatus);
        RegisteredWait->ThreadId = 0;

        //
        // If the *ExecuteOnlyOnce* is true or there is an unregister
        // in progress, set the state to INACTIVE. If any thread is waiting,
        // unpark it.
        //

        if (RegisteredWait->ExecuteOnlyOnce != FALSE || StateIsParker(OldState)) {
            if (StateIsParker(OldState)) {
                UnparkThread(OldState, WAIT_SUCCESS);
            } else {
                RegisteredWait->State = INACTIVE;
            }
            return;
        }

        //
        // We must re-register with the Waitable.
        // So, initialize the parker and execute the WaitAny prologue.
        //

        InitializeParker(&RegisteredWait->CbParker.Parker, 1);
        WAIT_ANY_PROLOGUE(RegisteredWait->Waitable, &RegisteredWait->CbParker.Parker,
                          &RegisteredWait->WaitBlock, WAIT_SUCCESS, &Ignored);

        //
        // Enable the unpark callback.
        //

        if ((WaitStatus = EnableUnparkCallback(&RegisteredWait->CbParker, RegisteredWait->Timeout,
                                               &RegisteredWait->RawTimer)) == WAIT_PENDING) {

            //
            // If the *State* field constains still our *busy* set it to ACTIVE.
            //

            if (RegisteredWait->State == MyBusy) {
                CasPointer(&RegisteredWait->State, MyBusy, ACTIVE);
            }
            return;
        }

        //
        // The waitable was already signalled. So, execute the unpark
        // callback inline.
        //

    } while (TRUE);
}