From 2afa8319403b6e3d9c87bc211b9299e7ae7afb44 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Sun, 15 Nov 2015 16:50:15 +0100 Subject: [PATCH] DVR: use atomic operations for the running start/stop variables --- configure | 6 ++++ src/atomic.h | 86 ++++++++++++++++++++++++++++++++++------------- src/dvr/dvr_db.c | 9 ++--- src/dvr/dvr_rec.c | 14 ++++---- 4 files changed, 81 insertions(+), 34 deletions(-) diff --git a/configure b/configure index 99adb4085..4e8517553 100755 --- a/configure +++ b/configure @@ -146,6 +146,12 @@ uint64_t test(uint64_t *ptr){ return __sync_fetch_and_add(ptr, 1); }' +check_cc_snippet atomic_time_t '#include +#include +uint64_t test(time_t *ptr){ +return __sync_fetch_and_add(ptr, 1); +}' + check_cc_snippet lockowner ' #include #include diff --git a/src/atomic.h b/src/atomic.h index 525b225e8..67b972d1f 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -19,33 +19,20 @@ #pragma once #include +#include extern pthread_mutex_t atomic_lock; +/* + * Atomic FETCH and ADD operation + */ + static inline int atomic_add(volatile int *ptr, int incr) { return __sync_fetch_and_add(ptr, incr); } -static inline int -atomic_dec(volatile int *ptr, int decr) -{ - return __sync_fetch_and_sub(ptr, decr); -} - -static inline int -atomic_exchange(volatile int *ptr, int new) -{ - return __sync_lock_test_and_set(ptr, new); -} - -static inline int -atomic_exchange_u64(volatile uint64_t *ptr, uint64_t new) -{ - return __sync_lock_test_and_set(ptr, new); -} - static inline uint64_t atomic_add_u64(volatile uint64_t *ptr, uint64_t incr) { @@ -61,21 +48,25 @@ atomic_add_u64(volatile uint64_t *ptr, uint64_t incr) #endif } -static inline uint64_t -atomic_dec_u64(volatile uint64_t *ptr, uint64_t decr) +static inline time_t +atomic_add_time_t(volatile time_t *ptr, time_t incr) { -#if ENABLE_ATOMIC64 - return __sync_fetch_and_sub(ptr, decr); +#if ENABLE_ATOMIC_TIME_T + return __sync_fetch_and_add(ptr, incr); #else - uint64_t ret; + time_t ret; pthread_mutex_lock(&atomic_lock); ret = *ptr; - *ptr -= decr; + *ptr += incr; pthread_mutex_unlock(&atomic_lock); return ret; #endif } +/* + * Atomic ADD and FETCH operation + */ + static inline uint64_t atomic_pre_add_u64(volatile uint64_t *ptr, uint64_t incr) { @@ -90,3 +81,50 @@ atomic_pre_add_u64(volatile uint64_t *ptr, uint64_t incr) return ret; #endif } + +/* + * Atomic DEC operation + */ + +static inline int +atomic_dec(volatile int *ptr, int decr) +{ + return __sync_fetch_and_sub(ptr, decr); +} + +static inline uint64_t +atomic_dec_u64(volatile uint64_t *ptr, uint64_t decr) +{ +#if ENABLE_ATOMIC64 + return __sync_fetch_and_sub(ptr, decr); +#else + uint64_t ret; + pthread_mutex_lock(&atomic_lock); + ret = *ptr; + *ptr -= decr; + pthread_mutex_unlock(&atomic_lock); + return ret; +#endif +} + +/* + * Atomic EXCHANGE operation + */ + +static inline int +atomic_exchange(volatile int *ptr, int new) +{ + return __sync_lock_test_and_set(ptr, new); +} + +static inline int +atomic_exchange_u64(volatile uint64_t *ptr, uint64_t new) +{ + return __sync_lock_test_and_set(ptr, new); +} + +static inline int +atomic_exchange_time_t(volatile time_t *ptr, int new) +{ + return __sync_lock_test_and_set(ptr, new); +} diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 3ab9d0beb..9256d8cf4 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1622,7 +1622,8 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running) return; LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link) { if (de->de_dvb_eid == 0 || !dvr_entry_get_epg_running(de)) { - de->de_running_start = de->de_running_stop = 0; + atomic_exchange_time_t(&de->de_running_start, 0); + atomic_exchange_time_t(&de->de_running_stop, 0); continue; } if (running && de->de_dvb_eid == e->dvb_eid) { @@ -1631,10 +1632,10 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running) idnode_uuid_as_sstr(&de->de_id), epg_broadcast_get_title(e, NULL), channel_get_name(e->channel)); - de->de_running_start = dispatch_clock; + atomic_exchange_time_t(&de->de_running_start, dispatch_clock); } if (dvr_entry_get_start_time(de) > dispatch_clock) { - de->de_start = dispatch_clock; + atomic_exchange_time_t(&de->de_start, dispatch_clock); dvr_entry_set_timer(de); tvhdebug("dvr", "dvr entry %s event %s on %s - EPG start", idnode_uuid_as_sstr(&de->de_id), @@ -1658,7 +1659,7 @@ void dvr_event_running(epg_broadcast_t *e, epg_source_t esrc, int running) epg_broadcast_get_title(e, NULL), channel_get_name(de->de_channel)); } - de->de_running_stop = dispatch_clock; + atomic_exchange_time_t(&de->de_running_stop, dispatch_clock); if (de->de_sched_state == DVR_RECORDING && de->de_running_start) { de->de_dont_reschedule = 1; dvr_stop_recording(de, SM_CODE_OK, 0, 0); diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index f829554fa..230c50b8c 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -1199,7 +1199,7 @@ dvr_thread(void *aux) int commercial = COMMERCIAL_UNKNOWN; int running_disabled; int64_t packets = 0, dts_offset = PTS_UNSET; - time_t start_time = 0; + time_t start_time = 0, running_start = 0, running_stop = 0; char *postproc; if (!dvr_thread_global_lock(de, &run)) @@ -1223,9 +1223,11 @@ dvr_thread(void *aux) if (running_disabled) { epg_running = 1; } else if (sm->sm_type == SMT_PACKET || sm->sm_type == SMT_MPEGTS) { - if (de->de_running_start > 0) { - epg_running = de->de_running_start >= de->de_running_stop; - } else if (de->de_running_stop == 0) { + running_start = atomic_add_time_t(&de->de_running_start, 0); + running_stop = atomic_add_time_t(&de->de_running_stop, 0); + if (running_start > 0) { + epg_running = running_start >= running_stop; + } else if (running_stop == 0) { if (start_time + 2 >= dispatch_clock) { TAILQ_INSERT_TAIL(&backlog, sm, sm_link); continue; @@ -1254,7 +1256,7 @@ dvr_thread(void *aux) dvr_rec_set_state(de, rs, 0); if ((rs == DVR_RS_COMMERCIAL && comm_skip) || !epg_running) { - if (ss && packets && de->de_running_start == 0) { + if (ss && packets && running_start == 0) { dvr_streaming_restart(de, &run); packets = 0; started = 0; @@ -1319,7 +1321,7 @@ dvr_thread(void *aux) break; if (!epg_running) { - if (packets && de->de_running_start == 0) { + if (packets && running_start == 0) { dvr_streaming_restart(de, &run); packets = 0; started = 0; -- 2.47.3