9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] A quite amusing thing...
@ 2003-02-22 19:17 Maksim Radziwill
  2003-02-22 20:30 ` Russ Cox
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Maksim Radziwill @ 2003-02-22 19:17 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 5773 bytes --]

Hi everyone,
I recently have found an amusing thing between (FSD-)Amoeba and Plan9 :
The code for cpu speed identification is the same ;)

Here I paste it. If you don't believe youre eyes check out
/sys/src/9/pc/i8253.c in the plan9 system
/profile/module/amoeba/src/machdep/dev/ibm_at/timer/pit.c in the
FSD-Amoeba system
(the sys source must be installed of course)

You can get FSD-Amoeba at fsd-amoeba.sourceforge.net it is the
continuation of
the original Amoeba project (www.cs.vu.nl/pub/amoeba) who has been
terminated
in 1996.

++++++ i8253.c the guesscpuhz function
void
guesscpuhz(int aalcycles)
{
      int cpufreq, loops, incr, x, y;
      uvlong a, b;

      /* find biggest loop that doesn't wrap */
      incr = 16000000/(aalcycles*HZ*2);
      x = 2000;
      for(loops = incr; loops < 64*1024; loops += incr) {

            /*
             *  measure time for the loop
             *
             *                MOVL  loops,CX
             *    aaml1:           AAM
             *                LOOP  aaml1
             *
             *  the time for the loop should be independent of external
             *  cache and memory system since it fits in the execution
             *  prefetch buffer.
             *
             */
            outb(Tmode, Latch0);
            if(m->havetsc)
                  rdtsc(&a);
            x = inb(T0cntr);
            x |= inb(T0cntr)<<8;
            aamloop(loops);
            outb(Tmode, Latch0);
            if(m->havetsc)
                  rdtsc(&b);
            y = inb(T0cntr);
            y |= inb(T0cntr)<<8;
            x -= y;

            if(x < 0)
                  x += Freq/HZ;

            if(x > Freq/(3*HZ))
                  break;
      }

      /*
       *  figure out clock frequency and a loop multiplier for delay().
       *  n.b. counter goes up by 2*Freq
       */
      cpufreq = loops*((aalcycles*2*Freq)/x);
      m->loopconst = (cpufreq/1000)/aalcycles;  /* AAM+LOOP's for 1 ms
*/

      if(m->havetsc){

            /* counter goes up by 2*Freq */
            b = (b-a)<<1;
            b *= Freq;
            b /= x;

            /*
             *  round to the nearest megahz
             */
            m->cpumhz = (b+500000)/1000000L;
            m->cpuhz = b;
      } else {
            /*
             *  add in possible 0.5% error and convert to MHz
             */
            m->cpumhz = (cpufreq + cpufreq/200)/1000000;
            m->cpuhz = cpufreq;
      }

      i8253.hz = Freq<<Tickshift;
}

+++++ Amoeba's pit.c cpuspeed function

/* For cpu speed measurement. We need timer access. */

void
cpuspeed(int aalcycles, int havecycleclock)
{
        int cpufreq, loops, incr, x, y;
        unsigned long ax1,dx1,ax2,dx2,a,b;

        pit_init();

        /* find biggest loop that doesn't wrap */
        incr = 16000000/(aalcycles*HZ*2);
        x = 2000;
        for(loops = incr; loops < 64*1024; loops += incr) {

                /*
                 *  measure time for the loop
                 *
                 *                        MOVL        loops,CX
                 *        aaml1:                 AAM
                 *                        LOOP        aaml1
                 *
                 *  the time for the loop should be independent of
external
                 *  cache and memory system since it fits in the
execution
                 *  prefetch buffer.
                 *
                 */

                /* Beware of counter reset's (wraps)... */

                /* Read the cpu internal clock if available */
                if(havecycleclock)
                        rdmsr(0x10, &ax1,&dx1);
                x = (int)pit_channel0();

                aamloop(loops);

                if(havecycleclock)
                        rdmsr(0x10, &ax2,&dx2);

                y = (int)pit_channel0();

                x -= y;

                if(x < 0)
                        x += PIT_FREQ/PIT_HZ;

                if(x > PIT_FREQ/(3*PIT_HZ))
                        break;
        }

        /*
         *  figure out clock frequency and a loop multiplier for
delay().
         *  n.b. counter goes up by 2*PIT_FREQ
         */
        cpufreq = loops*((aalcycles*PIT_FREQ)/x);
        cpu.loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1ms
*/

        /* check aalcycle value */
        if(kernel_option("cud") == 1)
                printf("cpuspeed: aalcycle MHz=%d\n",
                        (cpufreq + cpufreq/200)/1000000);

        if(havecycleclock){


                if(dx2 == dx1)
                        b = (ax2-ax1);
                else        /* counter wrap */
                        b = (ax2+0xffffffff-ax1);

                b /= x;
                b *= PIT_FREQ;


                /*
                 *  round to the nearest megahz
                 */
                cpu.cpumhz = (b+500000)/1000000L;
                cpu.cpuhz = b;
        } else {
                /*
                 *  add in possible 0.5% error and convert to MHz
                 */
                cpu.cpumhz = (cpufreq + cpufreq/200)/1000000;
                cpu.cpuhz = cpufreq;
        }

}


The thing is even more amusing since I heard someone saying plan9 is
written from the ground up... ;)

Hmm... It is possible too that Amoeba developer's have copied this code
but I doubt it.
Or maybe I'm missing something and the code comes from an other external
source...
(Don't forget these all are only hypotheses)

If someone could explain this it would be great, since I would like to
know the
only real true (story) ;)

Maks,


[-- Attachment #2: Type: text/html, Size: 69140 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-22 19:17 [9fans] A quite amusing thing Maksim Radziwill
@ 2003-02-22 20:30 ` Russ Cox
  2003-02-22 20:51 ` David Presotto
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Russ Cox @ 2003-02-22 20:30 UTC (permalink / raw)
  To: 9fans

That _is_ fairly amusing.

We've had a form of that code (including the big
comment) in our source tree since July 15, 1994.
But the 1994 code didn't have the for loop to run
until loops got big enough (it assumed 10000 was
enough) and it didn't have all the clock frequency
stuff (which got added later).

So either Plan 9 copied Amoeba back in 1994 (before
the original project was terminated) and has been
secretly tracking the code since then, or Amoeba copied
Plan 9 some time later after the code was changed to
look more like it does today.  I know where my money is.

Also, I downloaded the original Amoeba code and the
pit.c looked nothing like the Plan 9 code as of 1996.

Below you'll find Plan 9's clock.c from 1994, Amoeba's
pit.c from 1996, and Amoeba's pit.c from today.
Note the difference between the last two.  Sure looks like

 * Stefan Bosse (12/1999-7/2000)
 * sbosse@physik.uni-bremen.de
 *
 * -> pit_hw_milli now default routine with 1ms resolution
 * -> cpuspeed measurement and delay loop reference

copied the Plan 9 code.

> Hmm... It is possible too that Amoeba developer's have copied this code
> but I doubt it.

Why?

Russ

/* --rw-rw-r-- M 3014 jmk sys 2766 Jul 15  1994 sys/src/brazil/pc/clock.c */

void
clockinit(void)
{
	ulong x, y;	/* change in counter */
	ulong cycles, loops;

	/*
	 *  set vector for clock interrupts
	 */
	setvec(Clockvec, clock, 0);

	/*
	 *  set clock for 1/HZ seconds
	 */
	outb(Tmode, Load0|Square);
	outb(T0cntr, (Freq/HZ));	/* low byte */
	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */

	/*
	 *  measure time for the loop
	 *
	 *			MOVL	loops,CX
	 *	aaml1:	 	AAM
	 *			LOOP	aaml1
	 *
	 *  the time for the loop should be independent from external
	 *  cache's and memory system since it fits in the execution
	 *  prefetch buffer.
	 *
	 */
	loops = 10000;
	outb(Tmode, Latch0);
	x = inb(T0cntr);
	x |= inb(T0cntr)<<8;
	aamloop(loops);
	outb(Tmode, Latch0);
	y = inb(T0cntr);
	y |= inb(T0cntr)<<8;
	x -= y;

	/*
	 *  counter  goes at twice the frequency, once per transition,
	 *  i.e., twice per the square wave
	 */
	x >>= 1;

	/*
 	 *  figure out clock frequency and a loop multiplier for delay().
	 */
	switch(cputype = x86()){
	case 386:
		cycles = 30;
		break;
	case 486:
		cycles = 24;
		break;
	default:
		cycles = 23;
		break;
	}
	cpufreq = (cycles*loops) * (Freq/x);
	loopconst = (cpufreq/1000)/cycles;	/* AAM+LOOP's for 1 ms */
}


/*	@(#)pit.c	1.4	94/04/06 09:23:12 */
/*
 * Copyright 1994 Vrije Universiteit, The Netherlands.
 * For full copyright and restrictions on use see the file COPYRIGHT in the
 * top level of the Amoeba distribution.
 */

/*
 * pit.c
 *
 * Driver for the 8254 timer (PIT). The i8254 timer has three timer channels
 * of which only one (channel 0) is available for timer interrupts. The other
 * channels are used for the speaker and memory refresh.
 *
 * Author:
 *	Leendert van Doorn
 */
#include <amoeba.h>
#include <assert.h>
INIT_ASSERT
#include <fault.h>
#include <bool.h>
#include "sys/proto.h"
#include "i386_proto.h"
#include "pit.h"

#ifndef PIT_DEBUG
#define	PIT_DEBUG	0
#endif

static int pit_debug;			/* current debug level */

#ifdef notyet
static uint32 pit_hw_milli();
#endif
static void pit_intr();

/*
 * Initialize channel 0 of the i8254A timer
 */
void
pit_init()
{
    register uint32 counter = (PIT_FREQ * PIT_INTERVAL) / 1000L;

#ifndef NDEBUG
    if ((pit_debug = kernel_option("pit")) == 0)
	pit_debug = PIT_DEBUG;
    if (pit_debug > 1)
	printf("pit_init(), pit_interval = 0x%x (%d), counter = %x\n",
	    PIT_INTERVAL, PIT_INTERVAL, counter);
#endif

    /* set timer to run continuously */
    assert(counter <= 0xFFFF);
    out_byte(PIT_MODE, PIT_MODE3);
    out_byte(PIT_CH0, (int) (counter & 0xFF));
    out_byte(PIT_CH0, (int) ((counter >> 8) & 0xFF));

#ifdef notyet
    /* I still have to thoroughly test this */
    set_hw_milli(pit_hw_milli);
#endif

    setirq(PIT_IRQ, pit_intr);
    pic_enable(PIT_IRQ);
}

/*
 * Read i8254's channel 0 counter. The counter decrements at twice the
 * timer frequency (one full cycle for each half of a square wave).
 */
uint16
pit_channel0()
{
    register uint16 counter;

    out_byte(PIT_MODE, PIT_LC);
    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
    return counter;
}

/*
 * Delay for at least ``msec'' milli seconds
 */
void
pit_delay(msec)
    int msec;
{
    register uint16 current, previous, diff;
    register uint32 total;

    /*
     * The counter decrements at twice the timer frequency
     * (one full cycle for each half of a square wave).
     */
    diff = 100; /* just in case */
    total = (uint32) msec * (2 * PIT_FREQ / 1000);
    previous = pit_channel0();
    for (;;) {
	current = pit_channel0();
	if (current < previous)
	    diff = previous - current;
	if (diff >= total)
	    break;
	total -= diff;
	previous = current;
    }
}

#ifdef notyet
/*
 * Return number of actual milli-seconds that have passed
 */
static uint32
pit_hw_milli()
{
    extern uint32 milli_uptime;
    register uint32 milli;
    register int flags;
    uint16 counter;
    int status;

    flags = get_flags(); disable();
    out_byte(PIT_MODE, PIT_RB);
    out_byte(PIT_MODE, 0xC2);
    status = in_byte(PIT_CH0);
    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
    milli = milli_uptime + (PIT_INTERVAL / 2) *
	(counter / (PIT_FREQ * PIT_INTERVAL) / 1000L);
    if ((status & 0x80) == 0) milli += PIT_INTERVAL/2;
    set_flags(flags);
    return milli;
}
#endif

/*
 * The actual clock interrupt
 */
/* ARGSUSED */
static void
pit_intr(reason, frame)
    int reason;
    struct fault *frame;
{
    void sweeper_run();
    void flp_motoroff();
    extern int motortime;

#ifdef MCA
    /* ps/2 clock needs to be told to stop interrupting */
    out_byte(0x61, in_byte(0x61) | 0x80);
#endif

    enqueue(sweeper_run, (long) PIT_INTERVAL);

#if (defined(ISA) || defined(MCA)) && !defined(NOFLOPPY)
    /* stop running floppy motor */
    if (motortime != 0 && --motortime == 0)
	flp_motoroff();
#endif
}


/*
 * This file is part of the FIREBALL AMOEBA System.
 *
 *
 * Last modified:
 *		18/02/01
 *
 * Stefan Bosse (12/1999-7/2000)
 * sbosse@physik.uni-bremen.de
 *
 * -> pit_hw_milli now default routine with 1ms resolution
 * -> cpuspeed measurement and delay loop reference
 *
 *
 *
 * FIREBALL AMOEBA is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2.
 *
 * The FIREBALL AMOEBA is distributed in the hope that it will be usefull,
 * but WITHOUT ANY WARRANTY; without even implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * Original Copyright: Vrije Universiteit, The Netherlands.
 */




/*
 * pit.c
 *
 * Driver for the 8254 timer (PIT). The i8254 timer has three timer channels
 * of which only one (channel 0) is available for timer interrupts. The other
 * channels are used for the speaker and memory refresh.
 *
 * Author:
 *	Leendert van Doorn
 */


#include <amoeba.h>
#include <assert.h>
INIT_ASSERT
#include <fault.h>
#include <bool.h>
#include "sys/proto.h"
#include "i386_proto.h"
#include <irq.h>
#include "pit.h"
#include <cpu.h>

#ifndef PIT_DEBUG
#define	PIT_DEBUG	0
#endif

#ifdef STATISTICS
static unsigned long pit_hw_milli_count=0;
static unsigned long pit_hw_milli_wrap1=0;
static unsigned long pit_hw_milli_wrap2=0;
static unsigned long pit_delay_count=0;
#endif

static int pit_debug;			/* current debug level */
static int initialized=0;

#ifdef PIT_HW_MILLI
static uint32 pit_hw_milli();
#endif
static void pit_intr();

/*
 * milli_uptime will be incremented in sweeper_run, but it's delayed
 * because of enqueue() handling.
 * milli_uptime should be handled ***here***.
 * Hack: Local we use timer_ticks for pit_hw_milli(), incremented in low
 * level ISR below...
 */
unsigned long timer_ticks=0;

/* for time monotony checking; we have a serious problem with
 * this faulty timer hardware
 */
static unsigned long last_time=0;

/*
 * Initialize channel 0 of the i8254A timer
 */
void
pit_init()
{
    register uint32 counter = (PIT_FREQ * PIT_INTERVAL) / 1000L;


    if(!initialized)
    {

	initialized=1;
#ifndef NDEBUG
	if ((pit_debug = kernel_option("pit")) == 0)
		pit_debug = PIT_DEBUG;
	if (pit_debug > 1)
		printf("pit_init(), pit_interval = 0x%x (%d), counter = %x\n",
		       PIT_INTERVAL, PIT_INTERVAL, counter);
#endif

	/* set timer to run continuously */
	assert(counter <= 0xFFFF);

	if(check_region(PIT_CH0,4)<0)
		panic("Some fool allocated timer ports");
	request_region(PIT_CH0,4,"PIT");

	out_byte(PIT_MODE, PIT_MODE2);

	out_byte(PIT_CH0, (int) (counter & 0xFF));
	out_byte(PIT_CH0, (int) ((counter >> 8) & 0xFF));

#ifdef PIT_HW_MILLI
	/* I still have to thoroughly test this */
	/* SB: still timer wrap problems; but time monotonie is guranteed */
	set_hw_milli(pit_hw_milli);
#endif

	if(request_irq(PIT_IRQ,
		       pit_intr,
		       SA_NORMAL,
		       "PIT",
		       (void *)NULL)!=0)
		panic("Some fool allocated timer irq");

	enable_irq(PIT_IRQ);
	/*pic_enable(PIT_IRQ);*/
    }
}

/*
 * Read i8254's channel 0 counter. The counter decrements at twice the
 * timer frequency (one full cycle for each half of a square wave).
 */
uint16
pit_channel0()
{
    register uint16 counter;
    unsigned long flags;

    save_flags(flags);cli();
    out_byte(PIT_MODE, PIT_LC);
    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
    restore_flags(flags);
    return counter;
}

/*
 * Delay for at least ``msec'' milli seconds
 */
void
pit_delay(msec)
    int msec;
{
    register uint16 current, previous, diff;
    register uint32 total;


#ifdef STATISTICS
    pit_delay_count++;
#endif
    /*
     * The counter decrements at twice the timer frequency
     * (one full cycle for each half of a square wave).
     */
    diff = 100; /* just in case */
    total = (uint32) msec * (PIT_FREQ / 1000);
    previous = pit_channel0();
    for (;;) {
	current = pit_channel0();
	if (current < previous)
	    diff = previous - current;
	if (diff >= total)
	    break;
	total -= diff;
	previous = current;
    }
}


#ifdef PIT_HW_MILLI
/*
 * Return number of actual milli-seconds that have passed
 */
static uint32
pit_hw_milli()
{
    extern uint32 milli_uptime;
    register uint32 milli;
    uint16 counter,counter2;
    int status,status2;
    unsigned long flags;
    unsigned long ticks=timer_ticks;



#ifdef STATISTICS
    pit_hw_milli_count++;
#endif

    save_flags(flags);cli();
    /* Select timer0 and latch counter value. */
    out_byte(PIT_MODE,PIT_LC);
    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
    restore_flags(flags);

    milli = timer_ticks*PIT_INTERVAL +
	(1000*(((PIT_FREQ*PIT_INTERVAL)/1000) - counter )/(PIT_FREQ) );


    /* check time monotony */
    if(milli<last_time)
    {
#ifdef STATISTICS
	pit_hw_milli_wrap1++;
#endif
	if(ticks<timer_ticks)
	{
		milli=timer_ticks*PIT_INTERVAL;
#ifdef STATISTICS
		pit_hw_milli_wrap2++;
#endif
	}
	else
		milli=last_time;
    }


    last_time=milli;


    if(ticks<timer_ticks) /* Between start and here pit_intr was called */
	return (timer_ticks*PIT_INTERVAL);
    else
	return milli;
}
#endif

/*
 * The actual clock interrupt
 */
/* ARGSUSED */
#ifdef __KERNEL__	/* Work with Linux-ISR	*/
static void
pit_intr(reason,dev_idt,frame)
    int reason;
    void *dev_idt;
    struct fault *frame;
#else
static void
pit_intr(reason,frame)
    int reason;
    struct fault *frame;
#endif
{
    void sweeper_run();
    void flp_motoroff();
    extern int motortime;


    timer_ticks++;

#ifdef MCA
    /* ps/2 clock needs to be told to stop interrupting */
    out_byte(0x61, in_byte(0x61) | 0x80);
#endif

    enqueue(sweeper_run, (long) PIT_INTERVAL);

#if (defined(ISA) || defined(MCA)) && !defined(NOFLOPPY)
    /* stop running floppy motor */
    if (motortime != 0 && --motortime == 0)
	flp_motoroff();
#endif
}

#ifdef STATISTICS
int
pit_stat(begin,end)
char	*begin;
char	*end;
{
	char *p;
	int	i;

	p=bprintf(begin,end,"**** Hardware Timer statistics *****\n");
	p=bprintf(p,end,"pit_hw_milli() calls: %d\n",
		  pit_hw_milli_count);
	p=bprintf(p,end,"pit_hw_milli time wrap check failed: %d\n",
		  pit_hw_milli_wrap1);
	p=bprintf(p,end,"pit_hw_milli dirty ticks increment: %d\n",
		  pit_hw_milli_wrap2);

	p=bprintf(p,end,"pit_delay() calls: %d\n",
		  pit_delay_count);

	return p-begin;
}
#endif

/* For cpu speed measurement. We need timer access. */

void
cpuspeed(int aalcycles, int havecycleclock)
{
        int cpufreq, loops, incr, x, y;
	unsigned long ax1,dx1,ax2,dx2,a,b;

	pit_init();

	/* find biggest loop that doesn't wrap */
	incr = 16000000/(aalcycles*HZ*2);
	x = 2000;
	for(loops = incr; loops < 64*1024; loops += incr) {

		/*
		 *  measure time for the loop
		 *
		 *			MOVL	loops,CX
		 *	aaml1:	 	AAM
		 *			LOOP	aaml1
		 *
		 *  the time for the loop should be independent of external
		 *  cache and memory system since it fits in the execution
		 *  prefetch buffer.
		 *
		 */

		/* Beware of counter reset's (wraps)... */

		/* Read the cpu internal clock if available */
		if(havecycleclock)
			rdmsr(0x10, &ax1,&dx1);
		x = (int)pit_channel0();

		aamloop(loops);

		if(havecycleclock)
			rdmsr(0x10, &ax2,&dx2);

		y = (int)pit_channel0();

		x -= y;

		if(x < 0)
			x += PIT_FREQ/PIT_HZ;

		if(x > PIT_FREQ/(3*PIT_HZ))
			break;
	}

	/*
 	 *  figure out clock frequency and a loop multiplier for delay().
	 *  n.b. counter goes up by 2*PIT_FREQ
	 */
	cpufreq = loops*((aalcycles*PIT_FREQ)/x);
	cpu.loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1ms */

	/* check aalcycle value */
	if(kernel_option("cud") == 1)
		printf("cpuspeed: aalcycle MHz=%d\n",
			(cpufreq + cpufreq/200)/1000000);

	if(havecycleclock){


		if(dx2 == dx1)
			b = (ax2-ax1);
		else	/* counter wrap */
			b = (ax2+0xffffffff-ax1);

		b /= x;
		b *= PIT_FREQ;


		/*
		 *  round to the nearest megahz
		 */
		cpu.cpumhz = (b+500000)/1000000L;
		cpu.cpuhz = b;
	} else {
		/*
		 *  add in possible 0.5% error and convert to MHz
		 */
		cpu.cpumhz = (cpufreq + cpufreq/200)/1000000;
		cpu.cpuhz = cpufreq;
	}


}



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-22 19:17 [9fans] A quite amusing thing Maksim Radziwill
  2003-02-22 20:30 ` Russ Cox
@ 2003-02-22 20:51 ` David Presotto
  2003-02-23  2:16 ` Skip Tavakkolian
  2003-02-23  3:53 ` John Packer
  3 siblings, 0 replies; 12+ messages in thread
From: David Presotto @ 2003-02-22 20:51 UTC (permalink / raw)
  To: 9fans

The original form, i.e., timing the aam loop, comes directly from
intel, I forget which manual/developer note, so one could say
the manufacturere is the source.  However, the .5% error and comment
had to come from us.  It was just fudging to get the numbers
close to what microsoft reported to avoid confusing people
and for which I took lots of chastising.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-22 19:17 [9fans] A quite amusing thing Maksim Radziwill
  2003-02-22 20:30 ` Russ Cox
  2003-02-22 20:51 ` David Presotto
@ 2003-02-23  2:16 ` Skip Tavakkolian
  2003-02-23  3:53 ` John Packer
  3 siblings, 0 replies; 12+ messages in thread
From: Skip Tavakkolian @ 2003-02-23  2:16 UTC (permalink / raw)
  To: 9fans

> Hmm... It is possible too that Amoeba developer's have copied this code
> but I doubt it.

They would have done well to imitate, or "borrow" code for such greats
as Plan9's developers.   Imitation is the sincerest form of flattery.
I think Plan9's developers should be flattered.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-22 19:17 [9fans] A quite amusing thing Maksim Radziwill
                   ` (2 preceding siblings ...)
  2003-02-23  2:16 ` Skip Tavakkolian
@ 2003-02-23  3:53 ` John Packer
  2003-02-23  6:10   ` northern snowfall
  3 siblings, 1 reply; 12+ messages in thread
From: John Packer @ 2003-02-23  3:53 UTC (permalink / raw)
  To: 9fans


> Hmm... It is possible too that Amoeba developer's have copied this code
> but I doubt it.

You were joking, right?

It is telling that the comment uses the 8a assembler instructions
MOVL, AAM, and LOOP:


                /*
                 *  measure time for the loop
                 *
                 *                        MOVL        loops,CX
                 *        aaml1:                 AAM
                 *                        LOOP        aaml1
                 *
                 *  the time for the loop should be independent of external
                 *  cache and memory system since it fits in theexecution
                 *  prefetch buffer.
                 *
                 */



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-23  3:53 ` John Packer
@ 2003-02-23  6:10   ` northern snowfall
  2003-02-23  8:30     ` John Packer
  0 siblings, 1 reply; 12+ messages in thread
From: northern snowfall @ 2003-02-23  6:10 UTC (permalink / raw)
  To: 9fans

>
>
>It is telling that the comment uses the 8a assembler instructions
>MOVL, AAM, and LOOP:
>
MOVL, AAM and LOOP are all standard Intel CPU mnemonics
Don

>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-23  6:10   ` northern snowfall
@ 2003-02-23  8:30     ` John Packer
  2003-02-23 20:26       ` northern snowfall
  0 siblings, 1 reply; 12+ messages in thread
From: John Packer @ 2003-02-23  8:30 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 49 bytes --]

Don't you mean movl, aam, and loop (lowercase)?

[-- Attachment #2: Type: message/rfc822, Size: 2258 bytes --]

From: northern snowfall <dbailey27@ameritech.net>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] A quite amusing thing...
Date: Sun, 23 Feb 2003 01:10:18 -0500
Message-ID: <3E5865CA.7060105@ameritech.net>

>
>
>It is telling that the comment uses the 8a assembler instructions
>MOVL, AAM, and LOOP:
>
MOVL, AAM and LOOP are all standard Intel CPU mnemonics
Don

>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-23  8:30     ` John Packer
@ 2003-02-23 20:26       ` northern snowfall
  2003-02-23 21:28         ` John Packer
  0 siblings, 1 reply; 12+ messages in thread
From: northern snowfall @ 2003-02-23 20:26 UTC (permalink / raw)
  To: 9fans

>
>
>Don't you mean movl, aam, and loop (lowercase)?
>
No




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-23 20:26       ` northern snowfall
@ 2003-02-23 21:28         ` John Packer
  2003-02-23 22:00           ` northern snowfall
  0 siblings, 1 reply; 12+ messages in thread
From: John Packer @ 2003-02-23 21:28 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 774 bytes --]

Well, that shows how little x86 assembly language I've had to deal
with the last few years. I had assumed an 8a instruction like

	MOVL        something, CX

would have been

	movl %ecx, something

with whatever assembler they use now to compile Amoeba.  You say the
instruction would be the same.  Thanks for the clarification.

            /*
             *  measure time for the loop
             *
             *                MOVL  loops,CX
             *    aaml1:           AAM
             *                LOOP  aaml1
             *
             *  the time for the loop should be independent of external
             *  cache and memory system since it fits in the execution
             *  prefetch buffer.
             *
             */

[-- Attachment #2: Type: message/rfc822, Size: 2156 bytes --]

From: northern snowfall <dbailey27@ameritech.net>
To: 9fans@cse.psu.edu
Subject: Re: [9fans] A quite amusing thing...
Date: Sun, 23 Feb 2003 15:26:48 -0500
Message-ID: <3E592E88.3020906@ameritech.net>

>
>
>Don't you mean movl, aam, and loop (lowercase)?
>
No

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [9fans] A quite amusing thing...
  2003-02-23 21:28         ` John Packer
@ 2003-02-23 22:00           ` northern snowfall
  0 siblings, 0 replies; 12+ messages in thread
From: northern snowfall @ 2003-02-23 22:00 UTC (permalink / raw)
  To: 9fans

>
>
>MOVL        something, CX
>
This syntax is Intel style ASM as depicted in their x86 manuals.

>movl %ecx, something
>
This is known as "AT&T flavor" intel ASM.
Its really no big deal, just assembler dependent. Despite flavors in
syntax, though, Intel mnemonics are considered static and should
never be assumed to change unless Intel specifically removes or
changes a mnemonic (which isn't likely to happen with such
universal instructions as are in question). Mnemonics should also
be considered case independent, though, Intel prefers upper-case.
Don

>




^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [9fans] A quite amusing thing...
  2003-02-22 20:34 philw
@ 2003-02-22 20:40 ` Russ Cox
  0 siblings, 0 replies; 12+ messages in thread
From: Russ Cox @ 2003-02-22 20:40 UTC (permalink / raw)
  To: 9fans

> Leendert van Doorn was a summer student at the labs that year I think

That's part of what was amusing, though the users file seems
to indicate it was 1995.

The Amoeba pit.c code as he left it when the project ended
still didn't have the AAM loop though -- the FSD guys added it.

Russ



^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [9fans] A quite amusing thing...
@ 2003-02-22 20:34 philw
  2003-02-22 20:40 ` Russ Cox
  0 siblings, 1 reply; 12+ messages in thread
From: philw @ 2003-02-22 20:34 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 17886 bytes --]

Leendert van Doorn was a summer student at the labs that year I think
 
phil

	-----Original Message----- 
	From: Russ Cox [mailto:rsc@plan9.bell-labs.com] 
	Sent: Sat 2/22/2003 12:30 PM 
	To: 9fans@cse.psu.edu 
	Cc: 
	Subject: Re: [9fans] A quite amusing thing...
	
	

	That _is_ fairly amusing.
	
	We've had a form of that code (including the big
	comment) in our source tree since July 15, 1994.
	But the 1994 code didn't have the for loop to run
	until loops got big enough (it assumed 10000 was
	enough) and it didn't have all the clock frequency
	stuff (which got added later).
	
	So either Plan 9 copied Amoeba back in 1994 (before
	the original project was terminated) and has been
	secretly tracking the code since then, or Amoeba copied
	Plan 9 some time later after the code was changed to
	look more like it does today.  I know where my money is.
	
	Also, I downloaded the original Amoeba code and the
	pit.c looked nothing like the Plan 9 code as of 1996. 
	
	Below you'll find Plan 9's clock.c from 1994, Amoeba's
	pit.c from 1996, and Amoeba's pit.c from today.
	Note the difference between the last two.  Sure looks like
	
	 * Stefan Bosse (12/1999-7/2000)
	 * sbosse@physik.uni-bremen.de
	 *
	 * -> pit_hw_milli now default routine with 1ms resolution
	 * -> cpuspeed measurement and delay loop reference
	
	copied the Plan 9 code.
	
	> Hmm... It is possible too that Amoeba developer's have copied this code
	> but I doubt it.
	
	Why?
	
	Russ
	
	/* --rw-rw-r-- M 3014 jmk sys 2766 Jul 15  1994 sys/src/brazil/pc/clock.c */
	
	void
	clockinit(void)
	{
	        ulong x, y;     /* change in counter */
	        ulong cycles, loops;
	
	        /*
	         *  set vector for clock interrupts
	         */
	        setvec(Clockvec, clock, 0);
	
	        /*
	         *  set clock for 1/HZ seconds
	         */
	        outb(Tmode, Load0|Square);
	        outb(T0cntr, (Freq/HZ));        /* low byte */
	        outb(T0cntr, (Freq/HZ)>>8);     /* high byte */
	
	        /*
	         *  measure time for the loop
	         *
	         *                      MOVL    loops,CX
	         *      aaml1:          AAM
	         *                      LOOP    aaml1
	         *
	         *  the time for the loop should be independent from external
	         *  cache's and memory system since it fits in the execution
	         *  prefetch buffer.
	         *
	         */
	        loops = 10000;
	        outb(Tmode, Latch0);
	        x = inb(T0cntr);
	        x |= inb(T0cntr)<<8;
	        aamloop(loops);
	        outb(Tmode, Latch0);
	        y = inb(T0cntr);
	        y |= inb(T0cntr)<<8;
	        x -= y;
	
	        /*
	         *  counter  goes at twice the frequency, once per transition,
	         *  i.e., twice per the square wave
	         */
	        x >>= 1;
	
	        /*
	         *  figure out clock frequency and a loop multiplier for delay().
	         */
	        switch(cputype = x86()){
	        case 386:
	                cycles = 30;
	                break;
	        case 486:
	                cycles = 24;
	                break;
	        default:
	                cycles = 23;
	                break;
	        }
	        cpufreq = (cycles*loops) * (Freq/x);
	        loopconst = (cpufreq/1000)/cycles;      /* AAM+LOOP's for 1 ms */
	}
	
	
	/*      @(#)pit.c       1.4     94/04/06 09:23:12 */
	/*
	 * Copyright 1994 Vrije Universiteit, The Netherlands.
	 * For full copyright and restrictions on use see the file COPYRIGHT in the
	 * top level of the Amoeba distribution.
	 */
	
	/*
	 * pit.c
	 *
	 * Driver for the 8254 timer (PIT). The i8254 timer has three timer channels
	 * of which only one (channel 0) is available for timer interrupts. The other
	 * channels are used for the speaker and memory refresh.
	 *
	 * Author:
	 *      Leendert van Doorn
	 */
	#include <amoeba.h>
	#include <assert.h>
	INIT_ASSERT
	#include <fault.h>
	#include <bool.h>
	#include "sys/proto.h"
	#include "i386_proto.h"
	#include "pit.h"
	
	#ifndef PIT_DEBUG
	#define PIT_DEBUG       0
	#endif
	
	static int pit_debug;                   /* current debug level */
	
	#ifdef notyet
	static uint32 pit_hw_milli();
	#endif
	static void pit_intr();
	
	/*
	 * Initialize channel 0 of the i8254A timer
	 */
	void
	pit_init()
	{
	    register uint32 counter = (PIT_FREQ * PIT_INTERVAL) / 1000L;
	
	#ifndef NDEBUG
	    if ((pit_debug = kernel_option("pit")) == 0)
	        pit_debug = PIT_DEBUG;
	    if (pit_debug > 1)
	        printf("pit_init(), pit_interval = 0x%x (%d), counter = %x\n",
	            PIT_INTERVAL, PIT_INTERVAL, counter);
	#endif
	
	    /* set timer to run continuously */
	    assert(counter <= 0xFFFF);
	    out_byte(PIT_MODE, PIT_MODE3);
	    out_byte(PIT_CH0, (int) (counter & 0xFF));
	    out_byte(PIT_CH0, (int) ((counter >> 8) & 0xFF));
	
	#ifdef notyet
	    /* I still have to thoroughly test this */
	    set_hw_milli(pit_hw_milli);
	#endif
	
	    setirq(PIT_IRQ, pit_intr);
	    pic_enable(PIT_IRQ);
	}
	
	/*
	 * Read i8254's channel 0 counter. The counter decrements at twice the
	 * timer frequency (one full cycle for each half of a square wave).
	 */
	uint16
	pit_channel0()
	{
	    register uint16 counter;
	
	    out_byte(PIT_MODE, PIT_LC);
	    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
	    return counter;
	}
	
	/*
	 * Delay for at least ``msec'' milli seconds
	 */
	void
	pit_delay(msec)
	    int msec;
	{
	    register uint16 current, previous, diff;
	    register uint32 total;
	
	    /*
	     * The counter decrements at twice the timer frequency
	     * (one full cycle for each half of a square wave).
	     */
	    diff = 100; /* just in case */
	    total = (uint32) msec * (2 * PIT_FREQ / 1000);
	    previous = pit_channel0();
	    for (;;) {
	        current = pit_channel0();
	        if (current < previous)
	            diff = previous - current;
	        if (diff >= total)
	            break;
	        total -= diff;
	        previous = current;
	    }
	}
	
	#ifdef notyet
	/*
	 * Return number of actual milli-seconds that have passed
	 */
	static uint32
	pit_hw_milli()
	{
	    extern uint32 milli_uptime;
	    register uint32 milli;
	    register int flags;
	    uint16 counter;
	    int status;
	
	    flags = get_flags(); disable();
	    out_byte(PIT_MODE, PIT_RB);
	    out_byte(PIT_MODE, 0xC2);
	    status = in_byte(PIT_CH0);
	    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
	    milli = milli_uptime + (PIT_INTERVAL / 2) *
	        (counter / (PIT_FREQ * PIT_INTERVAL) / 1000L);
	    if ((status & 0x80) == 0) milli += PIT_INTERVAL/2;
	    set_flags(flags);
	    return milli;
	}
	#endif
	
	/*
	 * The actual clock interrupt
	 */
	/* ARGSUSED */
	static void
	pit_intr(reason, frame)
	    int reason;
	    struct fault *frame;
	{
	    void sweeper_run();
	    void flp_motoroff();
	    extern int motortime;
	
	#ifdef MCA
	    /* ps/2 clock needs to be told to stop interrupting */
	    out_byte(0x61, in_byte(0x61) | 0x80);
	#endif
	
	    enqueue(sweeper_run, (long) PIT_INTERVAL);
	
	#if (defined(ISA) || defined(MCA)) && !defined(NOFLOPPY)
	    /* stop running floppy motor */
	    if (motortime != 0 && --motortime == 0)
	        flp_motoroff();
	#endif
	}
	
	
	/*
	 * This file is part of the FIREBALL AMOEBA System.
	 *
	 *
	 * Last modified:
	 *              18/02/01
	 *
	 * Stefan Bosse (12/1999-7/2000)
	 * sbosse@physik.uni-bremen.de
	 *
	 * -> pit_hw_milli now default routine with 1ms resolution
	 * -> cpuspeed measurement and delay loop reference
	 *
	 *
	 *
	 * FIREBALL AMOEBA is free software; you can redistribute it and/or
	 * modify it under the terms of the GNU General Public License as
	 * published by the Free Software Foundation; version 2.
	 *
	 * The FIREBALL AMOEBA is distributed in the hope that it will be usefull,
	 * but WITHOUT ANY WARRANTY; without even implied warranty of
	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
	 * General Public License for more details.
	 *
	 * Original Copyright: Vrije Universiteit, The Netherlands.
	 */
	
	
	
	
	/*
	 * pit.c
	 *
	 * Driver for the 8254 timer (PIT). The i8254 timer has three timer channels
	 * of which only one (channel 0) is available for timer interrupts. The other
	 * channels are used for the speaker and memory refresh.
	 *
	 * Author:
	 *      Leendert van Doorn
	 */
	
	
	#include <amoeba.h>
	#include <assert.h>
	INIT_ASSERT
	#include <fault.h>
	#include <bool.h>
	#include "sys/proto.h"
	#include "i386_proto.h"
	#include <irq.h>
	#include "pit.h"
	#include <cpu.h>
	
	#ifndef PIT_DEBUG
	#define PIT_DEBUG       0
	#endif
	
	#ifdef STATISTICS
	static unsigned long pit_hw_milli_count=0;
	static unsigned long pit_hw_milli_wrap1=0;
	static unsigned long pit_hw_milli_wrap2=0;
	static unsigned long pit_delay_count=0;
	#endif
	
	static int pit_debug;                   /* current debug level */
	static int initialized=0;
	
	#ifdef PIT_HW_MILLI
	static uint32 pit_hw_milli();
	#endif
	static void pit_intr();
	
	/*
	 * milli_uptime will be incremented in sweeper_run, but it's delayed
	 * because of enqueue() handling.
	 * milli_uptime should be handled ***here***.
	 * Hack: Local we use timer_ticks for pit_hw_milli(), incremented in low
	 * level ISR below...
	 */
	unsigned long timer_ticks=0;   
	
	/* for time monotony checking; we have a serious problem with
	 * this faulty timer hardware
	 */
	static unsigned long last_time=0;
	
	/*
	 * Initialize channel 0 of the i8254A timer
	 */
	void
	pit_init()
	{
	    register uint32 counter = (PIT_FREQ * PIT_INTERVAL) / 1000L;
	
	
	    if(!initialized)
	    {
	
	        initialized=1;
	#ifndef NDEBUG
	        if ((pit_debug = kernel_option("pit")) == 0)
	                pit_debug = PIT_DEBUG;
	        if (pit_debug > 1)
	                printf("pit_init(), pit_interval = 0x%x (%d), counter = %x\n",
	                       PIT_INTERVAL, PIT_INTERVAL, counter);
	#endif
	
	        /* set timer to run continuously */
	        assert(counter <= 0xFFFF);
	
	        if(check_region(PIT_CH0,4)<0)
	                panic("Some fool allocated timer ports");
	        request_region(PIT_CH0,4,"PIT");
	
	        out_byte(PIT_MODE, PIT_MODE2);
	
	        out_byte(PIT_CH0, (int) (counter & 0xFF));
	        out_byte(PIT_CH0, (int) ((counter >> 8) & 0xFF));
	
	#ifdef PIT_HW_MILLI
	        /* I still have to thoroughly test this */
	        /* SB: still timer wrap problems; but time monotonie is guranteed */
	        set_hw_milli(pit_hw_milli);
	#endif
	
	        if(request_irq(PIT_IRQ,
	                       pit_intr,
	                       SA_NORMAL,
	                       "PIT",
	                       (void *)NULL)!=0)
	                panic("Some fool allocated timer irq");
	
	        enable_irq(PIT_IRQ);
	        /*pic_enable(PIT_IRQ);*/
	    }
	}
	
	/*
	 * Read i8254's channel 0 counter. The counter decrements at twice the
	 * timer frequency (one full cycle for each half of a square wave).
	 */
	uint16
	pit_channel0()
	{
	    register uint16 counter;
	    unsigned long flags;
	
	    save_flags(flags);cli();
	    out_byte(PIT_MODE, PIT_LC);
	    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
	    restore_flags(flags);
	    return counter;
	}
	
	/*
	 * Delay for at least ``msec'' milli seconds
	 */
	void
	pit_delay(msec)
	    int msec;
	{
	    register uint16 current, previous, diff;
	    register uint32 total;
	
	
	#ifdef STATISTICS
	    pit_delay_count++;
	#endif
	    /*
	     * The counter decrements at twice the timer frequency
	     * (one full cycle for each half of a square wave).
	     */
	    diff = 100; /* just in case */
	    total = (uint32) msec * (PIT_FREQ / 1000);
	    previous = pit_channel0();
	    for (;;) {
	        current = pit_channel0();
	        if (current < previous)
	            diff = previous - current;
	        if (diff >= total)
	            break;
	        total -= diff;
	        previous = current;
	    }
	}
	
	
	#ifdef PIT_HW_MILLI
	/*
	 * Return number of actual milli-seconds that have passed
	 */
	static uint32
	pit_hw_milli()
	{
	    extern uint32 milli_uptime;
	    register uint32 milli;
	    uint16 counter,counter2;
	    int status,status2;
	    unsigned long flags;
	    unsigned long ticks=timer_ticks;
	
	
	
	#ifdef STATISTICS
	    pit_hw_milli_count++;      
	#endif
	
	    save_flags(flags);cli();
	    /* Select timer0 and latch counter value. */
	    out_byte(PIT_MODE,PIT_LC);
	    counter = in_byte(PIT_CH0), counter |= (in_byte(PIT_CH0) << 8);
	    restore_flags(flags);
	
	    milli = timer_ticks*PIT_INTERVAL +
	        (1000*(((PIT_FREQ*PIT_INTERVAL)/1000) - counter )/(PIT_FREQ) );
	
	
	    /* check time monotony */
	    if(milli<last_time)
	    {
	#ifdef STATISTICS
	        pit_hw_milli_wrap1++;
	#endif 
	        if(ticks<timer_ticks)
	        {
	                milli=timer_ticks*PIT_INTERVAL;
	#ifdef STATISTICS
	                pit_hw_milli_wrap2++;
	#endif
	        }
	        else
	                milli=last_time;
	    }
	
	
	    last_time=milli;
	
	
	    if(ticks<timer_ticks) /* Between start and here pit_intr was called */
	        return (timer_ticks*PIT_INTERVAL);
	    else
	        return milli;
	}
	#endif
	
	/*
	 * The actual clock interrupt
	 */
	/* ARGSUSED */
	#ifdef __KERNEL__       /* Work with Linux-ISR  */
	static void
	pit_intr(reason,dev_idt,frame)
	    int reason;
	    void *dev_idt;
	    struct fault *frame;
	#else
	static void
	pit_intr(reason,frame)
	    int reason;
	    struct fault *frame;
	#endif
	{
	    void sweeper_run();
	    void flp_motoroff();
	    extern int motortime;
	
	
	    timer_ticks++;
	
	#ifdef MCA
	    /* ps/2 clock needs to be told to stop interrupting */
	    out_byte(0x61, in_byte(0x61) | 0x80);
	#endif
	
	    enqueue(sweeper_run, (long) PIT_INTERVAL);
	
	#if (defined(ISA) || defined(MCA)) && !defined(NOFLOPPY)
	    /* stop running floppy motor */
	    if (motortime != 0 && --motortime == 0)
	        flp_motoroff();
	#endif
	}
	
	#ifdef STATISTICS
	int
	pit_stat(begin,end)
	char    *begin;
	char    *end;
	{
	        char *p;
	        int     i;
	
	        p=bprintf(begin,end,"**** Hardware Timer statistics *****\n");
	        p=bprintf(p,end,"pit_hw_milli() calls: %d\n",
	                  pit_hw_milli_count);
	        p=bprintf(p,end,"pit_hw_milli time wrap check failed: %d\n",
	                  pit_hw_milli_wrap1);
	        p=bprintf(p,end,"pit_hw_milli dirty ticks increment: %d\n",
	                  pit_hw_milli_wrap2);
	
	        p=bprintf(p,end,"pit_delay() calls: %d\n",
	                  pit_delay_count);
	
	        return p-begin;
	}
	#endif
	
	/* For cpu speed measurement. We need timer access. */
	
	void
	cpuspeed(int aalcycles, int havecycleclock)
	{
	        int cpufreq, loops, incr, x, y;
	        unsigned long ax1,dx1,ax2,dx2,a,b;
	
	        pit_init();
	
	        /* find biggest loop that doesn't wrap */
	        incr = 16000000/(aalcycles*HZ*2);
	        x = 2000;
	        for(loops = incr; loops < 64*1024; loops += incr) {
	       
	                /*
	                 *  measure time for the loop
	                 *
	                 *                      MOVL    loops,CX
	                 *      aaml1:          AAM
	                 *                      LOOP    aaml1
	                 *
	                 *  the time for the loop should be independent of external
	                 *  cache and memory system since it fits in the execution
	                 *  prefetch buffer.
	                 *
	                 */
	
	                /* Beware of counter reset's (wraps)... */
	
	                /* Read the cpu internal clock if available */
	                if(havecycleclock)
	                        rdmsr(0x10, &ax1,&dx1);
	                x = (int)pit_channel0();
	
	                aamloop(loops);
	
	                if(havecycleclock)
	                        rdmsr(0x10, &ax2,&dx2);
	
	                y = (int)pit_channel0();
	
	                x -= y;
	
	                if(x < 0)
	                        x += PIT_FREQ/PIT_HZ;
	
	                if(x > PIT_FREQ/(3*PIT_HZ))
	                        break;
	        }
	
	        /*
	         *  figure out clock frequency and a loop multiplier for delay().
	         *  n.b. counter goes up by 2*PIT_FREQ
	         */
	        cpufreq = loops*((aalcycles*PIT_FREQ)/x);
	        cpu.loopconst = (cpufreq/1000)/aalcycles; /* AAM+LOOP's for 1ms */
	
	        /* check aalcycle value */
	        if(kernel_option("cud") == 1)
	                printf("cpuspeed: aalcycle MHz=%d\n",
	                        (cpufreq + cpufreq/200)/1000000);
	
	        if(havecycleclock){
	
	
	                if(dx2 == dx1)
	                        b = (ax2-ax1);
	                else    /* counter wrap */
	                        b = (ax2+0xffffffff-ax1);
	
	                b /= x;
	                b *= PIT_FREQ;
	
	
	                /*
	                 *  round to the nearest megahz
	                 */
	                cpu.cpumhz = (b+500000)/1000000L;
	                cpu.cpuhz = b;
	        } else {
	                /*
	                 *  add in possible 0.5% error and convert to MHz
	                 */
	                cpu.cpumhz = (cpufreq + cpufreq/200)/1000000;
	                cpu.cpuhz = cpufreq;
	        }
	
	
	}
	
	


[-- Attachment #2.1: Type: text/plain, Size: 268 bytes --]

The following attachment had content that we can't
prove to be harmless.  To avoid possible automatic
execution, we changed the content headers.
The original header was:

	Content-Type: application/ms-tnef;
	name="winmail.dat"
	Content-Transfer-Encoding: base64

[-- Attachment #2.2: winmail.dat.suspect --]
[-- Type: application/octet-stream, Size: 34814 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2003-02-23 22:00 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-22 19:17 [9fans] A quite amusing thing Maksim Radziwill
2003-02-22 20:30 ` Russ Cox
2003-02-22 20:51 ` David Presotto
2003-02-23  2:16 ` Skip Tavakkolian
2003-02-23  3:53 ` John Packer
2003-02-23  6:10   ` northern snowfall
2003-02-23  8:30     ` John Packer
2003-02-23 20:26       ` northern snowfall
2003-02-23 21:28         ` John Packer
2003-02-23 22:00           ` northern snowfall
2003-02-22 20:34 philw
2003-02-22 20:40 ` Russ Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).