Fix for PR kern/22933

Avoid gcc3 pointer alias bugs caused by casting between struct callout
and struct callout_circq.
This commit is contained in:
scw 2003-09-25 10:44:11 +00:00
parent e045a0f96e
commit a3b1a08d1e
2 changed files with 47 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_timeout.c,v 1.10 2003/09/07 21:28:16 scw Exp $ */
/* $NetBSD: kern_timeout.c,v 1.11 2003/09/25 10:44:11 scw Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.10 2003/09/07 21:28:16 scw Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.11 2003/09/25 10:44:11 scw Exp $");
/*
* Adapted from OpenBSD: kern_timeout.c,v 1.15 2002/12/08 04:21:07 art Exp,
@ -139,40 +139,41 @@ do { \
* Circular queue definitions.
*/
#define CIRCQ_INIT(elem) \
#define CIRCQ_INIT(list) \
do { \
(elem)->cq_next = (elem); \
(elem)->cq_prev = (elem); \
(list)->cq_next_l = (list); \
(list)->cq_prev_l = (list); \
} while (/*CONSTCOND*/0)
#define CIRCQ_INSERT(elem, list) \
do { \
(elem)->cq_prev = (list)->cq_prev; \
(elem)->cq_next = (list); \
(list)->cq_prev->cq_next = (elem); \
(list)->cq_prev = (elem); \
(elem)->cq_prev_e = (list)->cq_prev_e; \
(elem)->cq_next_l = (list); \
(list)->cq_prev_l->cq_next_l = (elem); \
(list)->cq_prev_l = (elem); \
} while (/*CONSTCOND*/0)
#define CIRCQ_APPEND(fst, snd) \
do { \
if (!CIRCQ_EMPTY(snd)) { \
(fst)->cq_prev->cq_next = (snd)->cq_next; \
(snd)->cq_next->cq_prev = (fst)->cq_prev; \
(snd)->cq_prev->cq_next = (fst); \
(fst)->cq_prev = (snd)->cq_prev; \
(fst)->cq_prev_l->cq_next_l = (snd)->cq_next_l; \
(snd)->cq_next_l->cq_prev_l = (fst)->cq_prev_l; \
(snd)->cq_prev_l->cq_next_l = (fst); \
(fst)->cq_prev_l = (snd)->cq_prev_l; \
CIRCQ_INIT(snd); \
} \
} while (/*CONSTCOND*/0)
#define CIRCQ_REMOVE(elem) \
do { \
(elem)->cq_next->cq_prev = (elem)->cq_prev; \
(elem)->cq_prev->cq_next = (elem)->cq_next; \
(elem)->cq_next_l->cq_prev_e = (elem)->cq_prev_e; \
(elem)->cq_prev_l->cq_next_e = (elem)->cq_next_e; \
} while (/*CONSTCOND*/0)
#define CIRCQ_FIRST(elem) ((elem)->cq_next)
#define CIRCQ_EMPTY(elem) (CIRCQ_FIRST(elem) == (elem))
#define CIRCQ_FIRST(list) ((list)->cq_next_e)
#define CIRCQ_NEXT(elem) ((elem)->cq_next_e)
#define CIRCQ_LAST(elem,list) ((elem)->cq_next_l == (list))
#define CIRCQ_EMPTY(list) ((list)->cq_next_l == (list))
/*
* Some of the "math" in here is a bit tricky.
@ -379,8 +380,7 @@ softclock(void *v)
CALLOUT_LOCK(s);
while (!CIRCQ_EMPTY(&timeout_todo)) {
c = (struct callout *)CIRCQ_FIRST(&timeout_todo); /* XXX */
c = CIRCQ_FIRST(&timeout_todo);
CIRCQ_REMOVE(&c->c_list);
/* If due run it, otherwise insert it into the right bucket. */
@ -412,12 +412,13 @@ static void
db_show_callout_bucket(struct callout_circq *bucket)
{
struct callout *c;
struct callout_circq *p;
db_expr_t offset;
char *name;
for (p = CIRCQ_FIRST(bucket); p != bucket; p = CIRCQ_FIRST(p)) {
c = (struct callout *)p; /* XXX */
if (CIRCQ_EMPTY(bucket))
return;
for (c = CIRCQ_FIRST(bucket); /*nothing*/; c = CIRCQ_NEXT(&c->c_list)) {
db_find_sym_and_offset((db_addr_t)(intptr_t)c->c_func, &name,
&offset);
name = name ? name : "?";
@ -430,6 +431,9 @@ db_show_callout_bucket(struct callout_circq *bucket)
c->c_time - hardclock_ticks,
(int)((bucket - timeout_wheel) / WHEELSIZE),
(int)(bucket - timeout_wheel), (u_long) c->c_arg, name);
if (CIRCQ_LAST(&c->c_list, bucket))
break;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: callout.h,v 1.18 2003/07/20 16:25:58 he Exp $ */
/* $NetBSD: callout.h,v 1.19 2003/09/25 10:44:11 scw Exp $ */
/*-
* Copyright (c) 2000, 2003 The NetBSD Foundation, Inc.
@ -68,10 +68,26 @@
#ifndef _SYS_CALLOUT_H_
#define _SYS_CALLOUT_H_
/*
* The following funkyness is to appease gcc3's strict aliasing.
*/
struct callout;
struct callout_circq {
struct callout_circq *cq_next; /* next element */
struct callout_circq *cq_prev; /* previous element */
/* next element */
union {
struct callout *elem;
struct callout_circq *list;
} cq_next;
/* previous element */
union {
struct callout *elem;
struct callout_circq *list;
} cq_prev;
};
#define cq_next_e cq_next.elem
#define cq_prev_e cq_prev.elem
#define cq_next_l cq_next.list
#define cq_prev_l cq_prev.list
struct callout {
struct callout_circq c_list; /* linkage on queue */
@ -86,7 +102,7 @@ struct callout {
#define CALLOUT_INVOKING 0x0008 /* callout function is being invoked */
#define CALLOUT_INITIALIZER_SETFUNC(func, arg) \
{ { NULL, NULL }, func, arg, 0, 0 }
{ {{NULL}, {NULL}}, func, arg, 0, 0 }
#define CALLOUT_INITIALIZER CALLOUT_INITIALIZER_SETFUNC(NULL, NULL)