Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Aug 1996 07:13:54 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        msmith@atrad.adelaide.edu.au, nate@mt.sri.com
Cc:        freebsd-hackers@freefall.freebsd.org, ponds!rivers@dg-rtp.dg.com, ponds!rivers@freefall.freebsd.org, sag.space.lockheed.com!handy@dg-rtp.dg.com
Subject:   Re: sio issues (silo overflows on a pentium, locked in ttywait, etc...)
Message-ID:  <199608142113.HAA04204@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>see the overflows affecting me much.  The funny thing is I don't see
>overflows on the SLIP server box which is also running 16550A UARTS and
>is running multiple sessions, but it's not running X and never touches
>the hard disk.  (Basically it's the same hardware on both boxes, 486/66
>with 16MB, although my box has an Adaptec 1542B and the server box is
>IDE).

Upgrade everything to IDE :-).  Some busmastering SCSI controllers hog
the bus for too long (e.g., Ultrastor U34Fs sometimes hog it for 160 us
so they are unusable with single 8250s at speeds > 57600, unusable with
single 16550s at speeds > 115200, and barely usable with single UARTS at
exactly these speeds.  The aha driver sets the bus on/off times to 7/4,
so there should be no problems with single UARTs.

Here is my throwaway lkm and auxiliarly program for testing bus hogging.
Usage: make and load the lkm.  Run modstat to see what its syscall
number is.  It will be 210 if there are no other syscall-lkms.  If
the number isn't 210, then change 210 in hogtime.c to the number.
Compile and run the hogtime utility.  Start processes to exercise
the bus hog(s), e.g., `dd bs=1024k </dev/rsd0 >/dev/null'.  Watch the
output from hogtime.

Bruce

---
lkm/hogtime/Makefile
---
BINDIR=	/tmp
SRCS=	mycall.c
KMOD=	newsyscall_mod
NOMAN=	none

CLEANFILES+= ${KMOD}

.include <bsd.kmod.mk>
---
lkm/hogtime/mycall.c
---
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/kernel.h>
#include <sys/sysent.h>
#include <sys/lkm.h>

#define mycall	hogtime

static int mycall(struct proc *p, void *uap, int *retval);

static struct sysent newent = { 0, mycall, };
MOD_SYSCALL("newsyscall_mod", -1, &newent);

extern int newsyscall_mod(struct lkm_table *lkmtp, int cmd, int ver);
int newsyscall_mod(struct lkm_table *lkmtp, int cmd, int ver)
{
	DISPATCH(lkmtp, cmd, ver, lkm_nullcmd, lkm_nullcmd, lkm_nullcmd)
}

#ifdef MEMTEST
#define ADDR	0xf00d4000
#endif

static int hogtime(struct proc *p, void *uap, int *retval)
{
	int i, j, start, finish, delta;
#ifdef MADDR
	volatile u_char *maddr;
#endif
	long usec;

	disable_intr();
	for (i = 0; i < 2; ++i) {
		/*
		 * i = 0: load cache, if any.  i = 1: calibrate and count.
		 * Calibration must be combined with counting so that the
		 * same i/o wait states apply to both.
		 */
#ifdef MEMTEST
		maddr = (volatile u_char *)ADDR;
#endif
		outb(0x43, 0x00);
		start = inb(0x40);
		start |= inb(0x40) << 8;
#ifndef MEMTEST
		inb(0x43);	/* 7 dummy i/o's to get 10 altogether */
		inb(0x43);
		inb(0x43);
		inb(0x43);
		inb(0x43);
		inb(0x43);
		inb(0x43);
		for (j = 0; j < 100; ++j)
			;
#else
		for (j = 0; j < 0x100; j += 2)
			*(maddr + j);
#endif
		outb(0x43, 0x00);
		finish = inb(0x40);
		finish |= inb(0x40) << 8;
	}
	enable_intr();
	delta = start - finish;
#define	TIMER_FREQ	1193182
#define	LATCH		((TIMER_FREQ + hz / 2) / hz)
	if (delta < 0)
		delta += LATCH;
	usec = (delta * tick + LATCH / 2) / LATCH;
	*retval = usec;
	return 0;
}

static long microtime_buf[4096];

static int microtime_test(struct proc *p, void *uap, int *retval)
{
    int i;
    struct timeval tv;
    struct timeval tvp;

    microtime(&tvp);
    for (i = 0; i < 4096; ++i)
    {
	microtime(&tv);
	microtime_buf[i] = tv.tv_usec - tvp.tv_usec
			   + 1000000 * (tv.tv_sec - tvp.tv_sec);
	tvp = tv;
    }
    return 0;
}
---
bin/hogtime.c
---
#include <limits.h>
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    for (;;)
    {
	int i;
	long max = 0;
	long min = LONG_MAX;
	long tot = 0;
	int val;

	for (i = 0; i < 10000; ++i)
	{
	    val = syscall(210);
	    if (val == -1)
	    {
		perror("syscall");
		exit(1);
	    }
	    if (max < val)
		max = val;
	    if (min > val)
		min = val;
	    tot += val;
	}
	printf("min = %ld, av = %ld, max = %ld\n", min, tot / i, max);
    }
    return 0;
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199608142113.HAA04204>