1 /* Copyright (C) 2006  Britton Leo Kerin, see copyright. */
2 
3 /* Global variables.  Most are thread-related. */
4 
5 #include <pthread.h>
6 
7 /* Here because everybody needs it to report errors.  This gets set to
8    the full name of the program as invoked on the command line
9    (i.e. presumably argv[0]).  */
10 char *progname;
11 
12 /* This gets set true on program start if the executable is suid root.  */
13 int have_root_authority;
14 
15 /* "move*" because any given execution either records or plays, not
16    both.  Data is moved by move_au_th between the sampling device and
17    the main buffer, and by move_fd_th between the main buffer and the
18    applicable file descriptor.  We don't know in advance which way. */
19 pthread_t move_au_th, move_fd_th;
20 pthread_attr_t move_au_attr, move_fd_attr;
21 struct sched_param move_au_param, move_fd_param;
22 
23 /* Return values for thread functions, because these functions can
24    only return pointers, and pointers to automatic variables end up
25    pointing to garbage.  Currently, only success or failure can be
26    indicated. */
27 const int th_failure = -1;
28 const int th_success = 0;
29 
30 /* The ring buffer is what all these other pthreads objects are
31    synchronizing.  Note that not all data that goes in this buffer is
32    necesarilly unsigned, but this doesn't matter, since all this
33    buffer does is hold data that is on route to or from the audio
34    driver, which interprets it according to the current mode for the
35    device (set with SNDCTL_DSP_SETFMT). */
36 unsigned char *ringbufp;
37 /* When playing from standard input, it is possible that some buffer
38    segments may not always end up completely full.  This array allows
39    the move_fd thread to tell the mova_au thread how many good bytes
40    are in each segment (the remaining bytes are garbage or data left
41    over from the last time around the buffer). */
42 long *bytes_in_seg;
43 /* Allow whichever of move_au and move_fd is in the lead to mark the
44    segment it is working on as the last segment to be processed.
45    Currently this is used to achieve clean shutdown after receiving a
46    signal for which we do special shutdown processing.  */
47 int *is_last_seg;
48 
49 /* If we have_root_authority, we want to drop root permissions as soon
50    as possible.  We have to get all the high priority threads created
51    first though.  So the high priority threads all block at the start
52    waiting for a signal that root permission have been dropped before
53    doing anything.  */
54 int root_permissions_dropped = 0;
55 pthread_cond_t root_permissions_dropped_cv = PTHREAD_COND_INITIALIZER;
56 pthread_mutex_t root_permissions_dropped_mutex = PTHREAD_MUTEX_INITIALIZER;
57 
58 /* This condition variable is used ensure that any threads which
59    concurrently begin to access the ring buffer do so in the desired
60    order.  The first thread to get the ringbuffer will be the one with
61    the startup_order field of it's argument structure equal to 1.
62    When this thread is done it can broadcast a wakeup signal to the
63    other threads waiting on the condition variable, and the one with
64    startup_order == 2 can take over.  Note that it is completely up to
65    the thread code implementor to specify when an given thread is
66    'done' and the next thread should be allowed to start accessing the
67    ring buffer, and to somehow determine from the startup_next cv
68    which thread to startup next.  In conjunction with a staggered
69    locking mechanism and the wrap_ready_cv, this allows just about any
70    kind of access scheme you can dream up.  Most applications should
71    be fairly simple.  */
72 int startup_next = 1;
73 pthread_cond_t startup_next_cv = PTHREAD_COND_INITIALIZER;
74 /* The mutex attribute object and mutex for the startup_next condition
75    variable. */
76 pthread_mutexattr_t startup_next_mutex_attr;
77 pthread_mutex_t startup_next_mutex;
78 
79 /* This condition variable indicates whether or not it has become safe
80    for threads to wrap around the end of the ring buffer and start
81    processing the first segment again.  This protects against the case
82    where an early thread is so fast that it processes all the buffer
83    segments and begins working on the first buffer segment again
84    before other slower threads even get going and lock that buffer.  */
85 int wrap_ready = 0;
86 pthread_cond_t wrap_ready_cv = PTHREAD_COND_INITIALIZER;
87 pthread_mutex_t wrap_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
88 
89 /* These arrays work together to synchronize ring buffer segment
90    access.  Note that each mutex protects both a single "ioctl(au_fd,
91    SNDCTL_DSP_GETBLKSIZE, &blocksize)" or "SNDCTL_DSP_SETFRAGMENT"
92    sized segment of the ring buffer, a corresponding element of the
93    bytes_in_seg array, and a corresponding element of the is_last_seg
94    array.  In other words, all data associated with a given ringbuffer
95    segment is protected by an element of this mutex array.  */
96 pthread_mutexattr_t *seg_mutex_attr;
97 pthread_mutex_t *seg_mutex;
98 
99 /* This allows the thread which does signal handling (which
100    unfortunately is the initial thread, since Linux Threads doesn't
101    yet conform to POSIX with respect to per thread signal masking) to
102    indicate to other threads that a signal for which we do special
103    shutdown processing has come in.  */
104 int shutdown_signal_seen;
105 pthread_mutex_t shutdown_signal_seen_mutex = PTHREAD_MUTEX_INITIALIZER;
106 
107 /* This is a first attempt at sensible behavior for when we find
108    ourselves waiting for standard input.  If we see
109    MAGIC_EMPTY_SEG_SEQ_LENGTH empty segments in a row, we assume game
110    over. */
111 const int MAGIC_EMPTY_SEG_SEQ_LENGTH = 5;
112