Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Apr 2000 21:01:01 -0500
From:      Stephen Harris <sch@aristotle.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/18316: contiguous bt848/878 captures to file causes system hang
Message-ID:  <00043021021500.03347@tiger.home.net>

next in thread | raw e-mail | index | archive | help

>Number:         18316
>Category:       kern
>Synopsis:       close-together bt848/878 captures to file causes system hang
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Apr 30 20:00:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Stephen Harris
>Release:        FreeBSD 4.0-RELEASE i386
>Organization:
None
>Environment:
	System is a 166Mhz dell, here's the part of the kernel config file
relating to the capture boards:

#############################################################
options         BROOKTREE_SYSTEM_DEFAULT=BROOKTREE_NTSC
options         BKTR_SIS_VIA_MODE

device smbus
device iicbus
device iicbb

device          bktr

device          ic
device          iic
device          iicsmb          # smb over i2c bridge
############################################################

The driver version is the current one (as of April 30, 2000) available from:
ftp://telepresence.dmem.strath.ac.uk/pub/bt848/driver/2.12 

>Description:

Short program causes system to lock-up completely ( no response to any 
keys, can't telnet to it, harddrive light doesn't go off even though 
there's no audible activity, num-lock key doesn't toggle its light).

The program just repeatedly captures an image and writes it to disk,
all in a SIGALRM handler.  If the spacing between the SIGALARM's is made
to be such that the disk writes run together (hard drive light on
continuously), the system locks solid after a few seconds.

This happened with RELEASE-3.3 also, I've never tried 3.4.
I have tried it on both a bt848 and a bt878 and have gotten lockups
on both (release 3.3 with bt848 and release 4.0 with bt878).
I've tried with and without BKTR_SIS_VIA_MODE (on 4.0),  locks up
either way.

Note that just repeatedly capturing and reading the buffer 
(and not writing to file) does not cause a lockup, nor just 
repeatedly writing the capture buffer to file (after only capturing once,
initially).  You have to capture and write repeatedly (close together) to get
the hang.

>How-To-Repeat:
Just compile and run this program:

/* --------------------------------------- */
/*     lockup.c                                                               */

#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include "/sys/i386/include/ioctl_meteor.h"

/* -------------------------------------------------- */
/* Stuff to ajust ----------------------------------- */
 
/* It seems to be only when both of these are off that a lockup happens,
   ie. only when capturing and writing to a file during every tick */
#define JUST_READ_DONT_WRITE_FILE 0
#define ONLY_CAPTURE_ONCE 0

/* This timer interval needs to be set low enough for your machine that
   the writes are continuous; my machine is 166Mhz, and 20 causes a lockup
   in just a few seconds, while 50 doesn't. */
int interval_100ths = 10; /* 100ths of sec between captures */

/* Stuff to ajust ----------------------------------- */
/* -------------------------------------------------- */

#define BYTES_PER_PIXEL 4
#define WIDTH  640
#define HEIGHT 480
static const int BUF_LEN = WIDTH * HEIGHT * BYTES_PER_PIXEL; 

static const int BOARD_COLOR_FORMAT = METEOR_GEO_RGB24;
static const int BOARD_INPUT_SOURCE = METEOR_INPUT_DEV0;
static const int BOARD_SOURCE_TYPE = METEOR_FMT_NTSC;

int vdev_fd;
void* grab_buf;

static void start_timer(int hundredths);

/*-----------------------------------------------------------------------*/
/* SIGALRM handler, time to do a capture                 */
void next_capture(int unused)
{
  static int first_time = 1;
  
  if ( ! ONLY_CAPTURE_ONCE || first_time )
    {
      int cap_single = METEOR_CAP_SINGLE;
      
      ioctl(vdev_fd, METEORCAPTUR, &cap_single);
      first_time = 0;
    }
  
  if ( JUST_READ_DONT_WRITE_FILE )
    {
      int ix;
      for (ix=0; ix<BUF_LEN; ++ix)
	{
	  if ( ((char*)grab_buf)[ix] == 'h' )
	    printf("Just so the read isn't optimized away");
	}
    }
  else /* Write contents of grab_buffer to output file */
    {
      int fd = open("out_file", O_RDWR | O_CREAT, S_IRWXU);
      
      if ( fd == -1 ) 
	{
	  perror("Couldn't open file");
	  exit(1);
	}
      
      write(fd, grab_buf, BUF_LEN);
      close(fd);
    }
}

/* ------------------------------------------------------------ */
void init_board()
{
  int source = BOARD_INPUT_SOURCE;
  int source_type = BOARD_SOURCE_TYPE;
  
  struct meteor_geomet geo;
  
  if ((vdev_fd = open("/dev/bktr0",O_RDONLY)) == -1) 
    {
      perror("Failed to open device\n");
      exit(1);
    }
  
  /* set up the capture type and size */
  geo.rows = HEIGHT;
  geo.columns = WIDTH;
  geo.frames = 1;
  geo.oformat = BOARD_COLOR_FORMAT;
  
  if (ioctl(vdev_fd, METEORSETGEO, &geo) < 0) {
    perror("ioctl for capture type and size failed");
    exit(1);
  }
  
  if (ioctl(vdev_fd, METEORSFMT, &source_type) < 0) {
    perror("ioctl for source type failed");
    exit(1);
  }

  /* Select the Video Source */
  /* Video In, Tuner, or S-Video */
  if (ioctl(vdev_fd, METEORSINPUT, &source) < 0) {
    perror("ioctl for input source failed");
    exit(1);
  }
  
  grab_buf = mmap( (caddr_t)0, 
		   BUF_LEN, 
		   PROT_READ, 
		   MAP_SHARED, 
		   vdev_fd, 
		   (off_t)0 );
  
  if ( grab_buf == MAP_FAILED ) 
    {
      perror("Could not mmap device");
      exit(1);
    }
}

/* ----------------------------------------------------- */
int main(int argc, char* argv[])
{
  sigset_t no_sigs;
  
  umask(0);
  
  init_board();
  
  start_timer(interval_100ths);
  

  /* Just wait for alarm signals, the handler does all the work */
  sigemptyset(&no_sigs);
  while(1) 
    {
      sigsuspend(&no_sigs);
    }
  
    
} // end of main()

/* ----------------------------------------------------- */
void start_timer(int hundredths)
{
  struct itimerval interval;
  struct sigaction sig_act;
  
  sigset_t mask;
  sigemptyset(&mask);

  sig_act.sa_handler=&next_capture;
  sig_act.sa_mask=mask;
  sig_act.sa_flags=0;
  sigaction(SIGALRM, &sig_act, NULL);
  
  interval.it_interval.tv_sec = 0;
  interval.it_interval.tv_usec = hundredths * (1000000/100);
  
  interval.it_value.tv_sec = 0;
  interval.it_value.tv_usec = hundredths * (1000000/100);
  
  if ( setitimer(ITIMER_REAL, &interval, NULL) == -1 )
    {
      perror("Couldn't set timer");
      exit(1);
    }
}

// end of program


>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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