epoch(9) background information?
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Aug 24 13:37:38 UTC 2018
Hello,
I try currently to understand the epoch implementation in FreeBSD to
implement the API in RTEMS.
If I understood epoch_wait() correctly, then this function just busy
waits until all conditions are satisfied. This is all right, since all
other participants operate with thread dispatching disabled, so the time
can be only influenced by interrupts and actual work.
I have some questions to epoch_block_handler_preempt(). The caller of
epoch_wait_prempt() seems to depend on threads which are currently
blocked, so busy waiting is not a good idea. Some questions to the code:
/*
* epoch_block_handler_preempt is a callback from the ck code when
another thread is
* currently in an epoch section.
*/
static void
epoch_block_handler_preempt(struct ck_epoch *global __unused,
ck_epoch_record_t *cr,
void *arg __unused)
{
epoch_record_t record;
struct thread *td, *owner, *curwaittd;
struct epoch_thread *tdwait;
struct turnstile *ts;
struct lock_object *lock;
int spincount, gen;
int locksheld __unused;
record = __containerof(cr, struct epoch_record, er_record);
td = curthread;
locksheld = td->td_locks;
spincount = 0;
counter_u64_add(block_count, 1);
/*
* We lost a race and there's no longer any threads
* on the CPU in an epoch section.
*/
if (TAILQ_EMPTY(&record->er_tdlist))
return;
if (record->er_cpuid != curcpu) {
...
### this seems clear
}
/*
* Try to find a thread in an epoch section on this CPU
* waiting on a turnstile. Otherwise find the lowest
* priority thread (highest prio value) and drop our priority
* to match to allow it to run.
*/
TAILQ_FOREACH(tdwait, &record->er_tdlist, et_link) {
/*
* Propagate our priority to any other waiters to prevent us
* from starving them. They will have their original priority
* restore on exit from epoch_wait().
*/
curwaittd = tdwait->et_td;
if (!TD_IS_INHIBITED(curwaittd) && curwaittd->td_priority >
td->td_priority) {
critical_enter();
thread_unlock(td);
thread_lock(curwaittd);
### could we accidentally lower the priority here?
sched_prio(curwaittd, td->td_priority);
thread_unlock(curwaittd);
thread_lock(td);
critical_exit();
}
if (TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd) &&
((ts = curwaittd->td_blocked) != NULL)) {
...
### is this some sort of condition variable which wakes us up together
with the waiting thread?
}
}
### is this a yield operation, e.g. in case we still the highest
priority thread, then we run immediately again?
/*
* We didn't find any threads actually blocked on a lock
* so we have nothing to do except context switch away.
*/
counter_u64_add(switch_count, 1);
mi_switch(SW_VOL | SWT_RELINQUISH, NULL);
/*
* Release the thread lock while yielding to
* allow other threads to acquire the lock
* pointed to by TDQ_LOCKPTR(td). Else a
* deadlock like situation might happen. (HPS)
*/
thread_unlock(td);
thread_lock(td);
}
--
Sebastian Huber, embedded brains GmbH
Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone : +49 89 189 47 41-16
Fax : +49 89 189 47 41-09
E-Mail : sebastian.huber at embedded-brains.de
PGP : Public key available on request.
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
More information about the freebsd-hackers
mailing list