Skip to content

Commit

Permalink
Committing Intel(R) TBB 2017 Update 8 source code
Browse files Browse the repository at this point in the history
  • Loading branch information
tbbdev committed Sep 22, 2017
1 parent eb6336a commit 75224c4
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 52 deletions.
11 changes: 11 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@
The list of most significant changes made over time in
Intel(R) Threading Building Blocks (Intel(R) TBB).

Intel TBB 2017 Update 8
TBB_INTERFACE_VERSION == 9108

Changes (w.r.t. Intel TBB 2017 Update 7):

Bugs fixed:

- Fixed an assertion failure in debug tbbmalloc binaries when
TBBMALLOC_CLEAN_ALL_BUFFERS is used.

------------------------------------------------------------------------
Intel TBB 2017 Update 7
TBB_INTERFACE_VERSION == 9107

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Intel(R) Threading Building Blocks 2017 Update 7
[![Stable release](https://img.shields.io/badge/version-2017_U7-green.svg)](https://github.com/01org/tbb/releases/tag/2017_U7)
# Intel(R) Threading Building Blocks 2017 Update 8
[![Stable release](https://img.shields.io/badge/version-2017_U8-green.svg)](https://github.com/01org/tbb/releases/tag/2017_U8)
[![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE)

Intel(R) Threading Building Blocks (Intel(R) TBB) lets you easily write parallel C++ programs that take
Expand Down
2 changes: 1 addition & 1 deletion cmake/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Use cases of Intel TBB integration into CMake-aware projects
------------------------------------------------------------
There are two types of Intel TBB packages:
* Binary packages with pre-built binaries for Windows* OS, Linux* OS and macOS*. They are available on the releases page of the Github repository: https://github.com/01org/tbb/releases. The main purpose of the binary package integration is the ability to build Intel TBB header files and binaries into your CMake-aware project.
* A source package is also available to download from the release page via the Source code link. In addition, it can be cloned from the repository by ``git clone https://github.com/01org/tbb.git``. The main purpose of the source package integration is to allow you to do a custom build of the Intel TBB library from the source files and then build that into your CMake-aware project.
* A source package is also available to download from the release page via the "Source code" link. In addition, it can be cloned from the repository by ``git clone https://github.com/01org/tbb.git``. The main purpose of the source package integration is to allow you to do a custom build of the Intel TBB library from the source files and then build that into your CMake-aware project.

There are four types of CMake modules that can be used to integrate Intel TBB: `TBBConfig`, `TBBGet`, `TBBMakeConfig` and `TBBBuild`. See `Technical documentation for CMake modules`_ section for additional details.

Expand Down
45 changes: 45 additions & 0 deletions cmake/tbb_config_generator.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (c) 2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
#
#

function(tbb_conf_gen_print_help)
message("Usage: cmake -DTBB_ROOT=<tbb_root> -DTBB_OS=Linux|Windows|Darwin [-DSAVE_TO=<path>] -P tbb_config_generator.cmake")
endfunction()

if (NOT DEFINED TBB_ROOT)
tbb_conf_gen_print_help()
message(FATAL_ERROR "Required parameter TBB_ROOT is not defined")
endif()

if (NOT EXISTS "${TBB_ROOT}")
tbb_conf_gen_print_help()
message(FATAL_ERROR "TBB_ROOT=${TBB_ROOT} does not exist")
endif()

if (NOT DEFINED TBB_OS)
tbb_conf_gen_print_help()
message(FATAL_ERROR "Required parameter TBB_OS is not defined")
endif()

if (DEFINED SAVE_TO)
set(tbb_conf_gen_save_to_param SAVE_TO ${SAVE_TO})
endif()

include(${CMAKE_CURRENT_LIST_DIR}/TBBMakeConfig.cmake)
tbb_make_config(TBB_ROOT ${TBB_ROOT} CONFIG_DIR tbb_config_dir SYSTEM_NAME ${TBB_OS} ${tbb_conf_gen_save_to_param})

message(STATUS "TBBConfig files were created in ${tbb_config_dir}")
2 changes: 1 addition & 1 deletion include/tbb/tbb_stddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#define TBB_VERSION_MINOR 0

// Engineering-focused interface version
#define TBB_INTERFACE_VERSION 9107
#define TBB_INTERFACE_VERSION 9108
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000

// The oldest major interface version still supported
Expand Down
1 change: 0 additions & 1 deletion python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#
#


# System imports
from __future__ import print_function
import platform
Expand Down
1 change: 0 additions & 1 deletion python/tbb.i
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#
#


# Based on the software developed by:
# Copyright (c) 2008,2016 david decotigny (Pool of threads)
# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool)
Expand Down
7 changes: 4 additions & 3 deletions src/tbb/market.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ market& market::global_market ( bool is_public, unsigned workers_requested, size
// The requested number of threads is intentionally not considered in
// computation of the hard limit, in order to separate responsibilities
// and avoid complicated interactions between global_control and task_scheduler_init.
const unsigned workers_hard_limit = max(factor*governor::default_num_threads(), app_parallelism_limit());
// The market guarantees that at least 256 threads might be created.
const unsigned workers_hard_limit = max(max(factor*governor::default_num_threads(), 256u), app_parallelism_limit());
const unsigned workers_soft_limit = calc_workers_soft_limit(workers_requested, workers_hard_limit);
// Create the global market instance
size_t size = sizeof(market);
Expand Down Expand Up @@ -695,9 +696,9 @@ void market::process( job& j ) {
// Workers leave market because there is no arena in need. It can happen earlier than
// adjust_job_count_estimate() decreases my_slack and RML can put this thread to sleep.
// It might result in a busy-loop checking for my_slack<0 and calling this method instantly.
// first_interval>0 and the pause refines this spinning.
// first_interval>0 and the yield refines this spinning.
if( i > 0 )
prolonged_pause();
__TBB_Yield();
else
#if !__TBB_SLEEP_PERMISSION
break;
Expand Down
57 changes: 28 additions & 29 deletions src/tbbmalloc/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ bool RecursiveMallocCallProtector::noRecursion() {

#endif // MALLOC_CHECK_RECURSION

/** Support for handling the special UNUSABLE pointer state **/
const intptr_t UNUSABLE = 0x1;
inline bool isSolidPtr( void* ptr ) {
return (UNUSABLE|(intptr_t)ptr)!=UNUSABLE;
}
inline bool isNotForUse( void* ptr ) {
return (intptr_t)ptr==UNUSABLE;
}

/*
* Block::objectSize value used to mark blocks allocated by startupAlloc
*/
Expand Down Expand Up @@ -346,14 +355,14 @@ class LocalBlockFields : public GlobalBlockFields, Padding<blockHeaderAlignment
class Block : public LocalBlockFields,
Padding<2*blockHeaderAlignment - sizeof(LocalBlockFields)> {
public:
bool empty() const { return allocatedCount==0 && publicFreeList==NULL; }
bool empty() const { return allocatedCount==0 && !isSolidPtr(publicFreeList); }
inline FreeObject* allocate();
inline FreeObject *allocateFromFreeList();
inline bool emptyEnoughToUse();
bool freeListNonNull() { return freeList; }
void freePublicObject(FreeObject *objectToFree);
inline void freeOwnObject(void *object);
void makeEmpty();
void reset();
void privatizePublicFreeList( bool cleanup = false );
void restoreBumpPtr();
void privatizeOrphaned(TLSData *tls, unsigned index);
Expand Down Expand Up @@ -390,7 +399,7 @@ class Block : public LocalBlockFields,
// expected after double free
MALLOC_ASSERT(toFree != freeList, msg);
// check against head of publicFreeList, to detect double free
// involiving foreign thread
// involving foreign thread
MALLOC_ASSERT(toFree != publicFreeList, msg);
}
#else
Expand Down Expand Up @@ -887,16 +896,6 @@ void BootStrapBlocks::reset()
static MallocMutex publicFreeListLock; // lock for changes of publicFreeList
#endif

const uintptr_t UNUSABLE = 0x1;
inline bool isSolidPtr( void* ptr )
{
return (UNUSABLE|(uintptr_t)ptr)!=UNUSABLE;
}
inline bool isNotForUse( void* ptr )
{
return (uintptr_t)ptr==UNUSABLE;
}

/********* End rough utility code **************/

/* LifoList assumes zero initialization so a vector of it can be created
Expand Down Expand Up @@ -1034,7 +1033,7 @@ Block *MemoryPool::getEmptyBlock(size_t size)

void MemoryPool::returnEmptyBlock(Block *block, bool poolTheBlock)
{
block->makeEmpty();
block->reset();
if (poolTheBlock) {
extMemPool.tlsPointerKey.getThreadMallocTLS()->freeSlabBlocks.returnBlock(block);
}
Expand Down Expand Up @@ -1310,7 +1309,7 @@ void Block::freeOwnObject(void *object)
else
STAT_increment(getThreadId(), getIndex(objectSize), freeToActiveBlock);
#endif
if (allocatedCount==0 && publicFreeList==NULL) {
if (empty()) {
// The bump pointer is about to be restored for the block,
// no need to find objectToFree here (this is costly).

Expand Down Expand Up @@ -1373,33 +1372,33 @@ void Block::freePublicObject (FreeObject *objectToFree)
void Block::privatizePublicFreeList( bool cleanup )
{
FreeObject *temp, *localPublicFreeList;
const intptr_t endMarker = cleanup? UNUSABLE : 0;

// During cleanup of orphaned blocks, the calling thread is not registered as the owner
MALLOC_ASSERT( cleanup || isOwnedByCurrentThread(), ASSERT_TEXT );
#if FREELIST_NONBLOCKING
temp = publicFreeList;
do {
localPublicFreeList = temp;
temp = (FreeObject*)AtomicCompareExchange(
(intptr_t&)publicFreeList,
0, (intptr_t)localPublicFreeList);
temp = (FreeObject*)AtomicCompareExchange( (intptr_t&)publicFreeList,
endMarker, (intptr_t)localPublicFreeList);
// no backoff necessary because trying to make change, not waiting for a change
} while( temp != localPublicFreeList );
#else
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
{
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
localPublicFreeList = publicFreeList;
publicFreeList = NULL;
publicFreeList = endMarker;
}
temp = localPublicFreeList;
#endif
MALLOC_ITT_SYNC_ACQUIRED(&publicFreeList);

// there should be something in publicFreeList, unless called by cleanup of orphaned blocks
MALLOC_ASSERT( cleanup || localPublicFreeList, ASSERT_TEXT );
// publicFreeList must have been UNUSABLE (possible for orphaned blocks) or valid, but not NULL
MALLOC_ASSERT( localPublicFreeList!=NULL, ASSERT_TEXT );
MALLOC_ASSERT( localPublicFreeList==temp, ASSERT_TEXT );
if( isSolidPtr(temp) ) { // return/getPartialBlock could set it to UNUSABLE
if( isSolidPtr(temp) ) {
MALLOC_ASSERT( allocatedCount <= (slabSize-sizeof(Block))/objectSize, ASSERT_TEXT );
/* other threads did not change the counter freeing our blocks */
allocatedCount--;
Expand Down Expand Up @@ -1447,13 +1446,13 @@ void Block::shareOrphaned(intptr_t binTag, unsigned index)
if ((intptr_t)nextPrivatizable==binTag) {
void* oldval;
#if FREELIST_NONBLOCKING
oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, (intptr_t)UNUSABLE, 0);
oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, UNUSABLE, 0);
#else
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
{
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
if ( (oldval=publicFreeList)==NULL )
(uintptr_t&)(publicFreeList) = UNUSABLE;
(intptr_t&)(publicFreeList) = UNUSABLE;
}
#endif
if ( oldval!=NULL ) {
Expand All @@ -1478,7 +1477,7 @@ void Block::shareOrphaned(intptr_t binTag, unsigned index)
// it is caller responsibility to ensure that the list of blocks
// formed by nextPrivatizable pointers is kept consistent if required.
// if only called from thread shutdown code, it does not matter.
(uintptr_t&)(nextPrivatizable) = UNUSABLE;
(intptr_t&)(nextPrivatizable) = UNUSABLE;
}

void Block::cleanBlockHeader()
Expand Down Expand Up @@ -1549,7 +1548,7 @@ bool OrphanedBlocks::cleanup(Backend* backend)
Block* next = block->next;
block->privatizePublicFreeList( /*cleanup=*/true );
if (block->empty()) {
block->makeEmpty();
block->reset();
// slab blocks in user's pools do not have valid backRefIdx
if (!backend->inUserPool())
removeBackRef(*(block->getBackRefIdx()));
Expand Down Expand Up @@ -1626,12 +1625,12 @@ bool FreeBlockPool::externalCleanup()
return nonEmpty;
}

/* We have a block give it back to the malloc block manager */
void Block::makeEmpty()
/* Prepare the block for returning to FreeBlockPool */
void Block::reset()
{
// it is caller's responsibility to ensure no data is lost before calling this
MALLOC_ASSERT( allocatedCount==0, ASSERT_TEXT );
MALLOC_ASSERT( publicFreeList==NULL, ASSERT_TEXT );
MALLOC_ASSERT( !isSolidPtr(publicFreeList), ASSERT_TEXT );
if (!isStartupAllocObject())
STAT_increment(getThreadId(), getIndex(objectSize), freeBlockBack);

Expand Down
Loading

0 comments on commit 75224c4

Please sign in to comment.