threads: add vlc_thread_self() and vlc_thread_id()
authorRémi Denis-Courmont <remi@remlab.net>
Wed, 25 May 2016 19:51:04 +0000 (22:51 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Wed, 25 May 2016 20:06:52 +0000 (23:06 +0300)
include/vlc_threads.h
src/Makefile.am
src/android/thread.c
src/darwin/thread.c
src/libvlccore.sym
src/linux/thread.c [new file with mode: 0644]
src/os2/thread.c
src/posix/thread.c
src/win32/thread.c

index 477ffff..e82c2bb 100644 (file)
@@ -675,6 +675,42 @@ VLC_API void vlc_restorecancel(int state);
  */
 VLC_API void vlc_control_cancel(int cmd, ...);
 
+/**
+ * Thread handle.
+ *
+ * This function returns the thread handle of the calling thread.
+ *
+ * \note The exact type of the thread handle depends on the platform,
+ * including an integer type, a pointer type or a compound type of any size.
+ * If you need an integer identifier, use vlc_thread_id() instead.
+ *
+ * \note vlc_join(vlc_thread_self(), NULL) is undefined,
+ * as it obviously does not make any sense (it might result in a deadlock, but
+ * there are no warranties that it will).
+ *
+ * \return the thread handle
+ */
+VLC_API vlc_thread_t vlc_thread_self(void) VLC_USED;
+
+/**
+ * Thread identifier.
+ *
+ * This function returns the identifier of the calling thread. The identifier
+ * cannot change for the entire duration of the thread, and no other thread can
+ * have the same identifier at the same time in the same process. Typically,
+ * the identifier is also unique across all running threads of all existing
+ * processes, but that depends on the operating system.
+ *
+ * There are no particular semantics to the thread ID with LibVLC.
+ * It is provided mainly for tracing and debugging.
+ *
+ * \warning This function is not currently implemented on all supported
+ * platforms. Where not implemented, it returns (unsigned long)-1.
+ *
+ * \return the thread identifier (or -1 if unimplemented)
+ */
+VLC_API unsigned long vlc_thread_id(void) VLC_USED;
+
 /**
  * Precision monotonic clock.
  *
index fe4e16a..e825fb4 100644 (file)
@@ -263,6 +263,7 @@ SOURCES_libvlc_android = \
        linux/cpu.c \
        linux/dirs.c \
        android/dirs.c \
+       linux/thread.c \
        android/thread.c \
        android/error.c \
        posix/filesystem.c \
@@ -281,6 +282,7 @@ SOURCES_libvlc_linux = \
        posix/filesystem.c \
        posix/netconf.c \
        posix/plugin.c \
+       linux/thread.c \
        posix/thread.c \
        posix/timer.c \
        posix/specific.c \
index e016e90..59499b4 100644 (file)
@@ -90,9 +90,9 @@ vlc_thread_fatal (const char *action, int error,
     }
 
     __android_log_print(ANDROID_LOG_ERROR, "vlc",
-        "LibVLC fatal error %s (%d) in thread %d "
+        "LibVLC fatal error %s (%d) in thread %lu "
         "at %s:%u in %s\n Error message: %s\n",
-        action, error, syscall (__NR_gettid), file, line, function, msg);
+        action, error, vlc_thread_id (), file, line, function, msg);
 
     abort ();
 }
@@ -180,6 +180,16 @@ struct vlc_thread
 
 static __thread struct vlc_thread *thread = NULL;
 
+vlc_thread_t vlc_thread_self (void)
+{
+    return thread;
+}
+
+unsigned long vlc_thread_id (void)
+{
+    return syscall (__NR_gettid);
+}
+
 void vlc_threads_setup (libvlc_int_t *p_libvlc)
 {
     (void)p_libvlc;
index 600b676..b4991fa 100644 (file)
@@ -74,13 +74,6 @@ void vlc_trace (const char *fn, const char *file, unsigned line)
      fsync (2);
 }
 
-static inline unsigned long vlc_threadid (void)
-{
-     union { pthread_t th; unsigned long int i; } v = { };
-     v.th = pthread_self ();
-     return v.i;
-}
-
 #ifndef NDEBUG
 /* Reports a fatal error from the threading layer, for debugging purposes. */
 static void
@@ -89,7 +82,7 @@ vlc_thread_fatal (const char *action, int error,
 {
     int canc = vlc_savecancel ();
     fprintf (stderr, "LibVLC fatal error %s (%d) in thread %lu ",
-             action, error, vlc_threadid ());
+             action, error, vlc_thread_id ());
     vlc_trace (function, file, line);
 
     char buf[1000];
@@ -463,6 +456,16 @@ int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data,
     return vlc_clone_attr (th, &attr, entry, data, priority);
 }
 
+vlc_thread_t vlc_thread_self (void)
+{
+    return pthread_self ();
+}
+
+unsigned long vlc_thread_id (void)
+{
+    return -1;
+}
+
 int vlc_set_priority (vlc_thread_t th, int priority)
 {
     (void) th; (void) priority;
index 06c39ce..2dcb5cf 100644 (file)
@@ -653,6 +653,8 @@ vlc_sdp_Start
 vlc_sd_Start
 vlc_sd_Stop
 vlc_testcancel
+vlc_thread_self
+vlc_thread_id
 vlc_threadvar_create
 vlc_threadvar_delete
 vlc_threadvar_get
diff --git a/src/linux/thread.c b/src/linux/thread.c
new file mode 100644 (file)
index 0000000..f9acb87
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * linux/thread.c: Linux specifics for threading
+ *****************************************************************************
+ * Copyright (C) 2016 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+unsigned long vlc_thread_id(void)
+{
+     static __thread pid_t tid = 0;
+
+     if (unlikely(tid == 0))
+         tid = syscall(__NR_gettid);
+
+     return tid;
+}
index 27f8f00..bbd1f1c 100644 (file)
@@ -77,7 +77,7 @@ static ULONG vlc_DosWaitEventSemEx( HEV hev, ULONG ulTimeout )
     int       n;
     ULONG     rc;
 
-    struct vlc_thread *th = vlc_threadvar_get( thread_key );
+    struct vlc_thread *th = vlc_thread_self( thread_key );
     if( th == NULL || !th->killable )
     {
         /* Main thread - cannot be cancelled anyway
@@ -638,6 +638,20 @@ int vlc_set_priority (vlc_thread_t th, int priority)
     return VLC_SUCCESS;
 }
 
+vlc_thread_t vlc_thread_self (void)
+{
+    return vlc_threadvar_get (thread_key);
+}
+
+unsigned long vlc_thread_id (void)
+{
+#if 0
+    return vlc_thread_self ()->tid; /* potential NULL deref */
+#else
+    return -1;
+#endif
+}
+
 /*** Thread cancellation ***/
 
 /* APC procedure for thread cancellation */
@@ -659,7 +673,7 @@ int vlc_savecancel (void)
 {
     int state;
 
-    struct vlc_thread *th = vlc_threadvar_get (thread_key);
+    struct vlc_thread *th = vlc_thread_self ();
     if (th == NULL)
         return false; /* Main thread - cannot be cancelled anyway */
 
@@ -670,7 +684,7 @@ int vlc_savecancel (void)
 
 void vlc_restorecancel (int state)
 {
-    struct vlc_thread *th = vlc_threadvar_get (thread_key);
+    struct vlc_thread *th = vlc_thread_self ();
     assert (state == false || state == true);
 
     if (th == NULL)
@@ -682,7 +696,7 @@ void vlc_restorecancel (int state)
 
 void vlc_testcancel (void)
 {
-    struct vlc_thread *th = vlc_threadvar_get (thread_key);
+    struct vlc_thread *th = vlc_thread_self ();
     if (th == NULL)
         return; /* Main thread - cannot be cancelled anyway */
 
@@ -709,7 +723,7 @@ void vlc_control_cancel (int cmd, ...)
      * need to lock anything. */
     va_list ap;
 
-    struct vlc_thread *th = vlc_threadvar_get (thread_key);
+    struct vlc_thread *th = vlc_thread_self ();
     if (th == NULL)
         return; /* Main thread - cannot be cancelled anyway */
 
@@ -738,7 +752,7 @@ void vlc_control_cancel (int cmd, ...)
 static int vlc_select( int nfds, fd_set *rdset, fd_set *wrset, fd_set *exset,
                        struct timeval *timeout )
 {
-    struct vlc_thread *th = vlc_threadvar_get( thread_key );
+    struct vlc_thread *th = vlc_thread_self( );
 
     int rc;
 
index a29cff3..f1d9542 100644 (file)
@@ -43,9 +43,6 @@
 #include <pthread.h>
 #include <sched.h>
 
-#ifdef __linux__
-# include <sys/syscall.h> /* SYS_gettid */
-#endif
 #ifdef HAVE_EXECINFO_H
 # include <execinfo.h>
 #endif
@@ -136,20 +133,6 @@ void vlc_trace (const char *fn, const char *file, unsigned line)
      fsync (2);
 }
 
-static inline unsigned long vlc_threadid (void)
-{
-#if defined (__linux__)
-     /* glibc does not provide a call for this */
-     return syscall (__NR_gettid);
-
-#else
-     union { pthread_t th; unsigned long int i; } v = { };
-     v.th = pthread_self ();
-     return v.i;
-
-#endif
-}
-
 #ifndef NDEBUG
 /**
  * Reports a fatal error from the threading layer, for debugging purposes.
@@ -160,7 +143,7 @@ vlc_thread_fatal (const char *action, int error,
 {
     int canc = vlc_savecancel ();
     fprintf (stderr, "LibVLC fatal error %s (%d) in thread %lu ",
-             action, error, vlc_threadid ());
+             action, error, vlc_thread_id ());
     vlc_trace (function, file, line);
     perror ("Thread error");
     fflush (stderr);
@@ -563,6 +546,18 @@ int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data,
     return vlc_clone_attr (th, &attr, entry, data, priority);
 }
 
+vlc_thread_t vlc_thread_self (void)
+{
+    return pthread_self ();
+}
+
+#if !defined (__linux__)
+unsigned long vlc_thread_id (void)
+{
+     return -1;
+}
+#endif
+
 int vlc_set_priority (vlc_thread_t th, int priority)
 {
 #if defined (_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 0) \
index 12cbed6..ea8ffe3 100644 (file)
@@ -447,7 +447,7 @@ retry:
 #if !IS_INTERRUPTIBLE
 static bool isCancelled(void)
 {
-    struct vlc_thread *th = TlsGetValue(thread_key);
+    struct vlc_thread *th = vlc_thread_self();
     if (th == NULL)
         return false; /* Main thread - cannot be cancelled anyway */
 
@@ -542,6 +542,16 @@ int vlc_clone_detach (vlc_thread_t *p_handle, void *(*entry) (void *),
     return vlc_clone_attr (p_handle, true, entry, data, priority);
 }
 
+vlc_thread_t vlc_thread_self (void)
+{
+    return TlsGetValue(thread_key);
+}
+
+unsigned long vlc_thread_id (void)
+{
+    return GetCurrentThreadId ();
+}
+
 int vlc_set_priority (vlc_thread_t th, int priority)
 {
     if (!SetThreadPriority (th->id, priority))
@@ -573,7 +583,7 @@ void vlc_cancel (vlc_thread_t th)
 
 int vlc_savecancel (void)
 {
-    struct vlc_thread *th = TlsGetValue(thread_key);
+    struct vlc_thread *th = vlc_thread_self();
     if (th == NULL)
         return false; /* Main thread - cannot be cancelled anyway */
 
@@ -584,7 +594,7 @@ int vlc_savecancel (void)
 
 void vlc_restorecancel (int state)
 {
-    struct vlc_thread *th = TlsGetValue(thread_key);
+    struct vlc_thread *th = vlc_thread_self();
     assert (state == false || state == true);
 
     if (th == NULL)
@@ -596,7 +606,7 @@ void vlc_restorecancel (int state)
 
 void vlc_testcancel (void)
 {
-    struct vlc_thread *th = TlsGetValue(thread_key);
+    struct vlc_thread *th = vlc_thread_self();
     if (th == NULL)
         return; /* Main thread - cannot be cancelled anyway */
     if (!th->killable)
@@ -625,7 +635,7 @@ void vlc_control_cancel (int cmd, ...)
      * need to lock anything. */
     va_list ap;
 
-    struct vlc_thread *th = TlsGetValue(thread_key);
+    struct vlc_thread *th = vlc_thread_self();
     if (th == NULL)
         return; /* Main thread - cannot be cancelled anyway */