Committing TBB 2019 Update 9 source code
[platform/upstream/tbb.git] / src / test / harness.h
1 /*
2     Copyright (c) 2005-2019 Intel Corporation
3
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7
8         http://www.apache.org/licenses/LICENSE-2.0
9
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16
17 // Declarations for rock-bottom simple test harness.
18 // Just include this file to use it.
19 // Every test is presumed to have a command line of the form "test [-v] [MinThreads[:MaxThreads]]"
20 // The default for MinThreads is 1, for MaxThreads 4.
21 // The defaults can be overridden by defining macros HARNESS_DEFAULT_MIN_THREADS
22 // and HARNESS_DEFAULT_MAX_THREADS before including harness.h
23
24 #ifndef tbb_tests_harness_H
25 #define tbb_tests_harness_H
26
27 #include "tbb/tbb_config.h"
28 #include "harness_defs.h"
29
30 namespace Harness {
31     enum TestResult {
32         Done,
33         Skipped,
34         Unknown
35     };
36 }
37
38 //! Entry point to a TBB unit test application
39 /** It MUST be defined by the test application.
40
41     If HARNESS_NO_PARSE_COMMAND_LINE macro was not explicitly set before including harness.h,
42     then global variables MinThread, and MaxThread will be available and
43     initialized when it is called.
44
45     Returns Harness::Done when the tests passed successfully. When the test fail, it must
46     not return, calling exit(errcode) or abort() instead. When the test is not supported
47     for the given platform/compiler/etc, it should return Harness::Skipped.
48
49     To provide non-standard variant of main() for the test, define HARNESS_CUSTOM_MAIN
50     before including harness.h **/
51 int TestMain ();
52
53 #if __SUNPRO_CC
54     #include <stdlib.h>
55     #include <string.h>
56     #include <ucontext.h>
57 #else /* !__SUNPRO_CC */
58     #include <cstdlib>
59     #include <cstring>
60 #endif /* !__SUNPRO_CC */
61
62 #include <new>
63
64 #if __TBB_MIC_NATIVE
65     #include "harness_mic.h"
66 #else
67     #define HARNESS_EXPORT
68     #define REPORT_FATAL_ERROR REPORT
69 #endif /* !__MIC__ */
70
71 #if _WIN32||_WIN64
72     #include "tbb/machine/windows_api.h"
73     #if _WIN32_WINNT > 0x0501 && _MSC_VER && !_M_ARM
74         // Suppress "typedef ignored ... when no variable is declared" warning by vc14
75         #pragma warning (push)
76         #pragma warning (disable: 4091)
77         #include <dbghelp.h>
78         #pragma warning (pop)
79         #pragma comment (lib, "dbghelp.lib")
80     #endif
81     #if __TBB_WIN8UI_SUPPORT
82         #include <thread>
83     #endif
84     #if _MSC_VER
85         #include <crtdbg.h>
86     #endif
87     #include <process.h>
88 #else
89     #include <pthread.h>
90 #endif
91
92 #if __linux__
93     #include <sys/utsname.h> /* for uname */
94     #include <errno.h>       /* for use in LinuxKernelVersion() */
95     #include <features.h>
96 #endif
97 // at least GLIBC 2.1 or OSX 10.5
98 #if __GLIBC__>2 || ( __GLIBC__==2 && __GLIBC_MINOR__ >= 1) || __APPLE__
99     #include <execinfo.h> /*backtrace*/
100     #define BACKTRACE_FUNCTION_AVAILABLE 1
101 #endif
102
103 namespace Harness {
104     class NativeMutex {
105 #if _WIN32||_WIN64
106         CRITICAL_SECTION my_critical_section;
107       public:
108         NativeMutex() {
109             InitializeCriticalSectionEx(&my_critical_section, 4000, 0);
110         }
111         void lock() {
112             EnterCriticalSection(&my_critical_section);
113         }
114         void unlock() {
115             LeaveCriticalSection(&my_critical_section);
116         }
117         ~NativeMutex() {
118             DeleteCriticalSection(&my_critical_section);
119         }
120 #else
121         pthread_mutex_t m_mutex;
122     public:
123         NativeMutex() {
124              pthread_mutex_init(&m_mutex, NULL);
125         }
126         void lock() {
127             pthread_mutex_lock(&m_mutex);
128         }
129         void unlock() {
130             pthread_mutex_unlock(&m_mutex);
131         }
132         ~NativeMutex() {
133             pthread_mutex_destroy(&m_mutex);
134         }
135 #endif
136     };
137     namespace internal {
138         static NativeMutex print_stack_mutex;
139     }
140 }
141
142 #include "harness_runtime_loader.h"
143 #include "harness_report.h"
144
145 //! Prints current call stack
146 void print_call_stack() {
147     Harness::internal::print_stack_mutex.lock();
148     fflush(stdout); fflush(stderr);
149     #if BACKTRACE_FUNCTION_AVAILABLE
150         const int sz = 100; // max number of frames to capture
151         void *buff[sz];
152         int n = backtrace(buff, sz);
153         REPORT("Call stack info (%d):\n", n);
154         backtrace_symbols_fd(buff, n, fileno(stdout));
155     #elif __SUNPRO_CC
156         REPORT("Call stack info:\n");
157         printstack(fileno(stdout));
158     #elif _WIN32_WINNT > 0x0501 && _MSC_VER>=1500 && !__TBB_WIN8UI_SUPPORT
159         const int sz = 62; // XP limitation for number of frames
160         void *buff[sz];
161         int n = CaptureStackBackTrace(0, sz, buff, NULL);
162         REPORT("Call stack info (%d):\n", n);
163         static LONG once = 0;
164         if( !InterlockedExchange(&once, 1) )
165             SymInitialize(GetCurrentProcess(), NULL, TRUE);
166         const int len = 255; // just some reasonable string buffer size
167         union { SYMBOL_INFO sym; char pad[sizeof(SYMBOL_INFO)+len]; };
168         sym.MaxNameLen = len;
169         sym.SizeOfStruct = sizeof( SYMBOL_INFO );
170         DWORD64 offset;
171         for(int i = 1; i < n; i++) { // skip current frame
172             if(!SymFromAddr( GetCurrentProcess(), DWORD64(buff[i]), &offset, &sym )) {
173                 sym.Address = ULONG64(buff[i]); offset = 0; sym.Name[0] = 0;
174             }
175             REPORT("[%d] %016I64X+%04I64X: %s\n", i, sym.Address, offset, sym.Name); //TODO: print module name
176         }
177     #endif /*BACKTRACE_FUNCTION_AVAILABLE*/
178     Harness::internal::print_stack_mutex.unlock();
179 }
180
181 #if !HARNESS_NO_ASSERT
182     #include <exception> //for set_terminate
183     #include "harness_assert.h"
184     #if TEST_USES_TBB
185         #include <tbb/tbb_stddef.h> /*set_assertion_handler*/
186     #endif
187
188     struct InitReporter {
189         void (*default_terminate_handler)() ;
190         InitReporter(): default_terminate_handler(NULL) {
191             #if TEST_USES_TBB
192                 #if TBB_USE_ASSERT
193                     tbb::set_assertion_handler(ReportError);
194                 #endif
195                 ASSERT_WARNING(TBB_INTERFACE_VERSION <= tbb::TBB_runtime_interface_version(), "runtime version mismatch");
196             #endif
197             #if TBB_USE_EXCEPTIONS
198                 default_terminate_handler = std::set_terminate(handle_terminate);
199             #endif
200         }
201         static void handle_terminate();
202     };
203     static InitReporter InitReportError;
204
205     void InitReporter::handle_terminate(){
206         REPORT("std::terminate called.\n");
207         print_call_stack();
208         if (InitReportError.default_terminate_handler){
209             InitReportError.default_terminate_handler();
210         }
211     }
212
213     typedef void (*test_error_extra_t)(void);
214     static test_error_extra_t ErrorExtraCall;
215     //! Set additional handler to process failed assertions
216     void SetHarnessErrorProcessing( test_error_extra_t extra_call ) {
217         ErrorExtraCall = extra_call;
218     }
219
220     //! Reports errors issued by failed assertions
221     void ReportError( const char* filename, int line, const char* expression, const char * message ) {
222         print_call_stack();
223     #if __TBB_ICL_11_1_CODE_GEN_BROKEN
224         printf("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" );
225     #else
226         REPORT_FATAL_ERROR("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" );
227     #endif
228
229         if( ErrorExtraCall )
230             (*ErrorExtraCall)();
231         fflush(stdout); fflush(stderr);
232     #if HARNESS_TERMINATE_ON_ASSERT
233         TerminateProcess(GetCurrentProcess(), 1);
234     #elif HARNESS_EXIT_ON_ASSERT
235         exit(1);
236     #elif HARNESS_CONTINUE_ON_ASSERT
237         // continue testing
238     #elif _MSC_VER && _DEBUG
239         // aligned with tbb_assert_impl.h behavior
240         if(1 == _CrtDbgReport(_CRT_ASSERT, filename, line, NULL, "%s\r\n%s", expression, message?message:""))
241             _CrtDbgBreak();
242     #else
243         abort();
244     #endif /* HARNESS_EXIT_ON_ASSERT */
245     }
246     //! Reports warnings issued by failed warning assertions
247     void ReportWarning( const char* filename, int line, const char* expression, const char * message ) {
248         REPORT("Warning: %s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" );
249     }
250
251 #else /* !HARNESS_NO_ASSERT */
252
253     #define ASSERT(p,msg) (Harness::suppress_unused_warning(p), (void)0)
254     #define ASSERT_WARNING(p,msg) (Harness::suppress_unused_warning(p), (void)0)
255
256 #endif /* !HARNESS_NO_ASSERT */
257
258 namespace Harness {
259     //TODO: unify with utility::internal::array_length from examples common utilities
260     template<typename T, size_t N>
261     inline size_t array_length(const T(&)[N])
262     {
263        return N;
264     }
265
266     template<typename T, size_t N>
267     inline T* end( T(& array)[N])
268     {
269        return array+ array_length(array) ;
270     }
271
272 } //namespace Harness
273
274 #if TEST_USES_TBB
275     #include "tbb/blocked_range.h"
276
277     namespace Harness {
278         template<typename T, size_t N>
279         tbb::blocked_range<T*> make_blocked_range( T(& array)[N]){ return tbb::blocked_range<T*>(array, array + N);}
280     }
281 #endif
282
283 #if !HARNESS_NO_PARSE_COMMAND_LINE
284
285 //! Controls level of commentary printed via printf-like REMARK() macro.
286 /** If true, makes the test print commentary.  If false, test should print "done" and nothing more. */
287 static bool Verbose;
288
289 #ifndef HARNESS_DEFAULT_MIN_THREADS
290     #define HARNESS_DEFAULT_MIN_THREADS 1
291 #endif
292
293 //! Minimum number of threads
294 static int MinThread = HARNESS_DEFAULT_MIN_THREADS;
295
296 #ifndef HARNESS_DEFAULT_MAX_THREADS
297     #define HARNESS_DEFAULT_MAX_THREADS 4
298 #endif
299
300 //! Maximum number of threads
301 static int MaxThread = HARNESS_DEFAULT_MAX_THREADS;
302
303 //! Parse command line of the form "name [-v] [MinThreads[:MaxThreads]]"
304 /** Sets Verbose, MinThread, and MaxThread accordingly.
305     The nthread argument can be a single number or a range of the form m:n.
306     A single number m is interpreted as if written m:m.
307     The numbers must be non-negative.
308     Clients often treat the value 0 as "run sequentially." */
309 inline void ParseCommandLine( int argc, char* argv[] ) {
310     if( !argc ) REPORT("Command line with 0 arguments\n");
311     int i = 1;
312     if( i<argc ) {
313         if( strncmp( argv[i], "-v", 2 )==0 ) {
314             Verbose = true;
315             ++i;
316         }
317     }
318     if( i<argc ) {
319         char* endptr;
320         MinThread = strtol( argv[i], &endptr, 0 );
321         if( *endptr==':' )
322             MaxThread = strtol( endptr+1, &endptr, 0 );
323         else if( *endptr=='\0' )
324             MaxThread = MinThread;
325         if( *endptr!='\0' ) {
326             REPORT_FATAL_ERROR("garbled nthread range\n");
327             exit(1);
328         }
329         if( MinThread<0 ) {
330             REPORT_FATAL_ERROR("nthread must be nonnegative\n");
331             exit(1);
332         }
333         if( MaxThread<MinThread ) {
334             REPORT_FATAL_ERROR("nthread range is backwards\n");
335             exit(1);
336         }
337         ++i;
338     }
339 #if __TBB_STDARGS_BROKEN
340     if ( !argc )
341         argc = 1;
342     else {
343         while ( i < argc && argv[i][0] == 0 )
344             ++i;
345     }
346 #endif /* __TBB_STDARGS_BROKEN */
347     if( i!=argc ) {
348         REPORT_FATAL_ERROR("Usage: %s [-v] [nthread|minthread:maxthread]\n", argv[0] );
349         exit(1);
350     }
351 }
352 #endif /* HARNESS_NO_PARSE_COMMAND_LINE */
353
354 #if !HARNESS_CUSTOM_MAIN
355
356 #if __TBB_MPI_INTEROP
357 #undef SEEK_SET
358 #undef SEEK_CUR
359 #undef SEEK_END
360 #include "mpi.h"
361 #endif
362
363 #if __TBB_MIC_OFFLOAD && __MIC__
364 extern "C" int COIProcessProxyFlush();
365 #endif
366
367 HARNESS_EXPORT
368 #if HARNESS_NO_PARSE_COMMAND_LINE
369 int main() {
370 #if __TBB_MPI_INTEROP
371     MPI_Init(NULL,NULL);
372 #endif
373 #else
374 int main(int argc, char* argv[]) {
375     ParseCommandLine( argc, argv );
376 #if __TBB_MPI_INTEROP
377     MPI_Init(&argc,&argv);
378 #endif
379 #endif
380 #if HARNESS_SKIP_TEST
381     REPORT( "skip\n" );
382     return 0;
383 #else
384 #if __TBB_MPI_INTEROP
385     // Simple TBB/MPI interoperability harness for most of tests
386     // Worker processes send blocking messages to the master process about their rank and group size
387     // Master process receives this info and print it in verbose mode
388     int rank, size, myrank;
389     MPI_Status status;
390     MPI_Comm_size(MPI_COMM_WORLD,&size);
391     MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
392     if (myrank == 0) {
393 #if !HARNESS_NO_PARSE_COMMAND_LINE
394         REMARK("Hello mpi world. I am %d of %d\n", myrank, size);
395 #endif
396         for ( int i = 1; i < size; i++ ) {
397             MPI_Recv (&rank, 1, MPI_INT, i, 1, MPI_COMM_WORLD, &status);
398             MPI_Recv (&size, 1, MPI_INT, i, 1, MPI_COMM_WORLD, &status);
399 #if !HARNESS_NO_PARSE_COMMAND_LINE
400             REMARK("Hello mpi world. I am %d of %d\n", rank, size);
401 #endif
402         }
403     } else {
404         MPI_Send (&myrank, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
405         MPI_Send (&size, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
406     }
407 #endif
408
409     int res = Harness::Unknown;
410 #if __TBB_MIC_OFFLOAD
411     // "mic:-1" or "mandatory" specifies execution on the target. The runtime
412     // system chooses the specific target. Execution on the CPU is not allowed.
413 #if __INTEL_COMPILER < 1400
414     #pragma offload target(mic:-1) out(res)
415 #else
416     #pragma offload target(mic) out(res) mandatory
417 #endif
418 #endif
419     {
420         res = TestMain();
421 #if __TBB_MIC_OFFLOAD && __MIC__
422         // It is recommended not to use the __MIC__ macro directly in the offload block but it is Ok here
423         // since it does not lead to an unexpected difference between host and target compilation phases.
424         // We need to flush internal Intel(R) Coprocessor Offload Infrastructure (Intel(R) COI) buffers
425         // to order output from the offload part before the host part.
426         // Also it is work-around for the issue with missed output.
427         COIProcessProxyFlush();
428 #endif
429     }
430
431     ASSERT( res==Harness::Done || res==Harness::Skipped, "Wrong return code by TestMain");
432 #if __TBB_MPI_INTEROP
433     if (myrank == 0) {
434         REPORT( res==Harness::Done ? "done\n" : "skip\n" );
435     }
436     MPI_Finalize();
437 #else
438     REPORT( res==Harness::Done ? "done\n" : "skip\n" );
439 #endif
440     return 0;
441 #endif /* HARNESS_SKIP_TEST */
442 }
443
444 #endif /* !HARNESS_CUSTOM_MAIN */
445
446 #if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT
447
448 //! Base class for types that should not be assigned.
449 class NoAssign {
450 public:
451     void operator=( const NoAssign& ) = delete;
452     NoAssign( const NoAssign& ) = default;
453     NoAssign() = default;
454 };
455
456 //! Base class for types that should not be copied or assigned.
457 class NoCopy: NoAssign {
458 public:
459     NoCopy( const NoCopy& ) = delete;
460     NoCopy() = default;
461 };
462
463 #else /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
464
465 //! Base class for prohibiting compiler-generated operator=
466 class NoAssign {
467     //! Assignment not allowed
468     void operator=( const NoAssign& );
469 public:
470     NoAssign() {} // explicitly defined to prevent gratuitous warnings
471 };
472
473 //! Base class for prohibiting compiler-generated copy constructor or operator=
474 class NoCopy: NoAssign {
475     //! Copy construction not allowed
476     NoCopy( const NoCopy& );
477 public:
478     NoCopy() {}
479 };
480
481 #endif /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
482
483 #if __TBB_CPP11_RVALUE_REF_PRESENT
484 #include <utility>
485
486 //! Base class for objects which support move ctors
487 class Movable {
488 public:
489     Movable() : alive(true) {}
490     void Reset() { alive = true; }
491     Movable(Movable&& other) {
492         ASSERT(other.alive, "Moving from a dead object");
493         alive = true;
494         other.alive = false;
495     }
496     Movable& operator=(Movable&& other) {
497         ASSERT(alive, "Assignment to a dead object");
498         ASSERT(other.alive, "Assignment of a dead object");
499         other.alive = false;
500         return *this;
501     }
502     Movable& operator=(const Movable& other) {
503         ASSERT(alive, "Assignment to a dead object");
504         ASSERT(other.alive, "Assignment of a dead object");
505         return *this;
506     }
507     Movable(const Movable& other) {
508         ASSERT(other.alive, "Const reference to a dead object");
509         alive = true;
510     }
511     ~Movable() { alive = false; }
512     volatile bool alive;
513 };
514
515 class MoveOnly : Movable, NoCopy {
516 public:
517     MoveOnly() : Movable() {}
518     MoveOnly(MoveOnly&& other) : Movable( std::move(other) ) {}
519 };
520 #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
521
522 #if HARNESS_TBBMALLOC_THREAD_SHUTDOWN && __TBB_SOURCE_DIRECTLY_INCLUDED && (_WIN32||_WIN64)
523 #include "../tbbmalloc/tbbmalloc_internal_api.h"
524 #endif
525
526 //! For internal use by template function NativeParallelFor
527 template<typename Index, typename Body>
528 class NativeParallelForTask: NoCopy {
529 public:
530     NativeParallelForTask( Index index_, const Body& body_ ) :
531         index(index_),
532         body(body_)
533     {}
534
535     //! Start task
536     void start() {
537 #if _WIN32||_WIN64
538         unsigned thread_id;
539 #if __TBB_WIN8UI_SUPPORT
540         std::thread* thread_tmp=new std::thread(thread_function, this);
541         thread_handle = thread_tmp->native_handle();
542         thread_id = 0;
543 #else
544         unsigned stack_size = 0;
545 #if HARNESS_THREAD_STACK_SIZE
546         stack_size = HARNESS_THREAD_STACK_SIZE;
547 #endif
548         thread_handle = (HANDLE)_beginthreadex( NULL, stack_size, thread_function, this, 0, &thread_id );
549 #endif
550         ASSERT( thread_handle!=0, "NativeParallelFor: _beginthreadex failed" );
551 #else
552 #if __ICC==1100
553     #pragma warning (push)
554     #pragma warning (disable: 2193)
555 #endif /* __ICC==1100 */
556         // Some machines may have very large hard stack limit. When the test is
557         // launched by make, the default stack size is set to the hard limit, and
558         // calls to pthread_create fail with out-of-memory error.
559         // Therefore we set the stack size explicitly (as for TBB worker threads).
560 #if !defined(HARNESS_THREAD_STACK_SIZE)
561 #if __i386__||__i386||__arm__
562         const size_t stack_size = 1*MByte;
563 #elif __x86_64__
564         const size_t stack_size = 2*MByte;
565 #else
566         const size_t stack_size = 4*MByte;
567 #endif
568 #else
569         const size_t stack_size = HARNESS_THREAD_STACK_SIZE;
570 #endif /* HARNESS_THREAD_STACK_SIZE */
571         pthread_attr_t attr_stack;
572         int status = pthread_attr_init(&attr_stack);
573         ASSERT(0==status, "NativeParallelFor: pthread_attr_init failed");
574         status = pthread_attr_setstacksize( &attr_stack, stack_size );
575         ASSERT(0==status, "NativeParallelFor: pthread_attr_setstacksize failed");
576         status = pthread_create(&thread_id, &attr_stack, thread_function, this);
577         ASSERT(0==status, "NativeParallelFor: pthread_create failed");
578         pthread_attr_destroy(&attr_stack);
579 #if __ICC==1100
580     #pragma warning (pop)
581 #endif
582 #endif /* _WIN32||_WIN64 */
583     }
584
585     //! Wait for task to finish
586     void wait_to_finish() {
587 #if _WIN32||_WIN64
588         DWORD status = WaitForSingleObjectEx( thread_handle, INFINITE, FALSE );
589         ASSERT( status!=WAIT_FAILED, "WaitForSingleObject failed" );
590         CloseHandle( thread_handle );
591 #else
592         int status = pthread_join( thread_id, NULL );
593         ASSERT( !status, "pthread_join failed" );
594 #endif
595 #if HARNESS_NO_ASSERT
596         (void)status;
597 #endif
598     }
599
600 private:
601 #if _WIN32||_WIN64
602     HANDLE thread_handle;
603 #else
604     pthread_t thread_id;
605 #endif
606
607     //! Range over which task will invoke the body.
608     const Index index;
609
610     //! Body to invoke over the range.
611     const Body body;
612
613 #if _WIN32||_WIN64
614     static unsigned __stdcall thread_function( void* object )
615 #else
616     static void* thread_function(void* object)
617 #endif
618     {
619         NativeParallelForTask& self = *static_cast<NativeParallelForTask*>(object);
620         (self.body)(self.index);
621 #if HARNESS_TBBMALLOC_THREAD_SHUTDOWN && __TBB_SOURCE_DIRECTLY_INCLUDED && (_WIN32||_WIN64)
622         // in those cases can't release per-thread cache automatically,
623         // so do it manually
624         // TODO: investigate less-intrusive way to do it, for example via FLS keys
625         __TBB_mallocThreadShutdownNotification();
626 #endif
627         return 0;
628     }
629 };
630
631 //! Execute body(i) in parallel for i in the interval [0,n).
632 /** Each iteration is performed by a separate thread. */
633 template<typename Index, typename Body>
634 void NativeParallelFor( Index n, const Body& body ) {
635     typedef NativeParallelForTask<Index,Body> task;
636
637     if( n>0 ) {
638         // Allocate array to hold the tasks
639         task* array = static_cast<task*>(operator new( n*sizeof(task) ));
640
641         // Construct the tasks
642         for( Index i=0; i!=n; ++i )
643             new( &array[i] ) task(i,body);
644
645         // Start the tasks
646         for( Index i=0; i!=n; ++i )
647             array[i].start();
648
649         // Wait for the tasks to finish and destroy each one.
650         for( Index i=n; i; --i ) {
651             array[i-1].wait_to_finish();
652             array[i-1].~task();
653         }
654
655         // Deallocate the task array
656         operator delete(array);
657     }
658 }
659
660 //! The function to zero-initialize arrays; useful to avoid warnings
661 template <typename T>
662 void zero_fill(void* array, size_t n) {
663     memset(array, 0, sizeof(T)*n);
664 }
665
666 #if __SUNPRO_CC && defined(min)
667 #undef min
668 #undef max
669 #endif
670
671 #ifndef min
672 //! Utility template function returning lesser of the two values.
673 /** Provided here to avoid including not strict safe <algorithm>.\n
674     In case operands cause signed/unsigned or size mismatch warnings it is caller's
675     responsibility to do the appropriate cast before calling the function. **/
676 template<typename T1, typename T2>
677 T1 min ( const T1& val1, const T2& val2 ) {
678     return val1 < val2 ? val1 : val2;
679 }
680 #endif /* !min */
681
682 #ifndef max
683 //! Utility template function returning greater of the two values.
684 /** Provided here to avoid including not strict safe <algorithm>.\n
685     In case operands cause signed/unsigned or size mismatch warnings it is caller's
686     responsibility to do the appropriate cast before calling the function. **/
687 template<typename T1, typename T2>
688 T1 max ( const T1& val1, const T2& val2 ) {
689     return val1 < val2 ? val2 : val1;
690 }
691 #endif /* !max */
692
693 template<typename T>
694 static inline bool is_aligned(T arg, size_t alignment) {
695     return 0==((size_t)arg &  (alignment-1));
696 }
697
698 #if __linux__
699 inline unsigned LinuxKernelVersion()
700 {
701     unsigned digit1, digit2, digit3;
702     struct utsname utsnameBuf;
703
704     if (-1 == uname(&utsnameBuf)) {
705         REPORT_FATAL_ERROR("Can't call uname: errno %d\n", errno);
706         exit(1);
707     }
708     if (3 != sscanf(utsnameBuf.release, "%u.%u.%u", &digit1, &digit2, &digit3)) {
709         REPORT_FATAL_ERROR("Unable to parse OS release '%s'\n", utsnameBuf.release);
710         exit(1);
711     }
712     return 1000000*digit1+1000*digit2+digit3;
713 }
714 #endif
715
716 namespace Harness {
717
718 #if !HARNESS_NO_ASSERT
719 //! Base class that asserts that no operations are made with the object after its destruction.
720 class NoAfterlife {
721 protected:
722     enum state_t {
723         LIVE=0x56781234,
724         DEAD=0xDEADBEEF
725     } m_state;
726
727 public:
728     NoAfterlife() : m_state(LIVE) {}
729     NoAfterlife( const NoAfterlife& src ) : m_state(LIVE) {
730         ASSERT( src.IsLive(), "Constructing from the dead source" );
731     }
732     ~NoAfterlife() {
733         ASSERT( IsLive(), "Repeated destructor call" );
734         m_state = DEAD;
735     }
736     const NoAfterlife& operator=( const NoAfterlife& src ) {
737         ASSERT( IsLive(), NULL );
738         ASSERT( src.IsLive(), NULL );
739         return *this;
740     }
741     void AssertLive() const {
742         ASSERT( IsLive(), "Already dead" );
743     }
744     bool IsLive() const {
745         return m_state == LIVE;
746     }
747 }; // NoAfterlife
748 #endif /* !HARNESS_NO_ASSERT */
749
750 #if _WIN32 || _WIN64
751     void Sleep ( int ms ) {
752 #if !__TBB_WIN8UI_SUPPORT
753         ::Sleep(ms);
754 #else
755          std::chrono::milliseconds sleep_time( ms );
756          std::this_thread::sleep_for( sleep_time );
757 #endif
758
759     }
760
761     typedef DWORD tid_t;
762     tid_t CurrentTid () { return GetCurrentThreadId(); }
763
764 #else /* !WIN */
765
766     void Sleep ( int ms ) {
767         timespec  requested = { ms / 1000, (ms % 1000)*1000000 };
768         timespec  remaining = { 0, 0 };
769         nanosleep(&requested, &remaining);
770     }
771
772     typedef pthread_t tid_t;
773     tid_t CurrentTid () { return pthread_self(); }
774 #endif /* !WIN */
775
776     static const unsigned Primes[] = {
777         0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b,
778         0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b,
779         0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3,
780         0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b,
781         0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7,
782         0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7,
783         0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b,
784         0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f
785     };
786
787     class FastRandom {
788         unsigned x, a;
789     public:
790         unsigned short get() {
791             unsigned short r = (unsigned short)(x >> 16);
792             x = x*a + 1;
793             return r;
794         }
795         explicit FastRandom( unsigned seed ) {
796             x = seed;
797             a = Primes[seed % (sizeof(Primes) / sizeof(Primes[0]))];
798         }
799     };
800     template<typename T>
801     class FastRandomBody {
802         FastRandom r;
803     public:
804         explicit FastRandomBody( unsigned seed ) : r(seed) {}
805         // Depending on the input type T the result distribution formed from this operator()
806         // might possess different characteristics than the original one used in FastRandom instance.
807         T operator()() { return T(r.get()); }
808     };
809
810     int SetEnv( const char *envname, const char *envval ) {
811         ASSERT( envname && envval, "Harness::SetEnv() requires two valid C strings" );
812 #if __TBB_WIN8UI_SUPPORT
813         ASSERT( false, "Harness::SetEnv() should not be called in code built for win8ui" );
814         return -1;
815 #elif !(_MSC_VER || __MINGW32__ || __MINGW64__)
816         // On POSIX systems use setenv
817         return setenv(envname, envval, /*overwrite=*/1);
818 #elif __STDC_SECURE_LIB__>=200411
819         // this macro is set in VC & MinGW if secure API functions are present
820         return _putenv_s(envname, envval);
821 #else
822         // If no secure API on Windows, use _putenv
823         size_t namelen = strlen(envname), valuelen = strlen(envval);
824         char* buf = new char[namelen+valuelen+2];
825         strncpy(buf, envname, namelen);
826         buf[namelen] = '=';
827         strncpy(buf+namelen+1, envval, valuelen);
828         buf[namelen+1+valuelen] = char(0);
829         int status = _putenv(buf);
830         delete[] buf;
831         return status;
832 #endif
833     }
834
835     char* GetEnv(const char *envname) {
836         ASSERT(envname, "Harness::GetEnv() requires a valid C string");
837 #if __TBB_WIN8UI_SUPPORT
838         return NULL;
839 #else
840         return std::getenv(envname);
841 #endif
842     }
843
844     class DummyBody {
845         int m_numIters;
846     public:
847         explicit DummyBody( int iters ) : m_numIters( iters ) {}
848         void operator()( int ) const {
849             for ( volatile int i = 0; i < m_numIters; ++i ) {}
850         }
851     };
852 } // namespace Harness
853
854 #endif /* tbb_tests_harness_H */