diff options
author | Johannes Stezenbach <devnull@localhost> | 2003-05-06 17:10:49 +0000 |
---|---|---|
committer | Johannes Stezenbach <devnull@localhost> | 2003-05-06 17:10:49 +0000 |
commit | 95637968e0b0384f6c6c1137a8c0522ae631f346 (patch) | |
tree | 9f57ae4a361901dd6384ea0a3b6b14b78a02b8a3 /linux | |
parent | 98a0a2449d34fea262dae8c5dbe88e78bd2bf3ea (diff) | |
download | mediapointer-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.c | 72 |
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; } |