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