]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVR: use atomic operations for the running start/stop variables
authorJaroslav Kysela <perex@perex.cz>
Sun, 15 Nov 2015 15:50:15 +0000 (16:50 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 15 Nov 2015 15:50:15 +0000 (16:50 +0100)
configure
src/atomic.h
src/dvr/dvr_db.c
src/dvr/dvr_rec.c

index 99adb40858ead54162147d9c7d5d2b5cdef91620..4e8517553bfb4c7f27542951358b04135b420f67 100755 (executable)
--- 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 <stdint.h>
+#include <time.h>
+uint64_t test(time_t *ptr){
+return __sync_fetch_and_add(ptr, 1);
+}'
+
 check_cc_snippet lockowner '
 #include <sys/syscall.h>
 #include <unistd.h>
index 525b225e87f1b5427ad9109f769b8282170c7de6..67b972d1f396d43a791dedc110c41bd4ff154bc0 100644 (file)
 #pragma once
 
 #include <stdint.h>
+#include <time.h>
 
 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);
+}
index 3ab9d0bebe880e7ce04e741f770e8f34c03045b8..9256d8cf4ec61a9d1d41d562077205c343117676 100644 (file)
@@ -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);
index f829554fa7d591131dd6f061ee146ce4ef3441b3..230c50b8c1aaecddfdb203acf83e56707d61a1f1 100644 (file)
@@ -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;