Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] vfree during spin_lock hold (Was: (In)consistency of DMX/DVR buffers and OSD ioctls)



Hi,

     during seeking for a better protection against dropouts of
of a PES filter for DMX_PES_OTHER (AC3) using DMX_OUT_TAP caused
by OSD popups, I've seen that within DmxDevSetBufferSize() in
dmxdev.c that vfree() is called within a spin_lock_irq/spin_unlock_irq
pair.  This seems to be a bug.  Enclosed a patch which changes this.
Also changed in this patch: hold spin_lock in DmxDevTSCallback()
during copy buffers (seems to decrease dropouts caused by other
activities on the system), use reparent_to_init() for the
kernel threads "arm_mon" and "fe_thread".

             Werner

-----------------------------------------------------------------------
--- dmxdev.c
+++ dmxdev.c	Wed Mar 27 11:54:02 2002
@@ -288,18 +288,19 @@
 DmxDevSetBufferSize(dmxdev_filter_t *dmxdevfilter, unsigned long size)
 {
 	dmxdev_buffer_t *buf=&dmxdevfilter->buffer;
+	void *mem=buffer->data;
 
 	if (buf->size==size)
 	        return 0;
         if (dmxdevfilter->state>=DMXDEV_STATE_GO)
                 return -EBUSY;
 	spin_lock_irq(&dmxdevfilter->dev->lock);
-        if (buf->data) 
-		vfree(buf->data);
 	buf->data=0;
 	buf->size=size;
 	buf->pwrite=buf->pread=0;    
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
+	if (mem) 
+		vfree(mem);
 		
         if (buf->size) {
 	        void *mem=vmalloc(dmxdevfilter->buffer.size);
@@ -384,18 +385,21 @@
         dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *) feed->priv;
 	dmxdev_buffer_t *buffer;
         int ret;
-        
-	if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER)
-	        return 0;
+
+	spin_lock(&dmxdevfilter->dev->lock);
+	if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER) {
+		spin_unlock(&dmxdevfilter->dev->lock);
+		return 0;
+	}
 
 	if (dmxdevfilter->params.pes.output==DMX_OUT_TAP)
 	        buffer=&dmxdevfilter->buffer;
 	else
 	        buffer=&dmxdevfilter->dev->dvr_buffer;
-	if (buffer->error) {
-		wake_up(&buffer->queue);
-	        return 0;
-	}
+
+	if (buffer->error)
+		goto out;
+
         ret=DmxDevBufferWrite(buffer, buffer1, buffer1_len);
         if (ret==buffer1_len) 
 	        ret=DmxDevBufferWrite(buffer, buffer2, buffer2_len);
@@ -403,6 +407,8 @@
 	        buffer->pwrite=buffer->pread;    
 	        buffer->error=-EBUFFEROVERFLOW;
 	}
+out:
+	spin_unlock(&dmxdevfilter->dev->lock);
 	wake_up(&buffer->queue);
 	return 0;
 }
--- dvb.c
+++ dvb.c	Wed Mar 27 11:49:06 2002
@@ -427,13 +427,19 @@
         u16 newloops;
     
 	lock_kernel();
-#if 0
+#if 1
 	daemonize();
+	reparent_to_init();
+
 #else
         exit_mm(current);
         current->session=current->pgrp=1;
 #endif
+	spin_lock_irq(&current->sigmask_lock);
 	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
 	strcpy(current->comm, "arm_mon");
 	dvb->arm_thread = current;
 	unlock_kernel();
--- dvb_frontend.c
+++ dvb_frontend.c	Wed Mar 27 11:49:06 2002
@@ -431,7 +431,13 @@
     
 	lock_kernel();
 	daemonize();
+	reparent_to_init();
+
+	spin_lock_irq(&current->sigmask_lock);
 	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
 	strcpy(current->comm,"fe_thread");
 	fe->thread = current;
 	unlock_kernel();


-- 
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe linux-dvb" as subject.


Home | Main Index | Thread Index