summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorJohannes Stezenbach <devnull@localhost>2003-05-06 17:10:49 +0000
committerJohannes Stezenbach <devnull@localhost>2003-05-06 17:10:49 +0000
commit95637968e0b0384f6c6c1137a8c0522ae631f346 (patch)
tree9f57ae4a361901dd6384ea0a3b6b14b78a02b8a3 /linux
parent98a0a2449d34fea262dae8c5dbe88e78bd2bf3ea (diff)
downloadmediapointer-dvb-s2-95637968e0b0384f6c6c1137a8c0522ae631f346.tar.gz
mediapointer-dvb-s2-95637968e0b0384f6c6c1137a8c0522ae631f346.tar.bz2
trying to fix frontend thread start/stop problems
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index ee95bb16d..73184e1c2 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -65,7 +65,7 @@ struct dvb_frontend_data {
struct semaphore sem;
struct list_head list_head;
wait_queue_head_t wait_queue;
- struct task_struct *thread;
+ pid_t thread_pid;
unsigned long release_jiffies;
unsigned long lost_sync_jiffies;
int bending;
@@ -437,7 +437,7 @@ int dvb_frontend_thread (void *data)
dvb_kernel_thread_setup (name);
- fe->thread = current;
+ fe->thread_pid = current->pid;
fe->lost_sync_count = -1;
dvb_call_frontend_notifiers (fe, 0);
@@ -447,11 +447,11 @@ int dvb_frontend_thread (void *data)
up (&fe->sem); /* is locked when we enter the thread... */
interruptible_sleep_on_timeout (&fe->wait_queue, delay);
+ if (signal_pending(current))
+ break;
- if (down_interruptible (&fe->sem)) {
- fe->thread = NULL;
- return -ERESTARTSYS;
- }
+ if (down_interruptible (&fe->sem))
+ break;
if (fe->lost_sync_count == -1)
continue;
@@ -493,7 +493,11 @@ int dvb_frontend_thread (void *data)
dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL);
up (&fe->sem);
- fe->thread = NULL;
+
+ fe->thread_pid = 0;
+ mb();
+
+ wake_up_interruptible (&fe->wait_queue);
return 0;
}
@@ -503,32 +507,54 @@ void dvb_frontend_stop (struct dvb_frontend_data *fe)
{
dprintk ("%s\n", __FUNCTION__);
- while (fe->thread) {
- fe->exit = 1;
- wake_up_interruptible (&fe->wait_queue);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout (5);
- if (signal_pending(current))
- break;
- };
+ fe->exit = 1;
+ mb();
+
+ if (!fe->thread_pid)
+ return;
+
+ /* check if the thread is really alive */
+ if (kill_proc(fe->thread_pid, 0, 1) == -ESRCH) {
+ printk("dvb_frontend_stop: thread PID %d already died\n",
+ fe->thread_pid);
+ /* make sure the mutex was not held by the thread */
+ init_MUTEX (&fe->sem);
+ return;
+ }
+
+ wake_up_interruptible(&fe->wait_queue);
+ interruptible_sleep_on(&fe->wait_queue);
+
+ /* paranoia check */
+ if (fe->thread_pid)
+ printk("dvb_frontend_stop: warning: thread PID %d won't exit\n",
+ fe->thread_pid);
}
static
-void dvb_frontend_start (struct dvb_frontend_data *fe)
+int dvb_frontend_start (struct dvb_frontend_data *fe)
{
dprintk ("%s\n", __FUNCTION__);
- if (fe->thread)
- dvb_frontend_stop (fe);
+ if (fe->thread_pid) {
+ if (!fe->exit)
+ return 0;
+ else
+ dvb_frontend_stop (fe);
+ }
+ if (signal_pending(current))
+ return -EINTR;
if (down_interruptible (&fe->sem))
- return;
+ return -EINTR;
fe->exit = 0;
- fe->thread = (void*) ~0;
+ fe->thread_pid = 0;
+ mb();
kernel_thread (dvb_frontend_thread, fe, 0);
+ return 0;
}
@@ -606,12 +632,12 @@ int dvb_frontend_open (struct inode *inode, struct file *file)
return ret;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
- dvb_frontend_start (fe);
+ ret = dvb_frontend_start (fe);
/* empty event queue */
- fe->events.eventr = fe->events.eventw;
+ fe->events.eventr = fe->events.eventw = 0;
}
-
+
return ret;
}