/* Create and start a new thread. * * The thread must be joined with vlc_join() to reclaim resources when it is * not needed anymore. * * 1st parameter: th [OUT] pointer to write the handle of the created thread to * (mandatory, must be non-NULL) * 2nd parameter: entry entry point for the thread * 3rd parameter: data data parameter given to the entry point * 4th parameter: priority thread priority value * returns 0 on success, a standard error code on error. */ int vlc_clone (vlc_thread_t *th, void *(*entry) (void *), void *data, int priority) { pthread_attr_t attr; pthread_attr_init (&attr); return vlc_clone_attr (th, &attr, entry, data, priority); }
int vlc_clone_detach (vlc_thread_t *p_handle, void *(*entry) (void *), void *data, int priority) { vlc_thread_t th; if (p_handle == NULL) p_handle = &th; return vlc_clone_attr (p_handle, true, entry, data, priority); }
int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data, int priority) { vlc_thread_t dummy; if (th == NULL) th = &dummy; (void) priority; return vlc_clone_attr (th, entry, data, true); }
/** * Creates and starts new detached thread. * A detached thread cannot be joined. Its resources will be automatically * released whenever the thread exits (in particular, its call stack will be * reclaimed). * * Detached thread are particularly useful when some work needs to be done * asynchronously, that is likely to be completed much earlier than the thread * can practically be joined. In this case, thread detach can spare memory. * * A detached thread may be cancelled, so as to expedite its termination. * Be extremely careful if you do this: while a normal joinable thread can * safely be cancelled after it has already exited, cancelling an already * exited detached thread is undefined: The thread handle would is destroyed * immediately when the detached thread exits. So you need to ensure that the * detached thread is still running before cancellation is attempted. * * @warning Care must be taken that any resources used by the detached thread * remains valid until the thread completes. * * @note A detached thread must eventually exit just like another other * thread. In practice, LibVLC will wait for detached threads to exit before * it unloads the plugins. * * @param th [OUT] pointer to hold the thread handle, or NULL * @param entry entry point for the thread * @param data data parameter given to the entry point * @param priority thread priority value * @return 0 on success, a standard error code on error. */ int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data, int priority) { vlc_thread_t dummy; pthread_attr_t attr; if (th == NULL) th = &dummy; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); return vlc_clone_attr (th, &attr, entry, data, priority); }
int vlc_clone (vlc_thread_t *p_handle, void *(*entry) (void *), void *data, int priority) { return vlc_clone_attr (p_handle, false, entry, data, priority); }
int vlc_clone (vlc_thread_t *th, void *(*entry) (void *), void *data, int priority) { (void) priority; return vlc_clone_attr (th, entry, data, false); }
static int vlc_clone_attr (vlc_thread_t *th, pthread_attr_t *attr, void *(*entry) (void *), void *data, int priority) { int ret; /* Block the signals that signals interface plugin handles. * If the LibVLC caller wants to handle some signals by itself, it should * block these before whenever invoking LibVLC. And it must obviously not * start the VLC signals interface plugin. * * LibVLC will normally ignore any interruption caused by an asynchronous * signal during a system call. But there may well be some buggy cases * where it fails to handle EINTR (bug reports welcome). Some underlying * libraries might also not handle EINTR properly. */ sigset_t oldset; { sigset_t set; sigemptyset (&set); sigdelset (&set, SIGHUP); sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); sigaddset (&set, SIGPIPE); /* We don't want this one, really! */ pthread_sigmask (SIG_BLOCK, &set, &oldset); } #if defined (_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 0) \ && defined (_POSIX_THREAD_PRIORITY_SCHEDULING) \ && (_POSIX_THREAD_PRIORITY_SCHEDULING >= 0) if (rt_priorities) { struct sched_param sp = { .sched_priority = priority + rt_offset, }; int policy; if (sp.sched_priority <= 0) sp.sched_priority += sched_get_priority_max (policy = SCHED_OTHER); else sp.sched_priority += sched_get_priority_min (policy = SCHED_RR); pthread_attr_setschedpolicy (attr, policy); pthread_attr_setschedparam (attr, &sp); } #else (void) priority; #endif /* The thread stack size. * The lower the value, the less address space per thread, the highest * maximum simultaneous threads per process. Too low values will cause * stack overflows and weird crashes. Set with caution. Also keep in mind * that 64-bits platforms consume more stack than 32-bits one. * * Thanks to on-demand paging, thread stack size only affects address space * consumption. In terms of memory, threads only use what they need * (rounded up to the page boundary). * * For example, on Linux i386, the default is 2 mega-bytes, which supports * about 320 threads per processes. */ #define VLC_STACKSIZE (128 * sizeof (void *) * 1024) #ifdef VLC_STACKSIZE ret = pthread_attr_setstacksize (attr, VLC_STACKSIZE); assert (ret == 0); /* fails iif VLC_STACKSIZE is invalid */ #endif ret = pthread_create (th, attr, entry, data); pthread_sigmask (SIG_SETMASK, &oldset, NULL); pthread_attr_destroy (attr); return ret; } /** * Creates and starts new thread. * * The thread must be <i>joined</i> with vlc_join() to reclaim resources * when it is not needed anymore. * * @param th [OUT] pointer to write the handle of the created thread to * (mandatory, must be non-NULL) * @param entry entry point for the thread * @param data data parameter given to the entry point * @param priority thread priority value * @return 0 on success, a standard error code on error. */ int vlc_clone (vlc_thread_t *th, void *(*entry) (void *), void *data, int priority) { pthread_attr_t attr; pthread_attr_init (&attr); return vlc_clone_attr (th, &attr, entry, data, priority); }