/* * 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"); }
/* * 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"); }
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; }
/* * 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); }