From owner-freebsd-hackers@FreeBSD.ORG Sat Sep 29 17:37:08 2007 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id ADAB116A41B for ; Sat, 29 Sep 2007 17:37:08 +0000 (UTC) (envelope-from arun@eagle.sharma-home.net) Received: from eagle.sharma-home.net (cpe-24-221-178-208.ca.sprintbbd.net [24.221.178.208]) by mx1.freebsd.org (Postfix) with ESMTP id 8390E13C469 for ; Sat, 29 Sep 2007 17:37:05 +0000 (UTC) (envelope-from arun@eagle.sharma-home.net) Received: by eagle.sharma-home.net (Postfix, from userid 1001) id 6CC1F341; Sat, 29 Sep 2007 08:14:37 -0700 (PDT) Date: Sat, 29 Sep 2007 08:14:37 -0700 From: Arun Sharma To: tbb-develop@lists.sourceforge.net Message-ID: <20070929151437.GA35489@sharma-home.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.1i X-Mailman-Approved-At: Sat, 29 Sep 2007 18:08:28 +0000 Cc: freebsd-hackers@freebsd.org, kfarnham@users.sourceforge.net Subject: TBB support for FreeBSD X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Sep 2007 17:37:08 -0000 FreeBSD support - tested on 7.0-CURRENT/amd64. Should apply cleanly to tbb20_20070815oss_src.tar.gz. Signed-off-by: Arun Sharma diff -r 627751b671bb -r ac2c116b7cee build/common.inc --- a/build/common.inc Sat Sep 29 16:18:03 2007 -0700 +++ b/build/common.inc Sat Sep 29 16:51:17 2007 -0700 @@ -37,6 +37,9 @@ ifndef tbb_os endif ifeq ($(OS), Darwin) export tbb_os=macos + endif + ifeq ($(OS), FreeBSD) + export tbb_os=freebsd endif endif endif diff -r 627751b671bb -r ac2c116b7cee build/freebsd.gcc.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build/freebsd.gcc.inc Sat Sep 29 16:51:17 2007 -0700 @@ -0,0 +1,98 @@ +# Copyright 2005-2007 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -MMD +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_KEY = -Wall -Werror +DYLIB_KEY = -shared +LIBDL = + +TBB_NOSTRICT = 1 + +CPLUS = g++ +INCLUDES += -I$(tbb_root)/src/tbb -I$(tbb_root)/include -I$(tbb_root)/src +LIB_LINK_FLAGS = -shared +LIBS = -lpthread -lrt +C_FLAGS = $(CPLUS_FLAGS) -x c + +ifeq ($(cfg), release) + CPLUS_FLAGS = -DDO_ITT_NOTIFY -O2 -DUSE_PTHREAD +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_DO_ASSERT -DDO_ITT_NOTIFY -g -O0 -DUSE_PTHREAD +endif + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= + +ifeq (itanium,$(arch)) +# Position-independent code (PIC) is a must for IA-64 + CPLUS_FLAGS += $(PIC_KEY) + $(PIC_KEY) = +endif + +ifeq (em64t,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +%.$(OBJ): %.s + cpp $(ASM_FLAGS) <$< | grep -v '^#' >$*.tmp + $(ASM) -o $@ $*.tmp + rm $*.tmp + +ASSEMBLY_SOURCE=$(arch)-gas +ifeq (itanium,$(arch)) + ASM=ias + TBB_ASM.OBJ = atomic_support.o lock_byte.o log2.o pause.o +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ +M_INCLUDES = $(INCLUDES) -I$(MALLOC_ROOT) -I$(MALLOC_SOURCE_ROOT) +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff -r 627751b671bb -r ac2c116b7cee build/freebsd.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build/freebsd.inc Sat Sep 29 16:51:17 2007 -0700 @@ -0,0 +1,86 @@ +# Copyright 2005-2007 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifndef arch + ifeq ($(shell uname -m),i686) + export arch:=ia32 + endif + ifeq ($(shell uname -m),ia64) + export arch:=itanium + endif + ifeq ($(shell uname -m),amd64) + export arch:=em64t + endif +endif + +ifndef runtime + gcc_version_full=$(shell gcc --version | grep 'gcc'| egrep -o ' [0-9]+\.[0-9]+\.[0-9]+.*' | sed -e 's/^\ //') + gcc_version=$(shell echo "$(gcc_version_full)" | egrep -o '^[0-9]+\.[0-9]+\.[0-9]+\s*' | head -n 1 | sed -e 's/ *//g') + os_version:=$(shell uname -r) + os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//') + export runtime:=cc$(os_version) +endif + +native_compiler := gcc +export compiler ?= gcc +debugger ?= gdb + +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= > /dev/null 2>&1 +SLASH=/ +MAKE_VERSIONS=sh $(tbb_root)/build/version_info_linux.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.tmp +MAKE_TBBVARS=sh $(tbb_root)/build/generate_tbbvars.sh + +ifdef LD_LIBRARY_PATH + export LD_LIBRARY_PATH := .:$(LD_LIBRARY_PATH) +else + export LD_LIBRARY_PATH := . +endif + +####### Build settigns ######################################################## + +OBJ = o +DLL = so +LIBEXT = so + +ifeq ($(cfg),debug) + DEBUG_SUFFIX = _debug +endif + +TBB.DEF = +TBB.DLL = libtbb$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = $(TBB.DLL) + +MALLOC.DLL = libtbbmalloc$(DEBUG_SUFFIX).so +MALLOC.LIB = $(MALLOC.DLL) + +TBB_NOSTRICT=1 + + + diff -r 627751b671bb -r ac2c116b7cee examples/common/gui/convideo.cpp --- a/examples/common/gui/convideo.cpp Sat Sep 29 16:18:03 2007 -0700 +++ b/examples/common/gui/convideo.cpp Sat Sep 29 16:51:17 2007 -0700 @@ -48,7 +48,7 @@ void video::win_load_accelerators(int id } #endif -#elif __linux__ || __APPLE__ +#elif __linux__ || __APPLE__ || __FreeBSD__ #include #include diff -r 627751b671bb -r ac2c116b7cee examples/parallel_for/tacheon/src/types.h --- a/examples/parallel_for/tacheon/src/types.h Sat Sep 29 16:18:03 2007 -0700 +++ b/examples/parallel_for/tacheon/src/types.h Sat Sep 29 16:51:17 2007 -0700 @@ -61,6 +61,8 @@ #ifdef _WIN32 #include #define alloca _alloca +#elif __FreeBSD__ +#include #else #include #endif diff -r 627751b671bb -r ac2c116b7cee examples/parallel_reduce/convex_hull/convex_hull.h --- a/examples/parallel_reduce/convex_hull/convex_hull.h Sat Sep 29 16:18:03 2007 -0700 +++ b/examples/parallel_reduce/convex_hull/convex_hull.h Sat Sep 29 16:51:17 2007 -0700 @@ -133,7 +133,7 @@ namespace util { }; int random(unsigned int& rseed) { -#if __linux__ || __APPLE__ +#if __linux__ || __APPLE__ || __FreeBSD__ return rand_r(&rseed); #elif _WIN32 return rand(); diff -r 627751b671bb -r ac2c116b7cee include/tbb/machine/freebsd_em64t.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/tbb/machine/freebsd_em64t.h Sat Sep 29 16:51:17 2007 -0700 @@ -0,0 +1,160 @@ +/* + Copyright 2005-2007 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_H +#error Do not include this file directly; include tbb_machine.h instead +#endif + +#include +#include +#include + +#define __TBB_OFFSET_OF_NEXT -8 +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 0 + +//! Load with acquire semantics, both for hardware and compiler. +template +inline T __TBB_load_with_acquire_via_explicit_fence(const volatile T& location) { + T tmp = location; + __asm__ __volatile__("": : :"memory"); + return tmp; +} + +//! Store with release semantics, both for hardware and compiler. +template +inline void __TBB_store_with_release_via_explicit_fence(volatile T& location, V value) { + __asm__ __volatile__("": : :"memory"); + location = value; +} + +#define __TBB_load_with_acquire __TBB_load_with_acquire_via_explicit_fence +#define __TBB_store_with_release __TBB_store_with_release_via_explicit_fence + +#define __MACHINE_DECL_ATOMICS(S,T,X) \ +static inline T __TBB_machine_cmpswp##S (volatile void *ptr, T value, T comparand ) \ +{ \ + T result; \ + \ + __asm__ __volatile__("lock\ncmpxchg" X " %2,%1" \ + : "=a"(result), "=m"(*(T *)ptr) \ + : "q"(value), "0"(comparand) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchadd##S(volatile void *ptr, T addend) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxadd" X " %0,%1" \ + : "=r"(result),"=m"(*(T *)ptr) \ + : "0"(addend) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchstore##S(volatile void *ptr, T value) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxchg" X " %0,%1" \ + : "=r"(result),"=m"(*(T *)ptr) \ + : "0"(value) \ + : "memory"); \ + return result; \ +} \ + +__MACHINE_DECL_ATOMICS(1,int8_t,"") +__MACHINE_DECL_ATOMICS(2,int16_t,"") +__MACHINE_DECL_ATOMICS(4,int32_t,"") +__MACHINE_DECL_ATOMICS(8,int64_t,"q") + +static inline int64_t __TBB_machine_lg( uint64_t x ) { + int64_t j; + __asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); + return j; +} + +static inline void __TBB_machine_or( volatile void *ptr, uint64_t addend ) { + __asm__ __volatile__("lock\norq %1,%0" : "=m"(*(uint64_t *)ptr) : "r"(addend) : "memory"); +} + +static inline void __TBB_machine_pause( int32_t delay ) { + for (int32_t i = 0; i < delay; i++) { + __asm__ __volatile__("pause;"); + } + return; +} + +// Machine specific atomic operations + +#define __TBB_CompareAndSwap1(P,V,C) __TBB_machine_cmpswp1(P,V,C) +#define __TBB_CompareAndSwap2(P,V,C) __TBB_machine_cmpswp2(P,V,C) +#define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) +#define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) +#define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp8(P,V,C) + +#define __TBB_FetchAndAdd1(P,V) __TBB_machine_fetchadd1(P,V) +#define __TBB_FetchAndAdd2(P,V) __TBB_machine_fetchadd2(P,V) +#define __TBB_FetchAndAdd4(P,V) __TBB_machine_fetchadd4(P,V) +#define __TBB_FetchAndAdd8(P,V) __TBB_machine_fetchadd8(P,V) +#define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd8(P,V) + +#define __TBB_FetchAndStore1(P,V) __TBB_machine_fetchstore1(P,V) +#define __TBB_FetchAndStore2(P,V) __TBB_machine_fetchstore2(P,V) +#define __TBB_FetchAndStore4(P,V) __TBB_machine_fetchstore4(P,V) +#define __TBB_FetchAndStore8(P,V) __TBB_machine_fetchstore8(P,V) +#define __TBB_FetchAndStoreW(P,V) __TBB_machine_fetchstore8(P,V) + +#define __TBB_Store8(P,V) (*P = V) +#define __TBB_Load8(P) (*P) + +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) + +// Definition of other functions +#define __TBB_Yield() sched_yield() +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +// Special atomic functions +#define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V) +#define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1) +#define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,-1) + +// Definition of Lock functions +#undef __TBB_TryLockByte +#undef __TBB_LockByte + +#define __TBB_cpuid +static inline void __TBB_x86_cpuid( int32_t buffer[4], int32_t mode ) { + // NOTE: gcc sometimes fails to compile the following asm. But icc always succeeds. + __asm__ ("cpuid" : "=a"(buffer[0]), + "=b"(buffer[1]), + "=c"(buffer[2]), + "=d"(buffer[3]) : "0"(mode) : "memory" ); +} + diff -r 627751b671bb -r ac2c116b7cee include/tbb/machine/freebsd_ia32.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/tbb/machine/freebsd_ia32.h Sat Sep 29 16:51:17 2007 -0700 @@ -0,0 +1,225 @@ +/* + Copyright 2005-2007 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_H +#error Do not include this file directly; include tbb_machine.h instead +#endif + +#include +#include +#include + +#define __TBB_OFFSET_OF_NEXT -4 +#define __TBB_WORDSIZE 4 +#define __TBB_BIG_ENDIAN 0 + + +#define __MACHINE_DECL_ATOMICS(S,T,X) \ +static inline T __TBB_machine_cmpswp##S (volatile void *ptr, T value, T comparand ) \ +{ \ + T result; \ + \ + __asm__ __volatile__("lock\ncmpxchg" X " %2,%1" \ + : "=a"(result), "=m"(*(T *)ptr) \ + : "q"(value), "0"(comparand) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchadd##S(volatile void *ptr, T addend) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxadd" X " %0,%1" \ + : "=r"(result), "=m"(*(T *)ptr) \ + : "0"(addend) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchstore##S(volatile void *ptr, T value) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxchg" X " %0,%1" \ + : "=r"(result), "=m"(*(T *)ptr) \ + : "0"(value) \ + : "memory"); \ + return result; \ +} \ + +__MACHINE_DECL_ATOMICS(1,int8_t,"") +__MACHINE_DECL_ATOMICS(2,int16_t,"") +__MACHINE_DECL_ATOMICS(4,int32_t,"l") + +static int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand ) +{ + const int32_t comparand_lo = (int32_t)comparand; + const int32_t comparand_hi = *(int32_t*)((intptr_t)&comparand+sizeof(int32_t)); + int64_t result; + // EBX register saved for compliancy with position-independent code (PIC) rules on IA32 + __asm__ __volatile__ ( + "pushl %%ebx\n\t" + "movl (%%ecx),%%ebx\n\t" + "movl 4(%%ecx),%%ecx\n\t" + "lock\ncmpxchg8b (%2)\n\t" + "popl %%ebx" + : "=A"(result), "=m"(*(int64_t *)ptr) + : "S"(ptr), + "a"(comparand_lo), + "d"(comparand_hi), + "c"(&value) + : "memory", "esp"); + return result; +} + +static inline int32_t __TBB_machine_lg( uint32_t x ) { + int32_t j; + __asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); + return j; +} + +static inline void __TBB_machine_or( volatile void *ptr, uint32_t addend ) { + __asm__ __volatile__("lock\norl %1,%0" : "=m"(*(uint32_t *)ptr) : "r"(addend) : "memory"); +} + +static inline void __TBB_machine_pause( int32_t delay ) { + for (int32_t i = 0; i < delay; i++) { + __asm__ __volatile__("pause;"); + } + return; +} + +static inline int64_t __TBB_machine_load8 (const volatile void *ptr) { + int64_t result; + __asm__ __volatile__ ( "fildq %1\n\t" + "fistpq %0" : "=m"(result) : "m"(*(uint64_t *)ptr), "m"(result) : "memory" ); + return result; +} + +static inline void __TBB_machine_store8 (volatile void *ptr, int64_t value) { + __asm__ __volatile__ ( "fildq %1\n\t" + "fistpq (%2)" : "=m"(*(int64_t *)ptr) : "m"(value), "r"(ptr) : "memory" ); +} + +template +struct __TBB_machine_load_store { + static inline T load_with_acquire(const volatile T& location) { + T to_return = location; + __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards + return to_return; + } + + static inline void store_with_release(volatile T &location, T value) { + __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards + location = value; + } +}; + +template +struct __TBB_machine_load_store { + static inline T load_with_acquire(const volatile T& location) { + T to_return = __TBB_machine_load8((volatile void *)&location); + __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating upwards + return to_return; + } + + static inline void store_with_release(volatile T &location, T value) { + __asm__ __volatile__("" : : : "memory" ); // Compiler fence to keep operations from migrating downwards + __TBB_machine_store8((volatile void *)&location,(int64_t)value); + } +}; + +template +inline T __TBB_machine_load_with_acquire(const volatile T &location) { + return __TBB_machine_load_store::load_with_acquire(location); +} + +template +inline void __TBB_machine_store_with_release(volatile T &location, V value) { + __TBB_machine_load_store::store_with_release(location,value); +} + +#define __TBB_load_with_acquire(L) __TBB_machine_load_with_acquire((L)) +#define __TBB_store_with_release(L,V) __TBB_machine_store_with_release((L),(V)) + +// Machine specific atomic operations + +#define __TBB_CompareAndSwap1(P,V,C) __TBB_machine_cmpswp1(P,V,C) +#define __TBB_CompareAndSwap2(P,V,C) __TBB_machine_cmpswp2(P,V,C) +#define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4(P,V,C) +#define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8(P,V,C) +#define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C) + +#define __TBB_FetchAndAdd1(P,V) __TBB_machine_fetchadd1(P,V) +#define __TBB_FetchAndAdd2(P,V) __TBB_machine_fetchadd2(P,V) +#define __TBB_FetchAndAdd4(P,V) __TBB_machine_fetchadd4(P,V) +#define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd4(P,V) + +#define __TBB_FetchAndStore1(P,V) __TBB_machine_fetchstore1(P,V) +#define __TBB_FetchAndStore2(P,V) __TBB_machine_fetchstore2(P,V) +#define __TBB_FetchAndStore4(P,V) __TBB_machine_fetchstore4(P,V) +#define __TBB_FetchAndStoreW(P,V) __TBB_machine_fetchstore4(P,V) + +#define __TBB_Store8(P,V) __TBB_machine_store8(P,V) +#define __TBB_Load8(P) __TBB_machine_load8(P) + +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) + + +// Those we chose not to implement (they will be implemented generically using CMPSWP8) +#undef __TBB_FetchAndAdd8 +#undef __TBB_FetchAndStore8 + +// Definition of other functions +#define __TBB_Yield() sched_yield() +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +// Special atomic functions +#define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V) +#define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1) +#define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,-1) + +// Definition of Lock functions +#undef __TBB_TryLockByte +#undef __TBB_LockByte + +#define __TBB_cpuid +static inline void __TBB_x86_cpuid( int32_t buffer[4], int32_t mode ) { + // EBX register saved for compliancy with position-independent code (PIC) rules on IA32 + __asm__ ("pushl %%ebx\n\t" + "cpuid\n\t" + "movl %%ebx,%1\n\t" + "popl %%ebx" + : "=a"(buffer[0]), + "=S"(buffer[1]), + "=c"(buffer[2]), + "=d"(buffer[3]) + : "0"(mode) + : "memory" ); +} + diff -r 627751b671bb -r ac2c116b7cee include/tbb/machine/freebsd_itanium.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/tbb/machine/freebsd_itanium.h Sat Sep 29 16:51:17 2007 -0700 @@ -0,0 +1,179 @@ +/* + Copyright 2005-2007 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_H +#error Do not include this file directly; include tbb_machine.h instead +#endif + +#include +#include +#include +#include + +#define __TBB_OFFSET_OF_NEXT -8 +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 0 +#define __TBB_DECL_FENCED_ATOMICS 1 + +// Most of the functions will be in a .s file + +extern "C" { + int8_t __TBB_machine_cmpswp1__TBB_full_fence (volatile void *ptr, int8_t value, int8_t comparand); + int8_t __TBB_machine_fetchadd1__TBB_full_fence (volatile void *ptr, int8_t addend); + int8_t __TBB_machine_fetchadd1acquire(volatile void *ptr, int8_t addend); + int8_t __TBB_machine_fetchadd1release(volatile void *ptr, int8_t addend); + int8_t __TBB_machine_fetchstore1acquire(volatile void *ptr, int8_t value); + int8_t __TBB_machine_fetchstore1release(volatile void *ptr, int8_t value); + + int16_t __TBB_machine_cmpswp2__TBB_full_fence (volatile void *ptr, int16_t value, int16_t comparand); + int16_t __TBB_machine_fetchadd2__TBB_full_fence (volatile void *ptr, int16_t addend); + int16_t __TBB_machine_fetchadd2acquire(volatile void *ptr, int16_t addend); + int16_t __TBB_machine_fetchadd2release(volatile void *ptr, int16_t addend); + int16_t __TBB_machine_fetchstore2acquire(volatile void *ptr, int16_t value); + int16_t __TBB_machine_fetchstore2release(volatile void *ptr, int16_t value); + + int32_t __TBB_machine_fetchstore4__TBB_full_fence (volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchstore4acquire(volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchstore4release(volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchadd4acquire(volatile void *ptr, int32_t addend); + int32_t __TBB_machine_fetchadd4release(volatile void *ptr, int32_t addend); + + int64_t __TBB_machine_cmpswp8__TBB_full_fence (volatile void *ptr, int64_t value, int64_t comparand); + int64_t __TBB_machine_fetchstore8__TBB_full_fence (volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchstore8acquire(volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchstore8release(volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchadd8acquire(volatile void *ptr, int64_t addend); + int64_t __TBB_machine_fetchadd8release(volatile void *ptr, int64_t addend); + + int8_t __TBB_machine_cmpswp1acquire(volatile void *ptr, int8_t value, int8_t comparand); + int8_t __TBB_machine_cmpswp1release(volatile void *ptr, int8_t value, int8_t comparand); + int8_t __TBB_machine_fetchstore1__TBB_full_fence (volatile void *ptr, int8_t value); + + int16_t __TBB_machine_cmpswp2acquire(volatile void *ptr, int16_t value, int16_t comparand); + int16_t __TBB_machine_cmpswp2release(volatile void *ptr, int16_t value, int16_t comparand); + int16_t __TBB_machine_fetchstore2__TBB_full_fence (volatile void *ptr, int16_t value); + + int32_t __TBB_machine_cmpswp4__TBB_full_fence (volatile void *ptr, int32_t value, int32_t comparand); + int32_t __TBB_machine_cmpswp4acquire(volatile void *ptr, int32_t value, int32_t comparand); + int32_t __TBB_machine_cmpswp4release(volatile void *ptr, int32_t value, int32_t comparand); + int32_t __TBB_machine_fetchadd4__TBB_full_fence (volatile void *ptr, int32_t value); + + int64_t __TBB_machine_cmpswp8acquire(volatile void *ptr, int64_t value, int64_t comparand); + int64_t __TBB_machine_cmpswp8release(volatile void *ptr, int64_t value, int64_t comparand); + int64_t __TBB_machine_fetchadd8__TBB_full_fence (volatile void *ptr, int64_t value); + + int64_t __TBB_machine_lg(uint64_t value); + void __TBB_machine_pause(int32_t delay); + bool __TBB_machine_trylockbyte( volatile unsigned char &ptr ); +} + +#define __TBB_CompareAndSwap1(P,V,C) __TBB_machine_cmpswp1__TBB_full_fence(P,V,C) +#define __TBB_CompareAndSwap2(P,V,C) __TBB_machine_cmpswp2__TBB_full_fence(P,V,C) + +#define __TBB_FetchAndAdd1(P,V) __TBB_machine_fetchadd1__TBB_full_fence(P,V) +#define __TBB_FetchAndAdd1acquire(P,V) __TBB_machine_fetchadd1acquire(P,V) +#define __TBB_FetchAndAdd1release(P,V) __TBB_machine_fetchadd1release(P,V) +#define __TBB_FetchAndAdd2(P,V) __TBB_machine_fetchadd2__TBB_full_fence(P,V) +#define __TBB_FetchAndAdd2acquire(P,V) __TBB_machine_fetchadd2acquire(P,V) +#define __TBB_FetchAndAdd2release(P,V) __TBB_machine_fetchadd2release(P,V) +#define __TBB_FetchAndAdd4acquire(P,V) __TBB_machine_fetchadd4acquire(P,V) +#define __TBB_FetchAndAdd4release(P,V) __TBB_machine_fetchadd4release(P,V) +#define __TBB_FetchAndAdd8acquire(P,V) __TBB_machine_fetchadd8acquire(P,V) +#define __TBB_FetchAndAdd8release(P,V) __TBB_machine_fetchadd8release(P,V) + +#define __TBB_FetchAndStore1acquire(P,V) __TBB_machine_fetchstore1acquire(P,V) +#define __TBB_FetchAndStore1release(P,V) __TBB_machine_fetchstore1release(P,V) +#define __TBB_FetchAndStore2acquire(P,V) __TBB_machine_fetchstore2acquire(P,V) +#define __TBB_FetchAndStore2release(P,V) __TBB_machine_fetchstore2release(P,V) +#define __TBB_FetchAndStore4acquire(P,V) __TBB_machine_fetchstore4acquire(P,V) +#define __TBB_FetchAndStore4release(P,V) __TBB_machine_fetchstore4release(P,V) +#define __TBB_FetchAndStore8acquire(P,V) __TBB_machine_fetchstore8acquire(P,V) +#define __TBB_FetchAndStore8release(P,V) __TBB_machine_fetchstore8release(P,V) + +#define __TBB_CompareAndSwap1acquire(P,V,C) __TBB_machine_cmpswp1acquire(P,V,C) +#define __TBB_CompareAndSwap1release(P,V,C) __TBB_machine_cmpswp1release(P,V,C) +#define __TBB_CompareAndSwap2acquire(P,V,C) __TBB_machine_cmpswp2acquire(P,V,C) +#define __TBB_CompareAndSwap2release(P,V,C) __TBB_machine_cmpswp2release(P,V,C) +#define __TBB_CompareAndSwap4(P,V,C) __TBB_machine_cmpswp4__TBB_full_fence(P,V,C) +#define __TBB_CompareAndSwap4acquire(P,V,C) __TBB_machine_cmpswp4acquire(P,V,C) +#define __TBB_CompareAndSwap4release(P,V,C) __TBB_machine_cmpswp4release(P,V,C) +#define __TBB_CompareAndSwap8(P,V,C) __TBB_machine_cmpswp8__TBB_full_fence(P,V,C) +#define __TBB_CompareAndSwap8acquire(P,V,C) __TBB_machine_cmpswp8acquire(P,V,C) +#define __TBB_CompareAndSwap8release(P,V,C) __TBB_machine_cmpswp8release(P,V,C) + +#define __TBB_FetchAndAdd4(P,V) __TBB_machine_fetchadd4__TBB_full_fence(P,V) +#define __TBB_FetchAndAdd8(P,V) __TBB_machine_fetchadd8__TBB_full_fence(P,V) + +#define __TBB_FetchAndStore1(P,V) __TBB_machine_fetchstore1__TBB_full_fence(P,V) +#define __TBB_FetchAndStore2(P,V) __TBB_machine_fetchstore2__TBB_full_fence(P,V) +#define __TBB_FetchAndStore4(P,V) __TBB_machine_fetchstore4__TBB_full_fence(P,V) +#define __TBB_FetchAndStore8(P,V) __TBB_machine_fetchstore8__TBB_full_fence(P,V) + +#define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAdd8acquire(P,1) +#define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAdd8release(P,-1) + +#ifndef __INTEL_COMPILER +template +inline void __TBB_store_with_release_via_explicit_fence(volatile T& location, V value) { + __asm__ __volatile__("": : :"memory"); + location = value; +} + +//! Load with acquire semantics, both for hardware and compiler. +/** Even though GCC imbues volatile loads with acquire semantics, + it sometimes hoists loads over the acquire fence. We use + an explicit memory fence to prevent such incorrect hoisting. */ +template +inline T __TBB_load_with_acquire_via_explicit_fence(const volatile T& location) { + T tmp = location; + __asm__ __volatile__("": : :"memory"); + return tmp; +} +#define __TBB_load_with_acquire(L) __TBB_load_with_acquire_via_explicit_fence(L) +#define __TBB_store_with_release(L,V) __TBB_store_with_release_via_explicit_fence(L,V) +#endif + +// Special atomic functions +#define __TBB_CompareAndSwapW(P,V,C) __TBB_CompareAndSwap8(P,V,C) +#define __TBB_FetchAndStoreW(P,V) __TBB_FetchAndStore8(P,V) +#define __TBB_FetchAndAddW(P,V) __TBB_FetchAndAdd8(P,V) +#define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAdd8release(P,V) + +// Not needed +#undef __TBB_Store8 +#undef __TBB_Load8 + +// Definition of Lock functions +#define __TBB_TryLockByte(P) __TBB_machine_trylockbyte(P) +#undef __TBB_LockByte + +// Definition of other utility functions +#define __TBB_Yield() sched_yield() +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + diff -r 627751b671bb -r ac2c116b7cee include/tbb/tbb_machine.h --- a/include/tbb/tbb_machine.h Sat Sep 29 16:18:03 2007 -0700 +++ b/include/tbb/tbb_machine.h Sat Sep 29 16:51:17 2007 -0700 @@ -65,6 +65,16 @@ typedef unsigned __int64 uint64_t; #include "tbb/machine/linux_em64t.h" #elif __ia64__ #include "tbb/machine/linux_itanium.h" +#endif + +#elif __FreeBSD__ + +#if __i386__ +#include "tbb/machine/freebsd_ia32.h" +#elif __x86_64__ +#include "tbb/machine/freebsd_em64t.h" +#elif __ia64__ +#include "tbb/machine/freebsd_itanium.h" #endif #elif __APPLE__ diff -r 627751b671bb -r ac2c116b7cee src/tbb/cache_aligned_allocator.cpp --- a/src/tbb/cache_aligned_allocator.cpp Sat Sep 29 16:18:03 2007 -0700 +++ b/src/tbb/cache_aligned_allocator.cpp Sat Sep 29 16:51:17 2007 -0700 @@ -69,7 +69,7 @@ static const DynamicLinkDescriptor Mallo #define MALLOCLIB_NAME "tbbmalloc" DEBUG_SUFFIX ".dll" #elif __APPLE__ #define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".dylib" -#elif __linux__ +#elif __linux__ || __FreeBSD__ #define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".so" #else #error Unknown OS diff -r 627751b671bb -r ac2c116b7cee src/tbb/itt_notify.cpp --- a/src/tbb/itt_notify.cpp Sat Sep 29 16:18:03 2007 -0700 +++ b/src/tbb/itt_notify.cpp Sat Sep 29 16:51:17 2007 -0700 @@ -70,7 +70,7 @@ static const DynamicLinkDescriptor ITT_H // LIBITTNOTIFY_NAME is the name of the ITT notification library # if _WIN32||_WIN64 # define LIBITTNOTIFY_NAME "libittnotify.dll" -# elif __linux__ +# elif __linux__ || __FreeBSD__ # define LIBITTNOTIFY_NAME "libittnotify.so" # elif __APPLE__ # define LIBITTNOTIFY_NAME "libittnotify.dylib" diff -r 627751b671bb -r ac2c116b7cee src/tbb/tbb_misc.h --- a/src/tbb/tbb_misc.h Sat Sep 29 16:18:03 2007 -0700 +++ b/src/tbb/tbb_misc.h Sat Sep 29 16:51:17 2007 -0700 @@ -32,11 +32,8 @@ #include "tbb/tbb_stddef.h" #include "tbb/tbb_machine.h" -#if __linux__ -#include -#elif __APPLE__ -#include -#include +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) +#include #endif namespace tbb { @@ -59,24 +56,11 @@ static inline int DetectNumberOfWorkers( return number_of_workers; } -#elif __linux__ +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) static inline int DetectNumberOfWorkers( void ) { if (!number_of_workers) { - number_of_workers = get_nprocs(); - } - return number_of_workers; -} - -#elif __APPLE__ - -static inline int DetectNumberOfWorkers( void ) { - if (!number_of_workers) { - int name[2] = {CTL_HW, HW_AVAILCPU}; - int ncpu; - size_t size = sizeof(ncpu); - sysctl( name, 2, &ncpu, &size, NULL, 0 ); - number_of_workers = ncpu; + number_of_workers = sysconf(_SC_NPROCESSORS_ONLN); } return number_of_workers; } diff -r 627751b671bb -r ac2c116b7cee src/tbbmalloc/MemoryAllocator.cpp --- a/src/tbbmalloc/MemoryAllocator.cpp Sat Sep 29 16:18:03 2007 -0700 +++ b/src/tbbmalloc/MemoryAllocator.cpp Sat Sep 29 16:51:17 2007 -0700 @@ -324,7 +324,7 @@ static inline unsigned int highestBitPos unsigned int pos; #if __ARCH_x86_32||__ARCH_x86_64 -# if __linux__||__APPLE__ +# if __linux__||__APPLE__ || __FreeBSD__ __asm__ ("bsr %1,%0" : "=r"(pos) : "r"(number)); # elif (_WIN32 && (!_WIN64 || __INTEL_COMPILER)) __asm diff -r 627751b671bb -r ac2c116b7cee src/test/harness.h --- a/src/test/harness.h Sat Sep 29 16:18:03 2007 -0700 +++ b/src/test/harness.h Sat Sep 29 16:51:17 2007 -0700 @@ -38,7 +38,7 @@ #include "tbb/tbb_stddef.h" #include "harness_assert.h" -#if __linux__||__APPLE__ +#if __linux__||__APPLE__ || __FreeBSD__ #include #elif _WIN32||WIN64 #include @@ -120,7 +120,7 @@ public: //! Start task void start() { -#if __linux__||__APPLE__ +#if __linux__||__APPLE__ || __FreeBSD__ int status = pthread_create(&thread_id, NULL, thread_function, this); ASSERT(0==status, "NativeParallelFor: pthread_create failed"); #else @@ -132,7 +132,7 @@ public: //! Wait for task to finish void wait_to_finish() { -#if __linux__||__APPLE__ +#if __linux__||__APPLE__ || __FreeBSD__ int status = pthread_join( thread_id, NULL ); ASSERT( !status, "pthread_join failed" ); #else @@ -148,7 +148,7 @@ public: Top-level caller should let index default to 0. */ static size_t build_task_array( const Range& range, const Body& body, NativeParalleForTask* array, size_t index ); private: -#if __linux__||__APPLE__ +#if __linux__||__APPLE__ || __FreeBSD__ pthread_t thread_id; #else HANDLE thread_handle; @@ -160,7 +160,7 @@ private: //! Body to invoke over the range. const Body body; -#if __linux__||__APPLE__ +#if __linux__||__APPLE__ || __FreeBSD__ static void* thread_function(void* object) #else static unsigned __stdcall thread_function( void* object ) --- a/src/test/test_concurrent_hash_map.cpp Sat Sep 29 16:51:17 2007 -0700 +++ b/src/test/test_concurrent_hash_map.cpp Sat Sep 29 17:08:18 2007 -0700 @@ -320,7 +320,7 @@ public: // more logical threads than physical threads, and should yield in // order to let suspended logical threads make progress. j = 0; -#if __linux__||__APPLE__ +#if __linux__ || __APPLE__ || __FreeBSD__ sched_yield(); #else Sleep(0);