Volatile magic

Pavel Machek (pavel@elf.ucw.cz)
Fri, 23 Jan 1998 23:54:17 +0100


Hi!

2.0.33 kernel broke when compiled with gcc 2.8.0. Everyone saw
that. Then, simple fix for single procedure appeared, and now it seems
like everything is right.

*IT PROBABLY IS NOT*

There are more pieces like that *(type *)& in sys_iopl(). I did a bit
of grep for such constructs, and it seems to me like pretty much code
may be broken. [I probably included too many situations. I just can
not judge that].

Patch to scheduler is attached, it kills comment duplication, and adds
one volatile, which is IMO needed.

Please note that if you want to know if long is 64bit, #if ((~0UL) ==
0xffffffff) is not good way - what about crosscompiling? I already
posted one patch to solve this, it was later superceeded by mj's
patch.

--- clean/kernel/sched.c Wed Jan 14 21:46:09 1998
+++ linux/kernel/sched.c Fri Jan 23 20:03:15 1998
@@ -435,11 +435,6 @@
prev->has_cpu = 0;
#endif

-/*
- * Note! there may appear new tasks on the run-queue during this, as
- * interrupts are enabled. However, they will be put on front of the
- * list, so our list starting at "p" is essentially fixed.
- */
/* this is the scheduler proper: */
{
int c = -1000;
@@ -761,10 +758,7 @@
struct timer_struct timer_table[32];

/*
- * Hmm.. Changed this, as the GNU make sources (load.c) seems to
- * imply that avenrun[] is the standard name for this kind of thing.
- * Nothing else seems to be standardized: the fractional size etc
- * all seem to differ on different machines.
+ * This is famous 'load average'
*/
unsigned long avenrun[3] = { 0,0,0 };

@@ -1094,16 +1088,16 @@

static void timer_bh(void)
{
update_times();
run_old_timers();
run_timer_list();
}

void do_timer(struct pt_regs * regs)
{
- (*(unsigned long *)&jiffies)++;
+ (*(unsigned long * volatile)&jiffies)++;
lost_ticks++;
mark_bh(TIMER_BH);
if (!user_mode(regs))
lost_ticks_system++;
if (tq_timer)
@@ -1480,6 +1476,7 @@
printk(stat_nam[p->state]);
else
printk(" ");
+/* This is broken! What about crosscompiling?! */
#if ((~0UL) == 0xffffffff)
if (p == current)
printk(" current ");

./fs/binfmt_elf.c: *(struct pt_regs *)&prstatus.pr_reg = *regs;
./fs/ufs/ufs_inode.c: inode->i_rdev = (kdev_t)SWAB64(*(__u64*)&ufsip->ui_db);
./net/core/filter.c: A = ntohl(*(long*)&data[k]);
(more)
./net/ipv4/icmp.c: mask = *(u32*)&icmph[1];
./net/ipv4/ip_forward.c: unsigned h = ((*(u8*)&rt->key.dst)^(*(u8*)&rt->key.src))&NETDEV_FASTROUTE_HMASK;
./net/ipv4/fib_hash.c: return *(fn_hash_idx_t*)&h;
./net/wanrouter/wanmain.c: *((unsigned short*)&skb->data[4]) = htons(skb->protocol);
./net/wanrouter/wanmain.c: ethertype = *((unsigned short*)&skb->data[cnt+4]);
./drivers/net/zlib.c: if (*(ush*)&buf != 0) return buf;
(more)
./drivers/net/de4x5.c: if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
(more occurences in de4x5.c...)
./drivers/net/seeq8005.c: printk("%02x ",*(p++)&0xff);
./drivers/net/strip.c: *(MetricomAddress*)&strip_info->true_dev_addr = zero_address;
./drivers/net/strip.c: *(MetricomAddress*)&dev->broadcast = broadcast_address;
./drivers/net/sdladrv.c: *(short*)&data[0x0D] = 128; /* default X.25 data size */
./drivers/net/sdladrv.c: *(short*)&data[0x0F] = 128; /* maximum X.25 data size */
./drivers/block/ide-cd.c: *(int *)&devinfo->speed = CDROM_CONFIG_FLAGS (drive)->max_speed;
./drivers/block/ide-cd.c: *(int *)&devinfo->capacity = nslots;
./drivers/block/amiflop.c: *(ulong *)&hdr.labels[0], *(ulong *)&hdr.labels[4],
./drivers/block/amiflop.c: *(ulong *)&hdr.labels[8], *(ulong *)&hdr.labels[12],
./drivers/char/rocket.c: sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
(more occurences in rocket.c)
./drivers/scsi/ultrastor.c: *(char *)&config_1 = inb(CONFIG(config.port_address + 0));
./drivers/scsi/ultrastor.c: *(char *)&config_2 = inb(CONFIG(config.port_address + 1));
./drivers/scsi/u14-34f.c: *(char *)&config_1 = inb(port_base + REG_CONFIG1);
./drivers/scsi/u14-34f.c: *(char *)&config_2 = inb(port_base + REG_CONFIG2);
./drivers/scsi/advansys.c:#define LO_BYTE(x) (*((__u8 *)&x))
./drivers/scsi/advansys.c:#define LO_WORD(x) (*((__u16 *)&x))
./drivers/scsi/gdth.c: cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]);
(...)
./drivers/sound/lowlevel/awe_wave.c: drum_flags = *(unsigned int*)&event[4];
./drivers/fc4/fc.c: FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo))
./drivers/fc4/fc.c: *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo,
./drivers/fc4/fc.c: *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo);
./drivers/fc4/soc.c: *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
./drivers/fc4/soc.c: *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
./drivers/fc4/soc.c: *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
./arch/i386/math-emu/reg_convert.c: *(long long *)&(x->sigl) = *(const long long *)&(a->sigl);
./arch/i386/kernel/vm86.c:#define IP(regs) (*(unsigned short *)&((regs)->eip))
./arch/i386/kernel/vm86.c:#define SP(regs) (*(unsigned short *)&((regs)->esp))
./arch/i386/kernel/vm86.c:#define VFLAGS (*(unsigned short *)&(current->tss.v86flags))
./arch/i386/kernel/io_apic.c: *(((int *)&entry)+0) = io_apic_read(0x10+irq*2);
(*many* occurences in io_apic.c)
./arch/sparc/kernel/irq.c: if (*((unsigned char *)&global_irq_lock))
./arch/sparc/kernel/irq.c: } while (*((unsigned char *)&global_irq_lock));
./arch/sparc/kernel/irq.c: while (*((unsigned char *)&global_irq_lock)) {
(hey, this is almost certainly broken on sparc - leading to ..?)
./arch/sparc/kernel/setup.c: *((unsigned char *)&global_irq_lock) = 0;
./arch/sparc/kernel/setup.c: *((unsigned char *)&global_bh_lock) = 0;
./arch/sparc/lib/debuglocks.c: (*((unsigned short *)&rw->lock))++;
(more)
./arch/sparc/ap1000/apmmu.c: *(((unsigned long long *)MC_MMU_TLB4K) + ((vaddr>>12)&0xFF)) = 0;
./arch/mips/kernel/irixelf.c: *(struct pt_regs *)&prstatus.pr_reg = *regs;
./arch/ppc/mm/fault.c: *((unsigned long *)(&p)), *((long *)&p+1),
./arch/ppc/kernel/irq.c: if (*((unsigned char *)&global_irq_lock))
./arch/ppc/kernel/irq.c: } while (*((unsigned char *)&global_irq_lock));
./arch/sparc64/kernel/unaligned.c: first = *(u64 *)&f->regs[freg];
./arch/sparc64/kernel/unaligned.c: second = *(u64 *)&f->regs[freg+2];
./arch/sparc64/kernel/unaligned.c: value = *(u64 *)&f->regs[freg];

-- 
I'm really pavel@atrey.karlin.mff.cuni.cz. 	   Pavel
Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).