mirror of
				https://github.com/Ryujinx/libsoundio.git
				synced 2025-11-04 11:54:47 +00:00 
			
		
		
		
	dummy: fix deadlock when pause called from write_callback
This commit is contained in:
		
							parent
							
								
									a3c4f85489
								
							
						
					
					
						commit
						277bb3106b
					
				| 
						 | 
					@ -44,6 +44,12 @@ static void playback_thread_run(void *arg) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (osd->pause_requested.load()) {
 | 
				
			||||||
 | 
					            start_time = now;
 | 
				
			||||||
 | 
					            frames_consumed = 0;
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
 | 
					        int fill_bytes = soundio_ring_buffer_fill_count(&osd->ring_buffer);
 | 
				
			||||||
        int fill_frames = fill_bytes / outstream->bytes_per_frame;
 | 
					        int fill_frames = fill_bytes / outstream->bytes_per_frame;
 | 
				
			||||||
        int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
 | 
					        int free_bytes = soundio_ring_buffer_capacity(&osd->ring_buffer) - fill_bytes;
 | 
				
			||||||
| 
						 | 
					@ -86,6 +92,12 @@ static void capture_thread_run(void *arg) {
 | 
				
			||||||
        double relative_time = next_period - now;
 | 
					        double relative_time = next_period - now;
 | 
				
			||||||
        soundio_os_cond_timed_wait(isd->cond, nullptr, relative_time);
 | 
					        soundio_os_cond_timed_wait(isd->cond, nullptr, relative_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isd->pause_requested.load()) {
 | 
				
			||||||
 | 
					            start_time = now;
 | 
				
			||||||
 | 
					            frames_consumed = 0;
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int fill_bytes = soundio_ring_buffer_fill_count(&isd->ring_buffer);
 | 
					        int fill_bytes = soundio_ring_buffer_fill_count(&isd->ring_buffer);
 | 
				
			||||||
        int free_bytes = soundio_ring_buffer_capacity(&isd->ring_buffer) - fill_bytes;
 | 
					        int free_bytes = soundio_ring_buffer_capacity(&isd->ring_buffer) - fill_bytes;
 | 
				
			||||||
        int fill_frames = fill_bytes / instream->bytes_per_frame;
 | 
					        int fill_frames = fill_bytes / instream->bytes_per_frame;
 | 
				
			||||||
| 
						 | 
					@ -166,6 +178,7 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
 | 
				
			||||||
    SoundIoDevice *device = outstream->device;
 | 
					    SoundIoDevice *device = outstream->device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    osd->clear_buffer_flag.test_and_set();
 | 
					    osd->clear_buffer_flag.test_and_set();
 | 
				
			||||||
 | 
					    osd->pause_requested.store(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (outstream->software_latency == 0.0)
 | 
					    if (outstream->software_latency == 0.0)
 | 
				
			||||||
        outstream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
 | 
					        outstream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
 | 
				
			||||||
| 
						 | 
					@ -193,16 +206,14 @@ static int outstream_open_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
 | 
					static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStreamPrivate *os, bool pause) {
 | 
				
			||||||
    SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
 | 
					    SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
 | 
				
			||||||
    SoundIo *soundio = &si->pub;
 | 
					    osd->pause_requested.store(pause);
 | 
				
			||||||
    if (pause) {
 | 
					    return 0;
 | 
				
			||||||
        if (osd->thread) {
 | 
					 | 
				
			||||||
            osd->abort_flag.clear();
 | 
					 | 
				
			||||||
            soundio_os_cond_signal(osd->cond, nullptr);
 | 
					 | 
				
			||||||
            soundio_os_thread_destroy(osd->thread);
 | 
					 | 
				
			||||||
            osd->thread = nullptr;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    } else {
 | 
					
 | 
				
			||||||
        if (!osd->thread) {
 | 
					static int outstream_start_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
 | 
				
			||||||
 | 
					    SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
 | 
				
			||||||
 | 
					    SoundIo *soundio = &si->pub;
 | 
				
			||||||
 | 
					    assert(!osd->thread);
 | 
				
			||||||
    osd->abort_flag.test_and_set();
 | 
					    osd->abort_flag.test_and_set();
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    if ((err = soundio_os_thread_create(playback_thread_run, os,
 | 
					    if ((err = soundio_os_thread_create(playback_thread_run, os,
 | 
				
			||||||
| 
						 | 
					@ -210,15 +221,9 @@ static int outstream_pause_dummy(struct SoundIoPrivate *si, struct SoundIoOutStr
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return err;
 | 
					        return err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int outstream_start_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
 | 
					 | 
				
			||||||
    return outstream_pause_dummy(si, os, false);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int outstream_begin_write_dummy(SoundIoPrivate *si,
 | 
					static int outstream_begin_write_dummy(SoundIoPrivate *si,
 | 
				
			||||||
        SoundIoOutStreamPrivate *os, SoundIoChannelArea **out_areas, int *frame_count)
 | 
					        SoundIoOutStreamPrivate *os, SoundIoChannelArea **out_areas, int *frame_count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -284,6 +289,7 @@ static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
 | 
				
			||||||
    SoundIoInStream *instream = &is->pub;
 | 
					    SoundIoInStream *instream = &is->pub;
 | 
				
			||||||
    SoundIoDevice *device = instream->device;
 | 
					    SoundIoDevice *device = instream->device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    isd->pause_requested.store(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (instream->software_latency == 0.0)
 | 
					    if (instream->software_latency == 0.0)
 | 
				
			||||||
        instream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
 | 
					        instream->software_latency = clamp(device->software_latency_min, 1.0, device->software_latency_max);
 | 
				
			||||||
| 
						 | 
					@ -313,16 +319,14 @@ static int instream_open_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int instream_pause_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) {
 | 
					static int instream_pause_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is, bool pause) {
 | 
				
			||||||
    SoundIoInStreamDummy *isd = &is->backend_data.dummy;
 | 
					    SoundIoInStreamDummy *isd = &is->backend_data.dummy;
 | 
				
			||||||
    SoundIo *soundio = &si->pub;
 | 
					    isd->pause_requested.store(pause);
 | 
				
			||||||
    if (pause) {
 | 
					    return 0;
 | 
				
			||||||
        if (isd->thread) {
 | 
					 | 
				
			||||||
            isd->abort_flag.clear();
 | 
					 | 
				
			||||||
            soundio_os_cond_signal(isd->cond, nullptr);
 | 
					 | 
				
			||||||
            soundio_os_thread_destroy(isd->thread);
 | 
					 | 
				
			||||||
            isd->thread = nullptr;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    } else {
 | 
					
 | 
				
			||||||
        if (!isd->thread) {
 | 
					static int instream_start_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
 | 
				
			||||||
 | 
					    SoundIoInStreamDummy *isd = &is->backend_data.dummy;
 | 
				
			||||||
 | 
					    SoundIo *soundio = &si->pub;
 | 
				
			||||||
 | 
					    assert(!isd->thread);
 | 
				
			||||||
    isd->abort_flag.test_and_set();
 | 
					    isd->abort_flag.test_and_set();
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    if ((err = soundio_os_thread_create(capture_thread_run, is,
 | 
					    if ((err = soundio_os_thread_create(capture_thread_run, is,
 | 
				
			||||||
| 
						 | 
					@ -330,15 +334,9 @@ static int instream_pause_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return err;
 | 
					        return err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int instream_start_dummy(SoundIoPrivate *si, SoundIoInStreamPrivate *is) {
 | 
					 | 
				
			||||||
    return instream_pause_dummy(si, is, false);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int instream_begin_read_dummy(SoundIoPrivate *si,
 | 
					static int instream_begin_read_dummy(SoundIoPrivate *si,
 | 
				
			||||||
        SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
 | 
					        SoundIoInStreamPrivate *is, SoundIoChannelArea **out_areas, int *frame_count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ struct SoundIoOutStreamDummy {
 | 
				
			||||||
    struct SoundIoRingBuffer ring_buffer;
 | 
					    struct SoundIoRingBuffer ring_buffer;
 | 
				
			||||||
    double playback_start_time;
 | 
					    double playback_start_time;
 | 
				
			||||||
    atomic_flag clear_buffer_flag;
 | 
					    atomic_flag clear_buffer_flag;
 | 
				
			||||||
 | 
					    atomic_bool pause_requested;
 | 
				
			||||||
    SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
					    SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +47,7 @@ struct SoundIoInStreamDummy {
 | 
				
			||||||
    int read_frame_count;
 | 
					    int read_frame_count;
 | 
				
			||||||
    int buffer_frame_count;
 | 
					    int buffer_frame_count;
 | 
				
			||||||
    struct SoundIoRingBuffer ring_buffer;
 | 
					    struct SoundIoRingBuffer ring_buffer;
 | 
				
			||||||
 | 
					    atomic_bool pause_requested;
 | 
				
			||||||
    SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
					    SoundIoChannelArea areas[SOUNDIO_MAX_CHANNELS];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue