Subject: Re: bcopy
To: Chris G Demetriou <Chris_G_Demetriou@BALVENIE.PDL.CS.CMU.EDU>
From: Trevor Blackwell <tlb@eecs.harvard.edu>
List: port-alpha
Date: 08/13/1995 09:56:52
Here's my bcopy regression test. I ran it for a good long time on the
one I submitted. It uses random inputs, with a skew toward lots of
misaligned overlapping regions.

Sorry for claiming your bcopy was wrong. It's confusing to us casual
kernel hackers to have kernel & libc functions with different
semantics but the same name. Maybe someday someone will write some
man(3k) library pages, that describe general-purpose functions in the
kernel.


/*
   Regression test for bcopy.
   Could be easily adapted to bzero.
   Will print a big error message if there is a difference.

   bcopies regions around in buffers - prints error message
   if any differences between tested bcopies.

   Author: Trevor Blackwell.
*/

#include <stdio.h>

#define MAXLEN 32768
#define PAD 128

extern int bcopy_naive(char *from, char *to, long len);
extern int bcopy_test(char *from, char *to, long len);
extern int bcopy(char *from, char *to, long len);

/*
   You can just add bcopy functions here to have them tested.
   Make the first one be the canonical bcopy that you are sure is
   correct. bcopy_naive below is good.
*/
int (*routines[])(char *from, char *to, long len)= {
  bcopy_naive,
  bcopy_test,
  bcopy
};

#define NUM_ROUTINES (sizeof(routines)/sizeof(void *))

char b[NUM_ROUTINES][MAXLEN+PAD];

int 
initb()
{
  int i,j;
  for (i=0; i<MAXLEN+PAD; i++) {
    int r=random()&0xff;
    for (j=0; j<NUM_ROUTINES; j++) {
      b[j][i]=r;
    }
  }
}

int
bcopy_naive(char *from, char *to, long len)
{
  int i;
  if (to>from) {
    for (i=len-1; i>=0; i--) {
      to[i]=from[i];
    }
  } else {
    for (i=0; i<len; i++) {
      to[i]=from[i];
    }
  }
}

int
tbc()
{
  int i,j;
  int s,d,l;
  int ret=0;
  int mlen;
  int mask;
  int n;
  unsigned int t1,t2,tt;

  mlen=32;
  while (mlen<MAXLEN && (random()%2==0)) mlen*=2;
  
  s=random()%(mlen/2);
  l=random()%(mlen/2);
  d=random()%(mlen/2);

  mask=(1<<NUM_ROUTINES)-1;
  while (mask) {
    n=random()%NUM_ROUTINES;
    if (!(mask & (1<<n))) continue;
    mask &= ~(1<<n);

    (*routines[n])(b[n]+s,b[n]+d,l);
  }

  for (i=1; i<NUM_ROUTINES; i++) {
    if (bcmp(b[0],b[i],mlen+PAD)) {
      printf("difference 0-%d\n",i);
      ret=1;
    }
  }
  if (ret) {
    printf(" s=%x d=%x l=%x\n",s,d,l);
    printf(" s+l=%x d+l=%x\n",s+l,d+l);
    printf(" s&7=%x d&7=%x l&7=%x\n",s&7,d&7,l&7);
    printf(" s^d&7=%x (s+l)^(d+l)&7=%x\n",(s^d)&7,((s+l)^(d+l))&7);

    for (i=0; i<MAXLEN; i++) {
      int f=0;
      for (j=1; j<NUM_ROUTINES; j++) {
	if (b[0][j] != b[i][j]) f=1;
      }

      printf("%08x: ");
      for (j=0; j<NUM_ROUTINES; j++) {
	printf("%02x ",b[j][i]);
      }
      printf("\n");
    }
    
  }

  return ret;
}


main()
{
  int i;
  printf("Testing %d routines\n",NUM_ROUTINES);
  while(1) {
    initb();
    for (i=0; i<10000; i++) {
      if (tbc()) break;
    }
    fprintf(stderr,".");
  }
}