Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Apr 2006 00:14:53 -0700 (PDT)
From:      "R. B. Riddick" <arne_woerner@yahoo.com>
To:        Erin E Conn <econn@nc.rr.com>
Cc:        freebsd-multimedia@freebsd.org
Subject:   Re: Rebooting problems with /dev/cxm0
Message-ID:  <20060424071453.4677.qmail@web30314.mail.mud.yahoo.com>
In-Reply-To: <444C25D7.9050600@nc.rr.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
--- Erin E Conn <econn@nc.rr.com> wrote:
> After some rebuilding and reinstalling of ports, I was able to cat 
> /dev/cxm0 to a file in my home directory for about half an hour with no 
> dma errors or lockups. I then stopped the cat and tried 'mplayer -cache 
> 4096 /dev/cxm0', and my machine locked up after about 2 minutes. The 
> display continues to update; my dockapps in fluxbox are still 
> functioning and updating, but the machine does not respond to any 
> network traffic or input devices and the video and audio from /dev/cxm0 
> have halted. Nothing is being logged to /var/log/messages at the time. I 
> tried it again while keeping an eye on the console in case there are dma 
> problems preventing anything being written to the log:
> 
> cxm0:encoder dma status 0xb
> # MACHINE STOPPED RESPONDING HERE
> cmx0:encoder dma status 0xb
> ad0: TIMEOUT - WRITE_DMA retrying (1 retry left) LBA=22069947
> ad0: TIMEOUT - WRITE_DMA retrying (0 retries left) LBA=22069947
> dc0: watchdog timeout
> dc0: failed to force tx and rx to idle state
> ad0: FAILURE - WRITE_DMA timed out LBA=22069947
> ad0: FAILURE - READ_DMA timed out LBA=20487259
> 
> The above messages continue to be output to the console and I have to 
> manually restart the computer.
> 
That sounds familiar... :-)

I attached a variation of my very special cxm-data-transfer-program, that just
copies the data to your disc (hopefully in the right order... :-)).
After examining some areas of the code (just in case I am evil), it can be
compiled with
  c++ -o dd3 dd3.c -O3
and it can be tested with
  ./dd3 /dev/cxm0 <outputfile> <time of day in sec since 1970 when to stop>
E.g.:
  ./dd3 /dev/cxm0 /tmp/blubberblah.mpg 1146862400
where the seconds since 1970 can be found via
  date +%s
which gives the current time in seconds since 1970 or via
  date -j +%s 2000
which gives the seconds since 1970 when it is 8 p.m. today.

I hope, I got the license right... It should be a BSD license or so...

In my opinion this dd3.c tool should result in more stability (currently more
then 66 days uptime...)...

-Arne

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
[-- Attachment #2 --]
// $Id: dd2.c,v 1.3 2005/12/08 01:17:49 aw Exp aw $

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <stdarg.h>

#define check(e) if (!(e)) _check(__func__,__FILE__,__LINE__,#e)
void _check(const char * const fu, const char * const fi,
              const int li, const char * const wh) {
	printf("ERR in %s, %s, %d, reason %s\n",fu,fi,li,wh);
	syslog(LOG_DEBUG,"ERR in %s, %s, %d, reason %s\n",fu,fi,li,wh);
	killpg(0,SIGKILL);
}

bool in = false;
bool to = false;
bool te = false;
void timeout(const int sno) {
	to = true;
	if (sno == SIGTERM)
		te = true;
}
void requestInfo(const int sno) { in = true; }

void stats(const uint64_t bc, const time_t dt) {
	fprintf(stderr,
		"%lldbytes read in %dsecs: %.3fMbytes/sec\n",
		bc,dt,bc*(1./(1024.*1024.))/dt);
}

void setOff(char * bu, const uint64_t bc)
	{ (*(uint64_t*)(bu-4-8)) = bc; }
uint64_t getOff(char * bu) { return *(uint64_t*)(bu-4-8); }
void setSz(char * const bu, const int cc) { (*(int*)(bu-4)) = cc; }
int getSz(char * bu) { return *(int*)(bu-4); }
void mark(char * bu, const bool s) { (*(bool*)(bu-(4+8+4))) = s; }
void markFull(char * bu) { mark(bu,true); }
void markEmpty(char * bu) { mark(bu,false); }
bool isFull(char * bu) { return bu[-(4+8+4)]!=0; }

char * get(char * const buf, const int bno, const int bsz)
	{ return buf+bno*bsz+4+8+4; }

void disc(int& ouf, char * const bu) {
	const int sz = getSz(bu);
	lseek(ouf,getOff(bu),SEEK_SET);
	ualarm(900*1000,0);
	const int r = write(ouf,bu,sz);
	ualarm(0,0);
	if (r == sz)
		markEmpty(bu);
	else if (r < 0) {
		printf("write error r%d errno%d\n",r,errno);
		exit(1);
	} else {
		printf("incomplete write r%d\n",r);
		exit(3);
	}
}

void markBlock(const int d, const bool blck) {
	int flags = fcntl(d,F_GETFL);
	check(flags != -1);
	if (blck)
		flags &= ~O_NONBLOCK;
	else
		flags |= O_NONBLOCK;
	check(fcntl(d,F_SETFL,&flags) != -1);
}

void flusher(const bool fff, const char * const fn,
             char * const buf, const int buc, const int bsz) {
	int maxSZ = 0;
	int maxBN = -1;
	int svf = socket(AF_INET, SOCK_STREAM, 0);
	if (svf >= 0) {
		markBlock(svf,false);

		struct sockaddr_in a;
		bzero(&a,sizeof(a));
		a.sin_family = AF_INET;
		a.sin_addr.s_addr = 0;
		const int mp = 1000;
		const int pb = 20000 + (fff?mp:0);
		int p;
		for (p=0; p<1000; p++) {
			a.sin_port = htons(pb+p);
			if (!bind(svf,(struct sockaddr*)&a,sizeof(a))) {
				if (listen(svf,1))
					p = mp;
				break;
			}
		}
		if (p == mp) {
			close(svf);
			svf = -1;
			printf("no network service possible\n");
		} else
			printf("network service at port %d\n",pb+p);
	}
	int ouf = -1;
	int fno = 0;
	for (bool allEmpty=false; !te || !allEmpty;) {
		allEmpty = true;
		for (int i=0; i<buc; i++) {
			char * bu = get(buf,i,bsz);
			if (!isFull(bu))
				continue;
			if (getSz(bu) > maxSZ)
				maxSZ = getSz(bu);
			if (i > maxBN)
				maxBN = i;
			if (!fff && ouf < 0) {
				char FN[strlen(fn)+20+1];
				check(snprintf(FN,sizeof(FN)-5,"%s.%d",fn,fno)<sizeof(FN)-2);
				fno++;
				ouf = open(FN,O_WRONLY|O_CREAT|O_EXCL,0666);
				check(ouf >= 0);
				const bool ready = false;
				ualarm(500*1000,0);
				check(write(ouf,&ready,sizeof(ready))==sizeof(ready));
				ualarm(0,0);
			}
			allEmpty = false;
			if (!false) {
				if (!fff)
					disc(ouf,bu);
				else
					usleep(50*1000);
			}
		}
		if (allEmpty)
			usleep(50*1000);
	}
	if (ouf >= 0) {
		check(lseek(ouf,0,SEEK_SET)==0);
		const bool ready = true;
		check(write(ouf,&ready,sizeof(ready))==sizeof(ready));
		check(close(ouf) != -1);
		printf("marked ouf ready %d\n",ready);
	}
	printf("flusher terminates ... now! [maxSZ%d maxBN%d]\n",maxSZ,maxBN);
	exit(0);
}

void next(char * const buf, char *& bu, const int bsz,
          int& cc, const uint64_t bc, int& bno, const int buc) {
	if (bu != 0) {
		setSz(bu,cc);
		check(getOff(bu)+cc == bc);
		markFull(bu);
	}
	for (bno=0; bno<buc; bno++) {
		bu = get(buf,bno,bsz);
		if (!isFull(bu)) {
			cc = 0;
			setOff(bu,bc);
			return;
		}
	}
	bu = 0;
}

void feedFromDevice(bool& to, int& r, const char * const devNam, time_t& now,
                    const time_t ets, const time_t sts, uint64_t& bc,
                    const int re, const int bs, int& cc, char * const buf,
                    char *& bu, const int buc, const int bsz, int& bno) {
	const int inf = open(devNam,O_RDONLY);
	for (int i=0; !to && now<ets; i++) {
		const int mi = 100;
		if (i > mi) {
			now = time(0);
			if (in) {
				in = false;
				stats(bc,now-sts);
			}
			i = 0;
		}
		check(re <= bs+re-cc);
		ualarm(2*1000*1000,0);
		r = read(inf,bu+cc,re);
		ualarm(0,0);
		if (r < 0)
			break;
		if (r == 0)
			continue;
		cc += r;
		bc += r;
		if (cc >= bs) {
			next(buf,bu,bsz,cc,bc,bno,buc);
			if (bu == 0) {
				printf("no free buffer\n");
				break;
			}
			i = mi;
		}
	}
	close(inf);
}

int main(const int argc, const char * const * const argv) {
	if (argc != 1+3)
		return 1;
	openlog("pvr-dd2",LOG_PID,LOG_USER);
	signal(SIGPIPE,SIG_IGN);
	siginterrupt(SIGPIPE,true);
	signal(SIGINFO,requestInfo);
	siginterrupt(SIGINFO,false);
	signal(SIGTERM,timeout);
	siginterrupt(SIGTERM,true);
	signal(SIGALRM,timeout);
	siginterrupt(SIGALRM,true);
	time_t now = time(0);
	const time_t sts = now;
	const bool fff = argv[1][0]==0;
	const time_t ets = fff?-1:atoi(argv[3]);
	const int bs = 1<<20;
	const int re = bs/4;
	const int bsz = bs+re+4+8+4;
	const int buc = 8;
	char * buf = (char*) mmap(0,buc*bsz,PROT_READ|PROT_WRITE,
	                          MAP_ANON|MAP_NOCORE|MAP_NOSYNC|MAP_SHARED,-1,0);
	for (int i=0; i<buc; i++)
		markEmpty(get(buf,i,bsz));

	const int fpid = fork();
	if (fpid == 0) {
		flusher(fff,argv[2],buf,buc,bsz);
		exit(0);
	}
	if (fpid < 0) {
		printf("fork failed\n");
		exit(1);
	}
	syslog(LOG_DEBUG,"me%d son%d\n",getpid(),fpid);

	uint64_t bc = 0;
	int bno = 0;
	int cc = 0;
	char * bu = get(buf,bno,bsz);
	setOff(bu,bc);
	while (!te && (ets==-1 || now<ets)) {
		to = false;
		int r;
		if (fff)
			;
		else
			feedFromDevice(to,r,argv[1],now,ets,sts,bc,re,bs,cc,
								buf,bu,buc,bsz,bno);
		usleep(500*1000);
		next(buf,bu,bsz,cc,bc,bno,buc);
		if (bu == 0) {
			printf("no free buffer\n");
			break;
		}
		int i=0;
		const int mi = 10*10;
		for (bool allEmpty=false; !allEmpty && i<mi; i++) {
			usleep(100*1000);
			allEmpty = true;
			for (int i=buc-1; i>=0; i--)
				if (isFull(get(buf,i,bsz))) {
					allEmpty = false;
					break;
				}
		}
		check(i < mi);
		now = time(0);
		fprintf(stderr,
		        "bailed out (to%d te%d cc%d r%d errno%d): ",
		        to,te,cc,r,errno);
		stats(bc,now-sts);
		usleep(500*1000);
	}
	{
		const int kr = kill(fpid,SIGTERM);
		printf("kill flusher process result: r%d errno%d\n",kr,errno);
		int status;
		wait(&status);
	}
	closelog();
	return 0;
}
help

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