Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,32 @@ check_include_file ( pthread.h HAVE_PTHREAD_H )
check_include_file ( signal.h HAVE_SIGNAL_H )
check_include_file ( getopt.h HAVE_GETOPT_H )
check_include_file ( stdint.h HAVE_STDINT_H )
check_c_source_compiles ("
#include <stdatomic.h>
int main(void) {
atomic_thread_fence(memory_order_acquire);
atomic_thread_fence(memory_order_seq_cst);
return 0;
}
" HAVE_STDATOMIC_H )
check_c_source_compiles ("
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
int main (int argc, char ** argv) {
syscall (__NR_futex, NULL, FUTEX_WAKE, FUTEX_WAIT);
return 0;
}
" HAVE_FUTEX)
check_c_source_compiles ("
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
int main (int argc, char ** argv) {
syscall (__NR_futex_time64, NULL, FUTEX_WAKE, FUTEX_WAIT);
return 0;
}
" HAVE_FUTEX_TIME64 )
check_type_size ( "long long" LONG_LONG )
if ( NOT HAVE_LONG_LONG AND NOT MSVC)
message ( FATAL_ERROR "Your compiler does not support intrinsic type 'long long'. Unable to compile fluidsynth." )
Expand Down
12 changes: 12 additions & 0 deletions src/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
/* whether or not we are supporting DART */
#cmakedefine DART_SUPPORT @DART_SUPPORT@

/* Define if building for Apple platforms */
#cmakedefine APPLE @APPLE@

/* Define if building for Mac OS X Darwin */
#cmakedefine DARWIN @DARWIN@

Expand Down Expand Up @@ -121,6 +124,15 @@
/* Define to 1 if you have the <getopt.h> header file. */
#cmakedefine HAVE_GETOPT_H @HAVE_GETOPT_H@

/* Define to 1 if you have the <stdatomic.h> header file. */
#cmakedefine HAVE_STDATOMIC_H @HAVE_STDATOMIC_H@

/* Define to 1 if you have the <linux/futex.h> header file. */
#cmakedefine HAVE_FUTEX @HAVE_FUTEX@

/* Define to 1 if you have futex_time64(2) system call. */
#cmakedefine HAVE_FUTEX_TIME64 @HAVE_FUTEX_TIME64@

/* Define to 1 if you have the inet_ntop() function. */
#cmakedefine HAVE_INETNTOP @HAVE_INETNTOP@

Expand Down
2 changes: 2 additions & 0 deletions src/utils/fluid_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
#include "fluid_sys_embedded.h"
#elif OSAL_cpp11
#include "fluid_sys_cpp11.h"
#elif OSAL_posix
#include "fluid_sys_posix.h"
#else
#error "no OS abstraction configured"
#endif
Expand Down
157 changes: 157 additions & 0 deletions src/utils/fluid_sys_posix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library 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 library 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 library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/

#include <pthread.h>

#include <utils/fluid_sys.h>
#include <utils/fluid_sys_posix.h>

#ifdef HAVE_STDATOMIC_H

#include <stdatomic.h>

// we want these in .c file, because otherwise it could be used by C++ code

#define exchange_acquire(ptr, _new) \
atomic_exchange_explicit((atomic_uint *) (ptr), (_new), __ATOMIC_ACQUIRE)

#define exchange_release(ptr, _new) \
atomic_exchange_explicit((atomic_uint *) (ptr), (_new), __ATOMIC_RELEASE)

#else

#define exchange_acquire(ptr, _new) \
__atomic_exchange_4((ptr), (_new), __ATOMIC_ACQUIRE)

#define exchange_release(ptr, _new) \
__atomic_exchange_4((ptr), (_new), __ATOMIC_RELEASE)

#endif


static void* set_prio_and_continue(void* arg) {
fluid_thread_info_t* tinfo;
tinfo = (fluid_thread_info_t*)arg;
fluid_thread_self_set_prio(tinfo->prio_level);
tinfo->func(tinfo->data);
FLUID_FREE(tinfo);
return 0;
}

FLUID_INLINE fluid_thread_t *
new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach)
{
int create_result;
void* actual_data;
fluid_thread_info_t* tinfo = 0;
pthread_attr_t attr;
pthread_t *thread;

thread = FLUID_NEW(pthread_t);
if (thread) {
fluid_thread_func_t actual_func = func;
actual_data = data;
if (prio_level > 0) {
tinfo = FLUID_NEW(fluid_thread_info_t);
if (tinfo == 0) {
FLUID_LOG(FLUID_ERR, "out of memory");
free(thread);
return 0;
}
tinfo->prio_level = prio_level;
tinfo->func = func;
tinfo->data = data;
actual_func = set_prio_and_continue;
actual_data = tinfo;
}
if (pthread_attr_init(&attr) == 0) {
#ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
pthread_attr_setinheritsched (&attr, PTHREAD_INHERIT_SCHED);
#endif
create_result = pthread_create(thread, &attr, actual_func, actual_data);

if (detach) {
pthread_detach(*thread);
}

pthread_attr_destroy(&attr);

if (create_result == 0) {
return thread;
}
FLUID_LOG(FLUID_ERR, "pthread_create failed");
}
else {
FLUID_LOG(FLUID_ERR, "pthread_attr_init failed");
}

free(tinfo);
free(thread);
}
return 0;
}


/* futex-related code adapted from glib */

#if defined(HAVE_FUTEX) || defined(HAVE_FUTEX_TIME64)
static inline void slow_path_lock(fluid_mutex_t* m) { fluid_futex_simple(&m->state, (size_t) FUTEX_WAIT_PRIVATE, FLUID_MUTEX_STATE_CONTENDED, NULL); }
static inline void slow_path_unlock(fluid_mutex_t* m) { fluid_futex_simple(&m->state, (size_t) FUTEX_WAKE_PRIVATE, (size_t) 1, NULL); }
#else
static inline void slow_path_lock(fluid_mutex_t* m) { pthread_mutex_lock(&m->slow_path_mutex); }
static inline void slow_path_unlock(fluid_mutex_t* m) { pthread_mutex_unlock(&m->slow_path_mutex); }
#endif

void _fluid_light_mutex_lock_slowpath(fluid_mutex_t* m) {
/* Set to contended. If it was empty before then we
* just acquired the lock.
*
* Otherwise, sleep for as long as the contended state remains...
*/
while (exchange_acquire (&m->state, FLUID_MUTEX_STATE_CONTENDED) != FLUID_MUTEX_STATE_EMPTY)
{
slow_path_lock(m);
}
}

void _fluid_light_mutex_unlock_slowpath(fluid_mutex_t* m, unsigned int prev)
{
/* We seem to get better code for the uncontended case by splitting
* this out...
*/
if FLUID_UNLIKELY(prev == FLUID_MUTEX_STATE_EMPTY)
{
FLUID_LOG(FLUID_PANIC, "Attempt to unlock mutex that was not locked\n");
abort();
}

slow_path_unlock(m);
}

void _fluid_mutex_unlock_by_pointer(fluid_mutex_t* m)
{
unsigned int prev;

prev = exchange_release (&m->state, FLUID_MUTEX_STATE_EMPTY);

/* 1->0 and we're done. Anything else and we need to signal... */
if FLUID_UNLIKELY(prev != FLUID_MUTEX_STATE_OWNED)
_fluid_light_mutex_unlock_slowpath(m, prev);
}
Loading
Loading