mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-30 06:18:19 +08:00
Critical bug fix for callouts
FreeBSD has two callout executors, one in software and one in hardware interrupt context. In libbsd, all callouts are executed by the timer server. Entirely remove the different execution contexts for libbsd. Previously, this was not properly done which could result an invalid callout_drain() sequence leading to system memory corruption.
This commit is contained in:
parent
3df89c0ef9
commit
6d9d7b1956
@ -164,7 +164,11 @@ struct cc_exec {
|
|||||||
*/
|
*/
|
||||||
struct callout_cpu {
|
struct callout_cpu {
|
||||||
struct mtx_padalign cc_lock;
|
struct mtx_padalign cc_lock;
|
||||||
|
#ifndef __rtems__
|
||||||
struct cc_exec cc_exec_entity[2];
|
struct cc_exec cc_exec_entity[2];
|
||||||
|
#else /* __rtems__ */
|
||||||
|
struct cc_exec cc_exec_entity;
|
||||||
|
#endif /* __rtems__ */
|
||||||
struct callout *cc_next;
|
struct callout *cc_next;
|
||||||
struct callout *cc_callout;
|
struct callout *cc_callout;
|
||||||
struct callout_list *cc_callwheel;
|
struct callout_list *cc_callwheel;
|
||||||
@ -182,11 +186,21 @@ struct callout_cpu {
|
|||||||
|
|
||||||
#define callout_migrating(c) ((c)->c_iflags & CALLOUT_DFRMIGRATION)
|
#define callout_migrating(c) ((c)->c_iflags & CALLOUT_DFRMIGRATION)
|
||||||
|
|
||||||
|
#ifndef __rtems__
|
||||||
#define cc_exec_curr(cc, dir) cc->cc_exec_entity[dir].cc_curr
|
#define cc_exec_curr(cc, dir) cc->cc_exec_entity[dir].cc_curr
|
||||||
#define cc_exec_drain(cc, dir) cc->cc_exec_entity[dir].cc_drain
|
#define cc_exec_drain(cc, dir) cc->cc_exec_entity[dir].cc_drain
|
||||||
|
#else /* __rtems__ */
|
||||||
|
#define cc_exec_curr(cc, dir) cc->cc_exec_entity.cc_curr
|
||||||
|
#define cc_exec_drain(cc, dir) cc->cc_exec_entity.cc_drain
|
||||||
|
#endif /* __rtems__ */
|
||||||
#define cc_exec_next(cc) cc->cc_next
|
#define cc_exec_next(cc) cc->cc_next
|
||||||
|
#ifndef __rtems__
|
||||||
#define cc_exec_cancel(cc, dir) cc->cc_exec_entity[dir].cc_cancel
|
#define cc_exec_cancel(cc, dir) cc->cc_exec_entity[dir].cc_cancel
|
||||||
#define cc_exec_waiting(cc, dir) cc->cc_exec_entity[dir].cc_waiting
|
#define cc_exec_waiting(cc, dir) cc->cc_exec_entity[dir].cc_waiting
|
||||||
|
#else /* __rtems__ */
|
||||||
|
#define cc_exec_cancel(cc, dir) cc->cc_exec_entity.cc_cancel
|
||||||
|
#define cc_exec_waiting(cc, dir) cc->cc_exec_entity.cc_waiting
|
||||||
|
#endif /* __rtems__ */
|
||||||
#ifdef SMP
|
#ifdef SMP
|
||||||
#define cc_migration_func(cc, dir) cc->cc_exec_entity[dir].ce_migration_func
|
#define cc_migration_func(cc, dir) cc->cc_exec_entity[dir].ce_migration_func
|
||||||
#define cc_migration_arg(cc, dir) cc->cc_exec_entity[dir].ce_migration_arg
|
#define cc_migration_arg(cc, dir) cc->cc_exec_entity[dir].ce_migration_arg
|
||||||
@ -497,7 +511,11 @@ callout_get_bucket(sbintime_t sbt)
|
|||||||
void
|
void
|
||||||
callout_process(sbintime_t now)
|
callout_process(sbintime_t now)
|
||||||
{
|
{
|
||||||
|
#ifndef __rtems__
|
||||||
struct callout *tmp, *tmpn;
|
struct callout *tmp, *tmpn;
|
||||||
|
#else /* __rtems__ */
|
||||||
|
struct callout *tmp;
|
||||||
|
#endif /* __rtems__ */
|
||||||
struct callout_cpu *cc;
|
struct callout_cpu *cc;
|
||||||
struct callout_list *sc;
|
struct callout_list *sc;
|
||||||
sbintime_t first, last, max, tmp_max;
|
sbintime_t first, last, max, tmp_max;
|
||||||
@ -665,8 +683,10 @@ callout_cc_add(struct callout *c, struct callout_cpu *cc,
|
|||||||
c->c_iflags |= CALLOUT_PENDING;
|
c->c_iflags |= CALLOUT_PENDING;
|
||||||
c->c_iflags &= ~CALLOUT_PROCESSED;
|
c->c_iflags &= ~CALLOUT_PROCESSED;
|
||||||
c->c_flags |= CALLOUT_ACTIVE;
|
c->c_flags |= CALLOUT_ACTIVE;
|
||||||
|
#ifndef __rtems__
|
||||||
if (flags & C_DIRECT_EXEC)
|
if (flags & C_DIRECT_EXEC)
|
||||||
c->c_iflags |= CALLOUT_DIRECT;
|
c->c_iflags |= CALLOUT_DIRECT;
|
||||||
|
#endif /* __rtems__ */
|
||||||
c->c_func = func;
|
c->c_func = func;
|
||||||
c->c_time = sbt;
|
c->c_time = sbt;
|
||||||
c->c_precision = precision;
|
c->c_precision = precision;
|
||||||
@ -1097,7 +1117,11 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
|
|||||||
{
|
{
|
||||||
sbintime_t to_sbt, precision;
|
sbintime_t to_sbt, precision;
|
||||||
struct callout_cpu *cc;
|
struct callout_cpu *cc;
|
||||||
|
#ifndef __rtems__
|
||||||
int cancelled, direct;
|
int cancelled, direct;
|
||||||
|
#else /* __rtems__ */
|
||||||
|
int cancelled;
|
||||||
|
#endif /* __rtems__ */
|
||||||
int ignore_cpu=0;
|
int ignore_cpu=0;
|
||||||
|
|
||||||
cancelled = 0;
|
cancelled = 0;
|
||||||
@ -1110,6 +1134,7 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
|
|||||||
}
|
}
|
||||||
callout_when(sbt, prec, flags, &to_sbt, &precision);
|
callout_when(sbt, prec, flags, &to_sbt, &precision);
|
||||||
|
|
||||||
|
#ifndef __rtems__
|
||||||
/*
|
/*
|
||||||
* This flag used to be added by callout_cc_add, but the
|
* This flag used to be added by callout_cc_add, but the
|
||||||
* first time you call this we could end up with the
|
* first time you call this we could end up with the
|
||||||
@ -1122,6 +1147,7 @@ callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t prec,
|
|||||||
}
|
}
|
||||||
KASSERT(!direct || c->c_lock == NULL,
|
KASSERT(!direct || c->c_lock == NULL,
|
||||||
("%s: direct callout %p has lock", __func__, c));
|
("%s: direct callout %p has lock", __func__, c));
|
||||||
|
#endif /* __rtems__ */
|
||||||
cc = callout_lock(c);
|
cc = callout_lock(c);
|
||||||
/*
|
/*
|
||||||
* Don't allow migration of pre-allocated callouts lest they
|
* Don't allow migration of pre-allocated callouts lest they
|
||||||
@ -1260,7 +1286,11 @@ _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *))
|
|||||||
{
|
{
|
||||||
struct callout_cpu *cc, *old_cc;
|
struct callout_cpu *cc, *old_cc;
|
||||||
struct lock_class *class;
|
struct lock_class *class;
|
||||||
|
#ifndef __rtems__
|
||||||
int direct, sq_locked, use_lock;
|
int direct, sq_locked, use_lock;
|
||||||
|
#else /* __rtems__ */
|
||||||
|
int sq_locked, use_lock;
|
||||||
|
#endif /* __rtems__ */
|
||||||
int cancelled, not_on_a_list;
|
int cancelled, not_on_a_list;
|
||||||
#ifdef __rtems__
|
#ifdef __rtems__
|
||||||
(void)old_cc;
|
(void)old_cc;
|
||||||
@ -1285,13 +1315,13 @@ _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *))
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
use_lock = 0;
|
use_lock = 0;
|
||||||
|
#ifndef __rtems__
|
||||||
if (c->c_iflags & CALLOUT_DIRECT) {
|
if (c->c_iflags & CALLOUT_DIRECT) {
|
||||||
direct = 1;
|
direct = 1;
|
||||||
} else {
|
} else {
|
||||||
direct = 0;
|
direct = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
sq_locked = 0;
|
sq_locked = 0;
|
||||||
old_cc = NULL;
|
old_cc = NULL;
|
||||||
again:
|
again:
|
||||||
|
@ -48,7 +48,9 @@
|
|||||||
#define CALLOUT_SHAREDLOCK 0x0020 /* callout lock held in shared mode */
|
#define CALLOUT_SHAREDLOCK 0x0020 /* callout lock held in shared mode */
|
||||||
#define CALLOUT_DFRMIGRATION 0x0040 /* callout in deferred migration mode */
|
#define CALLOUT_DFRMIGRATION 0x0040 /* callout in deferred migration mode */
|
||||||
#define CALLOUT_PROCESSED 0x0080 /* callout in wheel or processing list? */
|
#define CALLOUT_PROCESSED 0x0080 /* callout in wheel or processing list? */
|
||||||
|
#ifndef __rtems__
|
||||||
#define CALLOUT_DIRECT 0x0100 /* allow exec from hw int context */
|
#define CALLOUT_DIRECT 0x0100 /* allow exec from hw int context */
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
#define C_DIRECT_EXEC 0x0001 /* direct execution of callout */
|
#define C_DIRECT_EXEC 0x0001 /* direct execution of callout */
|
||||||
#define C_PRELBITS 7
|
#define C_PRELBITS 7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user