xref: /linux/drivers/accessibility/speakup/thread.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kthread.h>
3 #include <linux/wait.h>
4 
5 #include "spk_types.h"
6 #include "speakup.h"
7 #include "spk_priv.h"
8 
9 DECLARE_WAIT_QUEUE_HEAD(speakup_event);
10 EXPORT_SYMBOL_GPL(speakup_event);
11 
12 int speakup_thread(void *data)
13 {
14 	unsigned long flags;
15 	int should_break;
16 	struct bleep our_sound;
17 
18 	our_sound.active = 0;
19 	our_sound.freq = 0;
20 	our_sound.jiffies = 0;
21 
22 	mutex_lock(&spk_mutex);
23 	while (1) {
24 		DEFINE_WAIT(wait);
25 
26 		while (1) {
27 			spin_lock_irqsave(&speakup_info.spinlock, flags);
28 			our_sound = spk_unprocessed_sound;
29 			spk_unprocessed_sound.active = 0;
30 			prepare_to_wait(&speakup_event, &wait,
31 					TASK_INTERRUPTIBLE);
32 			should_break = kthread_should_stop() ||
33 				our_sound.active ||
34 				(synth && synth->catch_up && synth->alive &&
35 					(speakup_info.flushing ||
36 					!synth_buffer_empty()));
37 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
38 			if (should_break)
39 				break;
40 			mutex_unlock(&spk_mutex);
41 			schedule();
42 			mutex_lock(&spk_mutex);
43 		}
44 		finish_wait(&speakup_event, &wait);
45 		if (kthread_should_stop())
46 			break;
47 
48 		if (our_sound.active)
49 			kd_mksound(our_sound.freq, our_sound.jiffies);
50 		if (synth && synth->catch_up && synth->alive) {
51 			/*
52 			 * It is up to the callee to take the lock, so that it
53 			 * can sleep whenever it likes
54 			 */
55 			synth->catch_up(synth);
56 		}
57 
58 		speakup_start_ttys();
59 	}
60 	mutex_unlock(&spk_mutex);
61 	return 0;
62 }
63