Skip to content

Commit 75224c4

Browse files
author
tbbdev
committed
Committing Intel(R) TBB 2017 Update 8 source code
1 parent eb6336a commit 75224c4

File tree

11 files changed

+158
-52
lines changed

11 files changed

+158
-52
lines changed

CHANGES

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
The list of most significant changes made over time in
33
Intel(R) Threading Building Blocks (Intel(R) TBB).
44

5+
Intel TBB 2017 Update 8
6+
TBB_INTERFACE_VERSION == 9108
7+
8+
Changes (w.r.t. Intel TBB 2017 Update 7):
9+
10+
Bugs fixed:
11+
12+
- Fixed an assertion failure in debug tbbmalloc binaries when
13+
TBBMALLOC_CLEAN_ALL_BUFFERS is used.
14+
15+
------------------------------------------------------------------------
516
Intel TBB 2017 Update 7
617
TBB_INTERFACE_VERSION == 9107
718

README.md

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

55
Intel(R) Threading Building Blocks (Intel(R) TBB) lets you easily write parallel C++ programs that take

cmake/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Use cases of Intel TBB integration into CMake-aware projects
3636
------------------------------------------------------------
3737
There are two types of Intel TBB packages:
3838
* 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.
39-
* 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.
39+
* 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.
4040

4141
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.
4242

cmake/tbb_config_generator.cmake

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright (c) 2017 Intel Corporation
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
#
16+
#
17+
#
18+
19+
function(tbb_conf_gen_print_help)
20+
message("Usage: cmake -DTBB_ROOT=<tbb_root> -DTBB_OS=Linux|Windows|Darwin [-DSAVE_TO=<path>] -P tbb_config_generator.cmake")
21+
endfunction()
22+
23+
if (NOT DEFINED TBB_ROOT)
24+
tbb_conf_gen_print_help()
25+
message(FATAL_ERROR "Required parameter TBB_ROOT is not defined")
26+
endif()
27+
28+
if (NOT EXISTS "${TBB_ROOT}")
29+
tbb_conf_gen_print_help()
30+
message(FATAL_ERROR "TBB_ROOT=${TBB_ROOT} does not exist")
31+
endif()
32+
33+
if (NOT DEFINED TBB_OS)
34+
tbb_conf_gen_print_help()
35+
message(FATAL_ERROR "Required parameter TBB_OS is not defined")
36+
endif()
37+
38+
if (DEFINED SAVE_TO)
39+
set(tbb_conf_gen_save_to_param SAVE_TO ${SAVE_TO})
40+
endif()
41+
42+
include(${CMAKE_CURRENT_LIST_DIR}/TBBMakeConfig.cmake)
43+
tbb_make_config(TBB_ROOT ${TBB_ROOT} CONFIG_DIR tbb_config_dir SYSTEM_NAME ${TBB_OS} ${tbb_conf_gen_save_to_param})
44+
45+
message(STATUS "TBBConfig files were created in ${tbb_config_dir}")

include/tbb/tbb_stddef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#define TBB_VERSION_MINOR 0
2727

2828
// Engineering-focused interface version
29-
#define TBB_INTERFACE_VERSION 9107
29+
#define TBB_INTERFACE_VERSION 9108
3030
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
3131

3232
// The oldest major interface version still supported

python/setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#
1919
#
2020

21-
2221
# System imports
2322
from __future__ import print_function
2423
import platform

python/tbb.i

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#
1919
#
2020

21-
2221
# Based on the software developed by:
2322
# Copyright (c) 2008,2016 david decotigny (Pool of threads)
2423
# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool)

src/tbb/market.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ market& market::global_market ( bool is_public, unsigned workers_requested, size
140140
// The requested number of threads is intentionally not considered in
141141
// computation of the hard limit, in order to separate responsibilities
142142
// and avoid complicated interactions between global_control and task_scheduler_init.
143-
const unsigned workers_hard_limit = max(factor*governor::default_num_threads(), app_parallelism_limit());
143+
// The market guarantees that at least 256 threads might be created.
144+
const unsigned workers_hard_limit = max(max(factor*governor::default_num_threads(), 256u), app_parallelism_limit());
144145
const unsigned workers_soft_limit = calc_workers_soft_limit(workers_requested, workers_hard_limit);
145146
// Create the global market instance
146147
size_t size = sizeof(market);
@@ -695,9 +696,9 @@ void market::process( job& j ) {
695696
// Workers leave market because there is no arena in need. It can happen earlier than
696697
// adjust_job_count_estimate() decreases my_slack and RML can put this thread to sleep.
697698
// It might result in a busy-loop checking for my_slack<0 and calling this method instantly.
698-
// first_interval>0 and the pause refines this spinning.
699+
// first_interval>0 and the yield refines this spinning.
699700
if( i > 0 )
700-
prolonged_pause();
701+
__TBB_Yield();
701702
else
702703
#if !__TBB_SLEEP_PERMISSION
703704
break;

src/tbbmalloc/frontend.cpp

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ bool RecursiveMallocCallProtector::noRecursion() {
8181

8282
#endif // MALLOC_CHECK_RECURSION
8383

84+
/** Support for handling the special UNUSABLE pointer state **/
85+
const intptr_t UNUSABLE = 0x1;
86+
inline bool isSolidPtr( void* ptr ) {
87+
return (UNUSABLE|(intptr_t)ptr)!=UNUSABLE;
88+
}
89+
inline bool isNotForUse( void* ptr ) {
90+
return (intptr_t)ptr==UNUSABLE;
91+
}
92+
8493
/*
8594
* Block::objectSize value used to mark blocks allocated by startupAlloc
8695
*/
@@ -346,14 +355,14 @@ class LocalBlockFields : public GlobalBlockFields, Padding<blockHeaderAlignment
346355
class Block : public LocalBlockFields,
347356
Padding<2*blockHeaderAlignment - sizeof(LocalBlockFields)> {
348357
public:
349-
bool empty() const { return allocatedCount==0 && publicFreeList==NULL; }
358+
bool empty() const { return allocatedCount==0 && !isSolidPtr(publicFreeList); }
350359
inline FreeObject* allocate();
351360
inline FreeObject *allocateFromFreeList();
352361
inline bool emptyEnoughToUse();
353362
bool freeListNonNull() { return freeList; }
354363
void freePublicObject(FreeObject *objectToFree);
355364
inline void freeOwnObject(void *object);
356-
void makeEmpty();
365+
void reset();
357366
void privatizePublicFreeList( bool cleanup = false );
358367
void restoreBumpPtr();
359368
void privatizeOrphaned(TLSData *tls, unsigned index);
@@ -390,7 +399,7 @@ class Block : public LocalBlockFields,
390399
// expected after double free
391400
MALLOC_ASSERT(toFree != freeList, msg);
392401
// check against head of publicFreeList, to detect double free
393-
// involiving foreign thread
402+
// involving foreign thread
394403
MALLOC_ASSERT(toFree != publicFreeList, msg);
395404
}
396405
#else
@@ -887,16 +896,6 @@ void BootStrapBlocks::reset()
887896
static MallocMutex publicFreeListLock; // lock for changes of publicFreeList
888897
#endif
889898

890-
const uintptr_t UNUSABLE = 0x1;
891-
inline bool isSolidPtr( void* ptr )
892-
{
893-
return (UNUSABLE|(uintptr_t)ptr)!=UNUSABLE;
894-
}
895-
inline bool isNotForUse( void* ptr )
896-
{
897-
return (uintptr_t)ptr==UNUSABLE;
898-
}
899-
900899
/********* End rough utility code **************/
901900

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

10351034
void MemoryPool::returnEmptyBlock(Block *block, bool poolTheBlock)
10361035
{
1037-
block->makeEmpty();
1036+
block->reset();
10381037
if (poolTheBlock) {
10391038
extMemPool.tlsPointerKey.getThreadMallocTLS()->freeSlabBlocks.returnBlock(block);
10401039
}
@@ -1310,7 +1309,7 @@ void Block::freeOwnObject(void *object)
13101309
else
13111310
STAT_increment(getThreadId(), getIndex(objectSize), freeToActiveBlock);
13121311
#endif
1313-
if (allocatedCount==0 && publicFreeList==NULL) {
1312+
if (empty()) {
13141313
// The bump pointer is about to be restored for the block,
13151314
// no need to find objectToFree here (this is costly).
13161315

@@ -1373,33 +1372,33 @@ void Block::freePublicObject (FreeObject *objectToFree)
13731372
void Block::privatizePublicFreeList( bool cleanup )
13741373
{
13751374
FreeObject *temp, *localPublicFreeList;
1375+
const intptr_t endMarker = cleanup? UNUSABLE : 0;
13761376

13771377
// During cleanup of orphaned blocks, the calling thread is not registered as the owner
13781378
MALLOC_ASSERT( cleanup || isOwnedByCurrentThread(), ASSERT_TEXT );
13791379
#if FREELIST_NONBLOCKING
13801380
temp = publicFreeList;
13811381
do {
13821382
localPublicFreeList = temp;
1383-
temp = (FreeObject*)AtomicCompareExchange(
1384-
(intptr_t&)publicFreeList,
1385-
0, (intptr_t)localPublicFreeList);
1383+
temp = (FreeObject*)AtomicCompareExchange( (intptr_t&)publicFreeList,
1384+
endMarker, (intptr_t)localPublicFreeList);
13861385
// no backoff necessary because trying to make change, not waiting for a change
13871386
} while( temp != localPublicFreeList );
13881387
#else
13891388
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
13901389
{
13911390
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
13921391
localPublicFreeList = publicFreeList;
1393-
publicFreeList = NULL;
1392+
publicFreeList = endMarker;
13941393
}
13951394
temp = localPublicFreeList;
13961395
#endif
13971396
MALLOC_ITT_SYNC_ACQUIRED(&publicFreeList);
13981397

1399-
// there should be something in publicFreeList, unless called by cleanup of orphaned blocks
1400-
MALLOC_ASSERT( cleanup || localPublicFreeList, ASSERT_TEXT );
1398+
// publicFreeList must have been UNUSABLE (possible for orphaned blocks) or valid, but not NULL
1399+
MALLOC_ASSERT( localPublicFreeList!=NULL, ASSERT_TEXT );
14011400
MALLOC_ASSERT( localPublicFreeList==temp, ASSERT_TEXT );
1402-
if( isSolidPtr(temp) ) { // return/getPartialBlock could set it to UNUSABLE
1401+
if( isSolidPtr(temp) ) {
14031402
MALLOC_ASSERT( allocatedCount <= (slabSize-sizeof(Block))/objectSize, ASSERT_TEXT );
14041403
/* other threads did not change the counter freeing our blocks */
14051404
allocatedCount--;
@@ -1447,13 +1446,13 @@ void Block::shareOrphaned(intptr_t binTag, unsigned index)
14471446
if ((intptr_t)nextPrivatizable==binTag) {
14481447
void* oldval;
14491448
#if FREELIST_NONBLOCKING
1450-
oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, (intptr_t)UNUSABLE, 0);
1449+
oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, UNUSABLE, 0);
14511450
#else
14521451
STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList);
14531452
{
14541453
MallocMutex::scoped_lock scoped_cs(publicFreeListLock);
14551454
if ( (oldval=publicFreeList)==NULL )
1456-
(uintptr_t&)(publicFreeList) = UNUSABLE;
1455+
(intptr_t&)(publicFreeList) = UNUSABLE;
14571456
}
14581457
#endif
14591458
if ( oldval!=NULL ) {
@@ -1478,7 +1477,7 @@ void Block::shareOrphaned(intptr_t binTag, unsigned index)
14781477
// it is caller responsibility to ensure that the list of blocks
14791478
// formed by nextPrivatizable pointers is kept consistent if required.
14801479
// if only called from thread shutdown code, it does not matter.
1481-
(uintptr_t&)(nextPrivatizable) = UNUSABLE;
1480+
(intptr_t&)(nextPrivatizable) = UNUSABLE;
14821481
}
14831482

14841483
void Block::cleanBlockHeader()
@@ -1549,7 +1548,7 @@ bool OrphanedBlocks::cleanup(Backend* backend)
15491548
Block* next = block->next;
15501549
block->privatizePublicFreeList( /*cleanup=*/true );
15511550
if (block->empty()) {
1552-
block->makeEmpty();
1551+
block->reset();
15531552
// slab blocks in user's pools do not have valid backRefIdx
15541553
if (!backend->inUserPool())
15551554
removeBackRef(*(block->getBackRefIdx()));
@@ -1626,12 +1625,12 @@ bool FreeBlockPool::externalCleanup()
16261625
return nonEmpty;
16271626
}
16281627

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

0 commit comments

Comments
 (0)