/* This file is part of Deadbeef Player source code http://deadbeef.sourceforge.net pthread wrapper Copyright (C) 2009-2013 Alexey Yakovenko This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alexey Yakovenko waker@users.sourceforge.net */ #include #include #include #include #include #include "threading.h" #ifdef HAVE_CONFIG_H #include #endif intptr_t thread_start (void (*fn)(void *ctx), void *ctx) { pthread_t tid; pthread_attr_t attr; int s = pthread_attr_init (&attr); if (s != 0) { fprintf (stderr, "pthread_attr_init failed: %s\n", strerror (s)); return 0; } s = pthread_create (&tid, &attr, (void *(*)(void *))fn, (void*)ctx); if (s != 0) { fprintf (stderr, "pthread_create failed: %s\n", strerror (s)); return 0; } s = pthread_attr_destroy (&attr); if (s != 0) { fprintf (stderr, "pthread_attr_destroy failed: %s\n", strerror (s)); return 0; } return tid; } intptr_t thread_start_low_priority (void (*fn)(void *ctx), void *ctx) { #ifdef __linux__ pthread_t tid; pthread_attr_t attr; int s = pthread_attr_init (&attr); if (s != 0) { fprintf (stderr, "pthread_attr_init failed: %s\n", strerror (s)); return 0; } #if !STATICLINK && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4 int policy; s = pthread_attr_getschedpolicy (&attr, &policy); if (s != 0) { fprintf (stderr, "pthread_attr_getschedpolicy failed: %s\n", strerror (s)); return 0; } int minprio = sched_get_priority_min (policy); #endif s = pthread_create (&tid, &attr, (void *(*)(void *))fn, (void*)ctx); if (s != 0) { fprintf (stderr, "pthread_create failed: %s\n", strerror (s)); return 0; } #if !STATICLINK && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4 s = pthread_setschedprio (tid, minprio); if (s != 0) { fprintf (stderr, "pthread_setschedprio failed: %s\n", strerror (s)); pthread_cancel (tid); return 0; } #endif s = pthread_attr_destroy (&attr); if (s != 0) { fprintf (stderr, "pthread_attr_destroy failed: %s\n", strerror (s)); pthread_cancel (tid); return 0; } return tid; #else return thread_start (fn, ctx); #endif } int thread_join (intptr_t tid) { void *retval; int s = pthread_join ((pthread_t)tid, &retval); if (s) { fprintf (stderr, "pthread_join failed: %s\n", strerror (s)); return -1; } return 0; } int thread_detach (intptr_t tid) { int s = pthread_detach ((pthread_t)tid); if (s) { fprintf (stderr, "pthread_detach failed: %s\n", strerror (s)); return -1; } return 0; } void thread_exit (void *retval) { pthread_exit (retval); } uintptr_t mutex_create_nonrecursive (void) { pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t)); pthread_mutexattr_t attr = {0}; pthread_mutexattr_init (&attr); pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL); int err = pthread_mutex_init (mtx, &attr); if (err != 0) { fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err)); return 0; } pthread_mutexattr_destroy (&attr); return (uintptr_t)mtx; } uintptr_t mutex_create (void) { pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t)); pthread_mutexattr_t attr = {0}; pthread_mutexattr_init (&attr); pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); int err = pthread_mutex_init (mtx, &attr); if (err != 0) { fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err)); return 0; } pthread_mutexattr_destroy (&attr); return (uintptr_t)mtx; } void mutex_free (uintptr_t _mtx) { pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx; pthread_mutex_destroy (mtx); free (mtx); } int mutex_lock (uintptr_t _mtx) { pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx; int err = pthread_mutex_lock (mtx); if (err != 0) { fprintf (stderr, "pthread_mutex_lock failed: %s\n", strerror (err)); } return err; } int mutex_unlock (uintptr_t _mtx) { pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx; int err = pthread_mutex_unlock (mtx); if (err != 0) { fprintf (stderr, "pthread_mutex_unlock failed: %s\n", strerror (err)); } return err; } uintptr_t cond_create (void) { pthread_cond_t *cond = malloc (sizeof (pthread_cond_t)); int err = pthread_cond_init (cond, NULL); if (err != 0) { fprintf (stderr, "pthread_cond_init failed: %s\n", strerror (err)); return 0; } return (uintptr_t)cond; } void cond_free (uintptr_t c) { if (c) { pthread_cond_t *cond = (pthread_cond_t *)c; pthread_cond_destroy (cond); free (cond); } } int cond_wait (uintptr_t c, uintptr_t m) { pthread_cond_t *cond = (pthread_cond_t *)c; pthread_mutex_t *mutex = (pthread_mutex_t *)m; int err = mutex_lock (m); if (err != 0) { return err; } err = pthread_cond_wait (cond, mutex); if (err != 0) { fprintf (stderr, "pthread_cond_wait failed: %s\n", strerror (err)); } return err; } int cond_signal (uintptr_t c) { pthread_cond_t *cond = (pthread_cond_t *)c; int err = pthread_cond_signal (cond); if (err != 0) { fprintf (stderr, "pthread_cond_signal failed: %s\n", strerror (err)); } return err; } int cond_broadcast (uintptr_t c) { pthread_cond_t *cond = (pthread_cond_t *)c; int err = pthread_cond_broadcast (cond); if (err != 0) { fprintf (stderr, "pthread_cond_broadcast failed: %s\n", strerror (err)); } return err; }