kmp_lock.cpp

Go to the documentation of this file.
00001 /*
00002  * kmp_lock.cpp -- lock-related functions
00003  * $Revision: 42181 $
00004  * $Date: 2013-03-26 15:04:45 -0500 (Tue, 26 Mar 2013) $
00005  */
00006 
00007 /* <copyright>
00008     Copyright (c) 1997-2013 Intel Corporation.  All Rights Reserved.
00009 
00010     Redistribution and use in source and binary forms, with or without
00011     modification, are permitted provided that the following conditions
00012     are met:
00013 
00014       * Redistributions of source code must retain the above copyright
00015         notice, this list of conditions and the following disclaimer.
00016       * Redistributions in binary form must reproduce the above copyright
00017         notice, this list of conditions and the following disclaimer in the
00018         documentation and/or other materials provided with the distribution.
00019       * Neither the name of Intel Corporation nor the names of its
00020         contributors may be used to endorse or promote products derived
00021         from this software without specific prior written permission.
00022 
00023     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 
00035 
00036 ------------------------------------------------------------------------
00037 
00038     Portions of this software are protected under the following patents:
00039         U.S. Patent 5,812,852
00040         U.S. Patent 6,792,599
00041         U.S. Patent 7,069,556
00042         U.S. Patent 7,328,433
00043         U.S. Patent 7,500,242
00044 
00045 </copyright> */
00046 
00047 #include <stddef.h>
00048 
00049 #include "kmp.h"
00050 #include "kmp_i18n.h"
00051 #include "kmp_lock.h"
00052 #include "kmp_io.h"
00053 
00054 #if KMP_OS_LINUX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
00055 # include <unistd.h>
00056 # include <sys/syscall.h>
00057 // We should really include <futex.h>, but that causes compatibility problems on different
00058 // Linux* OS distributions that either require that you include (or break when you try to include) 
00059 // <pci/types.h>.
00060 // Since all we need is the two macros below (which are part of the kernel ABI, so can't change)
00061 // we just define the constants here and don't include <futex.h>
00062 # ifndef FUTEX_WAIT
00063 #  define FUTEX_WAIT    0
00064 # endif
00065 # ifndef FUTEX_WAKE
00066 #  define FUTEX_WAKE    1
00067 # endif
00068 #endif
00069 
00070 
00071 #ifndef KMP_DEBUG
00072 # define __kmp_static_delay( arg )     /* nothing to do */
00073 #else
00074 
00075 static void
00076 __kmp_static_delay( int arg )
00077 {
00078 /* Work around weird code-gen bug that causes assert to trip */
00079 # if KMP_ARCH_X86_64 && KMP_OS_LINUX
00080     KMP_ASSERT( arg != 0 );
00081 # else
00082     KMP_ASSERT( arg >= 0 );
00083 # endif
00084 }
00085 #endif /* KMP_DEBUG */
00086 
00087 static void
00088 __kmp_static_yield( int arg )
00089 {
00090     __kmp_yield( arg );
00091 }
00092 
00093 /* Implement spin locks for internal library use.             */
00094 /* The algorithm implemented is Lamport's bakery lock [1974]. */
00095 
00096 void
00097 __kmp_validate_locks( void )
00098 {
00099     int i;
00100     kmp_uint32  x, y;
00101 
00102     /* Check to make sure unsigned arithmetic does wraps properly */
00103     x = ~((kmp_uint32) 0) - 2;
00104     y = x - 2;
00105 
00106     for (i = 0; i < 8; ++i, ++x, ++y) {
00107         kmp_uint32 z = (x - y);
00108         KMP_ASSERT( z == 2 );
00109     }
00110 
00111     KMP_ASSERT( offsetof( kmp_base_queuing_lock, tail_id ) % 8 == 0 );
00112 }
00113 
00114 
00115 /* ------------------------------------------------------------------------ */
00116 /* test and set locks */
00117 
00118 //
00119 // For the non-nested locks, we can only assume that the first 4 bytes were
00120 // allocated, since gcc only allocates 4 bytes for omp_lock_t, and the Intel
00121 // compiler only allocates a 4 byte pointer on IA-32 architecture.  On
00122 // Windows* OS on Intel(R) 64, we can assume that all 8 bytes were allocated.
00123 //
00124 // gcc reserves >= 8 bytes for nested locks, so we can assume that the
00125 // entire 8 bytes were allocated for nested locks on all 64-bit platforms.
00126 //
00127 
00128 static kmp_int32
00129 __kmp_get_tas_lock_owner( kmp_tas_lock_t *lck )
00130 {
00131     return TCR_4( lck->lk.poll ) - 1;
00132 }
00133 
00134 static inline bool
00135 __kmp_is_tas_lock_nestable( kmp_tas_lock_t *lck )
00136 {
00137     return lck->lk.depth_locked != -1;
00138 }
00139 
00140 __forceinline static void
00141 __kmp_acquire_tas_lock_timed_template( kmp_tas_lock_t *lck, kmp_int32 gtid )
00142 {
00143     KMP_MB();
00144 
00145 #ifdef USE_LOCK_PROFILE
00146     kmp_uint32 curr = TCR_4( lck->lk.poll );
00147     if ( ( curr != 0 ) && ( curr != gtid + 1 ) )
00148         __kmp_printf( "LOCK CONTENTION: %p\n", lck );
00149     /* else __kmp_printf( "." );*/
00150 #endif /* USE_LOCK_PROFILE */
00151 
00152     if ( KMP_COMPARE_AND_STORE_ACQ32( & ( lck->lk.poll ), 0, gtid + 1 ) ) {
00153         return;
00154     }
00155 
00156     kmp_uint32 spins;
00157     KMP_INIT_YIELD( spins );
00158     if ( TCR_4( __kmp_nth ) > ( __kmp_avail_proc ? __kmp_avail_proc :
00159       __kmp_xproc ) ) {
00160         KMP_YIELD( TRUE );
00161     }
00162     else {
00163         KMP_YIELD_SPIN( spins );
00164     }
00165 
00166     while ( KMP_COMPARE_AND_STORE_ACQ32( & ( lck->lk.poll ), 0, gtid + 1 )
00167       == 0 ) {
00168         //
00169         // FIXME - use exponential backoff here
00170         //
00171         if ( TCR_4( __kmp_nth ) > ( __kmp_avail_proc ? __kmp_avail_proc :
00172           __kmp_xproc ) ) {
00173             KMP_YIELD( TRUE );
00174         }
00175         else {
00176             KMP_YIELD_SPIN( spins );
00177         }
00178     }
00179 }
00180 
00181 void
00182 __kmp_acquire_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00183 {
00184     __kmp_acquire_tas_lock_timed_template( lck, gtid );
00185 }
00186 
00187 static void
00188 __kmp_acquire_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00189 {
00190     if ( __kmp_env_consistency_check ) {
00191         char const * const func = "omp_set_lock";
00192         if ( ( sizeof ( kmp_tas_lock_t ) <= OMP_LOCK_T_SIZE )
00193           && __kmp_is_tas_lock_nestable( lck ) ) {
00194             KMP_FATAL( LockNestableUsedAsSimple, func );
00195         }
00196         if ( ( gtid >= 0 ) && ( __kmp_get_tas_lock_owner( lck ) == gtid ) ) {
00197             KMP_FATAL( LockIsAlreadyOwned, func );
00198         }
00199     }
00200     __kmp_acquire_tas_lock( lck, gtid );
00201 }
00202 
00203 int
00204 __kmp_test_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00205 {
00206     if ( KMP_COMPARE_AND_STORE_ACQ32( & ( lck->lk.poll ), 0, gtid + 1 ) ) {
00207         return TRUE;
00208     }
00209     return FALSE;
00210 }
00211 
00212 static int
00213 __kmp_test_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00214 {
00215     if ( __kmp_env_consistency_check ) {
00216         char const * const func = "omp_test_lock";
00217         if ( ( sizeof ( kmp_tas_lock_t ) <= OMP_LOCK_T_SIZE )
00218           && __kmp_is_tas_lock_nestable( lck ) ) {
00219             KMP_FATAL( LockNestableUsedAsSimple, func );
00220         }
00221     }
00222     return __kmp_test_tas_lock( lck, gtid );
00223 }
00224 
00225 void
00226 __kmp_release_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00227 {
00228     KMP_MB();       /* Flush all pending memory write invalidates.  */
00229 
00230     TCW_4( lck->lk.poll, 0 );
00231 
00232     KMP_MB();       /* Flush all pending memory write invalidates.  */
00233 
00234     KMP_YIELD( TCR_4( __kmp_nth ) > ( __kmp_avail_proc ? __kmp_avail_proc :
00235       __kmp_xproc ) );
00236 }
00237 
00238 static void
00239 __kmp_release_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00240 {
00241     if ( __kmp_env_consistency_check ) {
00242         char const * const func = "omp_unset_lock";
00243         KMP_MB();  /* in case another processor initialized lock */
00244         if ( ( sizeof ( kmp_tas_lock_t ) <= OMP_LOCK_T_SIZE )
00245           && __kmp_is_tas_lock_nestable( lck ) ) {
00246             KMP_FATAL( LockNestableUsedAsSimple, func );
00247         }
00248         if ( __kmp_get_tas_lock_owner( lck ) == -1 ) {
00249             KMP_FATAL( LockUnsettingFree, func );
00250         }
00251         if ( ( gtid >= 0 ) && ( __kmp_get_tas_lock_owner( lck ) >= 0 )
00252           && ( __kmp_get_tas_lock_owner( lck ) != gtid ) ) {
00253             KMP_FATAL( LockUnsettingSetByAnother, func );
00254         }
00255     }
00256     __kmp_release_tas_lock( lck, gtid );
00257 }
00258 
00259 void
00260 __kmp_init_tas_lock( kmp_tas_lock_t * lck )
00261 {
00262     TCW_4( lck->lk.poll, 0 );
00263 }
00264 
00265 static void
00266 __kmp_init_tas_lock_with_checks( kmp_tas_lock_t * lck )
00267 {
00268     __kmp_init_tas_lock( lck );
00269 }
00270 
00271 void
00272 __kmp_destroy_tas_lock( kmp_tas_lock_t *lck )
00273 {
00274     lck->lk.poll = 0;
00275 }
00276 
00277 static void
00278 __kmp_destroy_tas_lock_with_checks( kmp_tas_lock_t *lck )
00279 {
00280     if ( __kmp_env_consistency_check ) {
00281         char const * const func = "omp_destroy_lock";
00282         if ( ( sizeof ( kmp_tas_lock_t ) <= OMP_LOCK_T_SIZE )
00283           && __kmp_is_tas_lock_nestable( lck ) ) {
00284             KMP_FATAL( LockNestableUsedAsSimple, func );
00285         }
00286         if ( __kmp_get_tas_lock_owner( lck ) != -1 ) {
00287             KMP_FATAL( LockStillOwned, func );
00288         }
00289     }
00290     __kmp_destroy_tas_lock( lck );
00291 }
00292 
00293 
00294 //
00295 // nested test and set locks
00296 //
00297 
00298 void
00299 __kmp_acquire_nested_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00300 {
00301     KMP_DEBUG_ASSERT( gtid >= 0 );
00302 
00303     if ( __kmp_get_tas_lock_owner( lck ) == gtid ) {
00304         lck->lk.depth_locked += 1;
00305     }
00306     else {
00307         __kmp_acquire_tas_lock_timed_template( lck, gtid );
00308         lck->lk.depth_locked = 1;
00309     }
00310 }
00311 
00312 static void
00313 __kmp_acquire_nested_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00314 {
00315     if ( __kmp_env_consistency_check ) {
00316         char const * const func = "omp_set_nest_lock";
00317         if ( ! __kmp_is_tas_lock_nestable( lck ) ) {
00318             KMP_FATAL( LockSimpleUsedAsNestable, func );
00319         }
00320     }
00321     __kmp_acquire_nested_tas_lock( lck, gtid );
00322 }
00323 
00324 int
00325 __kmp_test_nested_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00326 {
00327     int retval;
00328 
00329     KMP_DEBUG_ASSERT( gtid >= 0 );
00330 
00331     if ( __kmp_get_tas_lock_owner( lck ) == gtid ) {
00332         retval = ++lck->lk.depth_locked;
00333     }
00334     else if ( !__kmp_test_tas_lock( lck, gtid ) ) {
00335         retval = 0;
00336     }
00337     else {
00338         KMP_MB();
00339         retval = lck->lk.depth_locked = 1;
00340     }
00341     return retval;
00342 }
00343 
00344 static int
00345 __kmp_test_nested_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00346 {
00347     if ( __kmp_env_consistency_check ) {
00348         char const * const func = "omp_test_nest_lock";
00349         if ( ! __kmp_is_tas_lock_nestable( lck ) ) {
00350             KMP_FATAL( LockSimpleUsedAsNestable, func );
00351         }
00352     }
00353     return __kmp_test_nested_tas_lock( lck, gtid );
00354 }
00355 
00356 int
00357 __kmp_release_nested_tas_lock( kmp_tas_lock_t *lck, kmp_int32 gtid )
00358 {
00359     KMP_DEBUG_ASSERT( gtid >= 0 );
00360 
00361     KMP_MB();
00362     if ( --(lck->lk.depth_locked) == 0 ) {
00363         __kmp_release_tas_lock( lck, gtid );
00364     return KMP_NESTED_LOCK_RELEASED;
00365     }
00366     return KMP_NESTED_LOCK_HELD;
00367 }
00368 
00369 static int
00370 __kmp_release_nested_tas_lock_with_checks( kmp_tas_lock_t *lck, kmp_int32 gtid )
00371 {
00372     if ( __kmp_env_consistency_check ) {
00373         char const * const func = "omp_unset_nest_lock";
00374         KMP_MB();  /* in case another processor initialized lock */
00375         if ( ! __kmp_is_tas_lock_nestable( lck ) ) {
00376             KMP_FATAL( LockSimpleUsedAsNestable, func );
00377         }
00378         if ( __kmp_get_tas_lock_owner( lck ) == -1 ) {
00379             KMP_FATAL( LockUnsettingFree, func );
00380         }
00381         if ( __kmp_get_tas_lock_owner( lck ) != gtid ) {
00382             KMP_FATAL( LockUnsettingSetByAnother, func );
00383         }
00384     }
00385     return __kmp_release_nested_tas_lock( lck, gtid );
00386 }
00387 
00388 void
00389 __kmp_init_nested_tas_lock( kmp_tas_lock_t * lck )
00390 {
00391     __kmp_init_tas_lock( lck );
00392     lck->lk.depth_locked = 0; // >= 0 for nestable locks, -1 for simple locks
00393 }
00394 
00395 static void
00396 __kmp_init_nested_tas_lock_with_checks( kmp_tas_lock_t * lck )
00397 {
00398     __kmp_init_nested_tas_lock( lck );
00399 }
00400 
00401 void
00402 __kmp_destroy_nested_tas_lock( kmp_tas_lock_t *lck )
00403 {
00404     __kmp_destroy_tas_lock( lck );
00405     lck->lk.depth_locked = 0;
00406 }
00407 
00408 static void
00409 __kmp_destroy_nested_tas_lock_with_checks( kmp_tas_lock_t *lck )
00410 {
00411     if ( __kmp_env_consistency_check ) {
00412         char const * const func = "omp_destroy_nest_lock";
00413         if ( ! __kmp_is_tas_lock_nestable( lck ) ) {
00414             KMP_FATAL( LockSimpleUsedAsNestable, func );
00415         }
00416         if ( __kmp_get_tas_lock_owner( lck ) != -1 ) {
00417             KMP_FATAL( LockStillOwned, func );
00418         }
00419     }
00420     __kmp_destroy_nested_tas_lock( lck );
00421 }
00422 
00423 
00424 #if KMP_OS_LINUX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
00425 
00426 /* ------------------------------------------------------------------------ */
00427 /* futex locks */
00428 
00429 // futex locks are really just test and set locks, with a different method
00430 // of handling contention.  They take the same amount of space as test and
00431 // set locks, and are allocated the same way (i.e. use the area allocated by
00432 // the compiler for non-nested locks / allocate nested locks on the heap).
00433 
00434 static kmp_int32
00435 __kmp_get_futex_lock_owner( kmp_futex_lock_t *lck )
00436 {
00437     return ( TCR_4( lck->lk.poll ) >> 1 ) - 1;
00438 }
00439 
00440 static inline bool
00441 __kmp_is_futex_lock_nestable( kmp_futex_lock_t *lck )
00442 {
00443     return lck->lk.depth_locked != -1;
00444 }
00445 
00446 __forceinline static void
00447 __kmp_acquire_futex_lock_timed_template( kmp_futex_lock_t *lck, kmp_int32 gtid )
00448 {
00449     kmp_int32 gtid_code = ( gtid + 1 ) << 1;
00450 
00451     KMP_MB();
00452 
00453 #ifdef USE_LOCK_PROFILE
00454     kmp_uint32 curr = TCR_4( lck->lk.poll );
00455     if ( ( curr != 0 ) && ( curr != gtid_code ) )
00456         __kmp_printf( "LOCK CONTENTION: %p\n", lck );
00457     /* else __kmp_printf( "." );*/
00458 #endif /* USE_LOCK_PROFILE */
00459 
00460     KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p(0x%x), T#%d entering\n",
00461       lck, lck->lk.poll, gtid ) );
00462 
00463     kmp_int32 poll_val;
00464     while ( ( poll_val = __kmp_compare_and_store_ret32( & ( lck->lk.poll ), 0,
00465       gtid_code ) ) != 0 ) {
00466         kmp_int32 cond = poll_val & 1;
00467         KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p, T#%d poll_val = 0x%x cond = 0x%x\n",
00468            lck, gtid, poll_val, cond ) );
00469 
00470         //
00471         // NOTE: if you try to use the following condition for this branch
00472         //
00473         // if ( poll_val & 1 == 0 )
00474         //
00475         // Then the 12.0 compiler has a bug where the following block will
00476         // always be skipped, regardless of the value of the LSB of poll_val.
00477         //
00478         if ( ! cond ) {
00479             //
00480             // Try to set the lsb in the poll to indicate to the owner
00481             // thread that they need to wake this thread up.
00482             //
00483             if ( ! __kmp_compare_and_store32( & ( lck->lk.poll ),
00484               poll_val, poll_val | 1 ) ) {
00485                 KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p(0x%x), T#%d can't set bit 0\n",
00486                   lck, lck->lk.poll, gtid ) );
00487                 continue;
00488             }
00489             poll_val |= 1;
00490 
00491             KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p(0x%x), T#%d bit 0 set\n",
00492               lck, lck->lk.poll, gtid ) );
00493         }
00494 
00495         KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p, T#%d before futex_wait(0x%x)\n",
00496            lck, gtid, poll_val ) );
00497 
00498         kmp_int32 rc;
00499         if ( ( rc = syscall( __NR_futex, & ( lck->lk.poll ), FUTEX_WAIT,
00500           poll_val, NULL, NULL, 0 ) ) != 0 ) {
00501             KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p, T#%d futex_wait(0x%x) failed (rc=%d errno=%d)\n",
00502                lck, gtid, poll_val, rc, errno ) );
00503             continue;
00504         }
00505 
00506         KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p, T#%d after futex_wait(0x%x)\n",
00507            lck, gtid, poll_val ) );
00508         //
00509         // This thread has now done a succesful futex wait call and was
00510         // entered on the OS futex queue.  We must now perform a futex
00511         // wake call when releasing the lock, as we have no idea how many
00512         // other threads are in the queue.
00513         //
00514         gtid_code |= 1;
00515     }
00516 
00517     KA_TRACE( 1000, ("__kmp_acquire_futex_lock: lck:%p(0x%x), T#%d exiting\n",
00518       lck, lck->lk.poll, gtid ) );
00519 }
00520 
00521 void
00522 __kmp_acquire_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00523 {
00524     __kmp_acquire_futex_lock_timed_template( lck, gtid );
00525 }
00526 
00527 static void
00528 __kmp_acquire_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00529 {
00530     if ( __kmp_env_consistency_check ) {
00531         char const * const func = "omp_set_lock";
00532         if ( ( sizeof ( kmp_futex_lock_t ) <= OMP_LOCK_T_SIZE )
00533           && __kmp_is_futex_lock_nestable( lck ) ) {
00534             KMP_FATAL( LockNestableUsedAsSimple, func );
00535         }
00536         if ( ( gtid >= 0 ) && ( __kmp_get_futex_lock_owner( lck ) == gtid ) ) {
00537             KMP_FATAL( LockIsAlreadyOwned, func );
00538         }
00539     }
00540     __kmp_acquire_futex_lock( lck, gtid );
00541 }
00542 
00543 int
00544 __kmp_test_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00545 {
00546     if ( KMP_COMPARE_AND_STORE_ACQ32( & ( lck->lk.poll ), 0, ( gtid + 1 ) << 1 ) ) {
00547         return TRUE;
00548     }
00549     return FALSE;
00550 }
00551 
00552 static int
00553 __kmp_test_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00554 {
00555     if ( __kmp_env_consistency_check ) {
00556         char const * const func = "omp_test_lock";
00557         if ( ( sizeof ( kmp_futex_lock_t ) <= OMP_LOCK_T_SIZE )
00558           && __kmp_is_futex_lock_nestable( lck ) ) {
00559             KMP_FATAL( LockNestableUsedAsSimple, func );
00560         }
00561     }
00562     return __kmp_test_futex_lock( lck, gtid );
00563 }
00564 
00565 void
00566 __kmp_release_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00567 {
00568     KMP_MB();       /* Flush all pending memory write invalidates.  */
00569 
00570     KA_TRACE( 1000, ("__kmp_release_futex_lock: lck:%p(0x%x), T#%d entering\n",
00571       lck, lck->lk.poll, gtid ) );
00572 
00573     kmp_int32 poll_val = __kmp_xchg_fixed32( & ( lck->lk.poll ), 0 );
00574 
00575     KA_TRACE( 1000, ("__kmp_release_futex_lock: lck:%p, T#%d released poll_val = 0x%x\n",
00576        lck, gtid, poll_val ) );
00577 
00578     if ( poll_val & 1 ) {
00579         KA_TRACE( 1000, ("__kmp_release_futex_lock: lck:%p, T#%d futex_wake 1 thread\n",
00580            lck, gtid ) );
00581         syscall( __NR_futex, & ( lck->lk.poll ), FUTEX_WAKE, 1, NULL, NULL, 0 );
00582     }
00583 
00584     KMP_MB();       /* Flush all pending memory write invalidates.  */
00585 
00586     KA_TRACE( 1000, ("__kmp_release_futex_lock: lck:%p(0x%x), T#%d exiting\n",
00587       lck, lck->lk.poll, gtid ) );
00588 
00589     KMP_YIELD( TCR_4( __kmp_nth ) > ( __kmp_avail_proc ? __kmp_avail_proc :
00590       __kmp_xproc ) );
00591 }
00592 
00593 static void
00594 __kmp_release_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00595 {
00596     if ( __kmp_env_consistency_check ) {
00597         char const * const func = "omp_unset_lock";
00598         KMP_MB();  /* in case another processor initialized lock */
00599         if ( ( sizeof ( kmp_futex_lock_t ) <= OMP_LOCK_T_SIZE )
00600           && __kmp_is_futex_lock_nestable( lck ) ) {
00601             KMP_FATAL( LockNestableUsedAsSimple, func );
00602         }
00603         if ( __kmp_get_futex_lock_owner( lck ) == -1 ) {
00604             KMP_FATAL( LockUnsettingFree, func );
00605         }
00606         if ( ( gtid >= 0 ) && ( __kmp_get_futex_lock_owner( lck ) >= 0 )
00607           && ( __kmp_get_futex_lock_owner( lck ) != gtid ) ) {
00608             KMP_FATAL( LockUnsettingSetByAnother, func );
00609         }
00610     }
00611     __kmp_release_futex_lock( lck, gtid );
00612 }
00613 
00614 void
00615 __kmp_init_futex_lock( kmp_futex_lock_t * lck )
00616 {
00617     TCW_4( lck->lk.poll, 0 );
00618 }
00619 
00620 static void
00621 __kmp_init_futex_lock_with_checks( kmp_futex_lock_t * lck )
00622 {
00623     __kmp_init_futex_lock( lck );
00624 }
00625 
00626 void
00627 __kmp_destroy_futex_lock( kmp_futex_lock_t *lck )
00628 {
00629     lck->lk.poll = 0;
00630 }
00631 
00632 static void
00633 __kmp_destroy_futex_lock_with_checks( kmp_futex_lock_t *lck )
00634 {
00635     if ( __kmp_env_consistency_check ) {
00636         char const * const func = "omp_destroy_lock";
00637         if ( ( sizeof ( kmp_futex_lock_t ) <= OMP_LOCK_T_SIZE )
00638           && __kmp_is_futex_lock_nestable( lck ) ) {
00639             KMP_FATAL( LockNestableUsedAsSimple, func );
00640         }
00641         if ( __kmp_get_futex_lock_owner( lck ) != -1 ) {
00642             KMP_FATAL( LockStillOwned, func );
00643         }
00644     }
00645     __kmp_destroy_futex_lock( lck );
00646 }
00647 
00648 
00649 //
00650 // nested futex locks
00651 //
00652 
00653 void
00654 __kmp_acquire_nested_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00655 {
00656     KMP_DEBUG_ASSERT( gtid >= 0 );
00657 
00658     if ( __kmp_get_futex_lock_owner( lck ) == gtid ) {
00659         lck->lk.depth_locked += 1;
00660     }
00661     else {
00662         __kmp_acquire_futex_lock_timed_template( lck, gtid );
00663         lck->lk.depth_locked = 1;
00664     }
00665 }
00666 
00667 static void
00668 __kmp_acquire_nested_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00669 {
00670     if ( __kmp_env_consistency_check ) {
00671         char const * const func = "omp_set_nest_lock";
00672         if ( ! __kmp_is_futex_lock_nestable( lck ) ) {
00673             KMP_FATAL( LockSimpleUsedAsNestable, func );
00674         }
00675     }
00676     __kmp_acquire_nested_futex_lock( lck, gtid );
00677 }
00678 
00679 int
00680 __kmp_test_nested_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00681 {
00682     int retval;
00683 
00684     KMP_DEBUG_ASSERT( gtid >= 0 );
00685 
00686     if ( __kmp_get_futex_lock_owner( lck ) == gtid ) {
00687         retval = ++lck->lk.depth_locked;
00688     }
00689     else if ( !__kmp_test_futex_lock( lck, gtid ) ) {
00690         retval = 0;
00691     }
00692     else {
00693         KMP_MB();
00694         retval = lck->lk.depth_locked = 1;
00695     }
00696     return retval;
00697 }
00698 
00699 static int
00700 __kmp_test_nested_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00701 {
00702     if ( __kmp_env_consistency_check ) {
00703         char const * const func = "omp_test_nest_lock";
00704         if ( ! __kmp_is_futex_lock_nestable( lck ) ) {
00705             KMP_FATAL( LockSimpleUsedAsNestable, func );
00706         }
00707     }
00708     return __kmp_test_nested_futex_lock( lck, gtid );
00709 }
00710 
00711 int
00712 __kmp_release_nested_futex_lock( kmp_futex_lock_t *lck, kmp_int32 gtid )
00713 {
00714     KMP_DEBUG_ASSERT( gtid >= 0 );
00715 
00716     KMP_MB();
00717     if ( --(lck->lk.depth_locked) == 0 ) {
00718         __kmp_release_futex_lock( lck, gtid );
00719     return KMP_NESTED_LOCK_RELEASED;
00720     }
00721     return KMP_NESTED_LOCK_HELD;
00722 }
00723 
00724 static int
00725 __kmp_release_nested_futex_lock_with_checks( kmp_futex_lock_t *lck, kmp_int32 gtid )
00726 {
00727     if ( __kmp_env_consistency_check ) {
00728         char const * const func = "omp_unset_nest_lock";
00729         KMP_MB();  /* in case another processor initialized lock */
00730         if ( ! __kmp_is_futex_lock_nestable( lck ) ) {
00731             KMP_FATAL( LockSimpleUsedAsNestable, func );
00732         }
00733         if ( __kmp_get_futex_lock_owner( lck ) == -1 ) {
00734             KMP_FATAL( LockUnsettingFree, func );
00735         }
00736         if ( __kmp_get_futex_lock_owner( lck ) != gtid ) {
00737             KMP_FATAL( LockUnsettingSetByAnother, func );
00738         }
00739     }
00740     return __kmp_release_nested_futex_lock( lck, gtid );
00741 }
00742 
00743 void
00744 __kmp_init_nested_futex_lock( kmp_futex_lock_t * lck )
00745 {
00746     __kmp_init_futex_lock( lck );
00747     lck->lk.depth_locked = 0; // >= 0 for nestable locks, -1 for simple locks
00748 }
00749 
00750 static void
00751 __kmp_init_nested_futex_lock_with_checks( kmp_futex_lock_t * lck )
00752 {
00753     __kmp_init_nested_futex_lock( lck );
00754 }
00755 
00756 void
00757 __kmp_destroy_nested_futex_lock( kmp_futex_lock_t *lck )
00758 {
00759     __kmp_destroy_futex_lock( lck );
00760     lck->lk.depth_locked = 0;
00761 }
00762 
00763 static void
00764 __kmp_destroy_nested_futex_lock_with_checks( kmp_futex_lock_t *lck )
00765 {
00766     if ( __kmp_env_consistency_check ) {
00767         char const * const func = "omp_destroy_nest_lock";
00768         if ( ! __kmp_is_futex_lock_nestable( lck ) ) {
00769             KMP_FATAL( LockSimpleUsedAsNestable, func );
00770         }
00771         if ( __kmp_get_futex_lock_owner( lck ) != -1 ) {
00772             KMP_FATAL( LockStillOwned, func );
00773         }
00774     }
00775     __kmp_destroy_nested_futex_lock( lck );
00776 }
00777 
00778 #endif // KMP_OS_LINUX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
00779 
00780 
00781 /* ------------------------------------------------------------------------ */
00782 /* ticket (bakery) locks */
00783 
00784 static kmp_int32
00785 __kmp_get_ticket_lock_owner( kmp_ticket_lock_t *lck )
00786 {
00787     return TCR_4( lck->lk.owner_id ) - 1;
00788 }
00789 
00790 static inline bool
00791 __kmp_is_ticket_lock_nestable( kmp_ticket_lock_t *lck )
00792 {
00793     return lck->lk.depth_locked != -1;
00794 }
00795 
00796 static kmp_uint32
00797 __kmp_bakery_check(kmp_uint value, kmp_uint checker)
00798 {
00799     register kmp_uint32 pause;
00800 
00801     if (value == checker) {
00802         return TRUE;
00803     }
00804     for (pause = checker - value; pause != 0; --pause) {
00805         __kmp_static_delay(TRUE);
00806     }
00807     return FALSE;
00808 }
00809 
00810 __forceinline static void
00811 __kmp_acquire_ticket_lock_timed_template( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00812 {
00813     kmp_uint32 my_ticket;
00814     KMP_MB();
00815 
00816     my_ticket = KMP_TEST_THEN_INC32( (kmp_int32 *) &lck->lk.next_ticket );
00817 
00818 #ifdef USE_LOCK_PROFILE
00819     if ( TCR_4( lck->lk.now_serving ) != my_ticket )
00820         __kmp_printf( "LOCK CONTENTION: %p\n", lck );
00821     /* else __kmp_printf( "." );*/
00822 #endif /* USE_LOCK_PROFILE */
00823 
00824     if ( TCR_4( lck->lk.now_serving ) == my_ticket ) {
00825         return;
00826     }
00827     KMP_WAIT_YIELD( &lck->lk.now_serving, my_ticket, __kmp_bakery_check, lck );
00828 }
00829 
00830 void
00831 __kmp_acquire_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00832 {
00833     __kmp_acquire_ticket_lock_timed_template( lck, gtid );
00834 }
00835 
00836 static void
00837 __kmp_acquire_ticket_lock_with_checks( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00838 {
00839     if ( __kmp_env_consistency_check ) {
00840         char const * const func = "omp_set_lock";
00841         if ( lck->lk.initialized != lck ) {
00842             KMP_FATAL( LockIsUninitialized, func );
00843         }
00844         if ( __kmp_is_ticket_lock_nestable( lck ) ) {
00845             KMP_FATAL( LockNestableUsedAsSimple, func );
00846         }
00847         if ( ( gtid >= 0 ) && ( __kmp_get_ticket_lock_owner( lck ) == gtid ) ) {
00848             KMP_FATAL( LockIsAlreadyOwned, func );
00849         }
00850     }
00851 
00852     __kmp_acquire_ticket_lock( lck, gtid );
00853 
00854     if ( __kmp_env_consistency_check ) {
00855         lck->lk.owner_id = gtid + 1;
00856     }
00857 }
00858 
00859 int
00860 __kmp_test_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00861 {
00862     kmp_uint32 my_ticket = TCR_4( lck->lk.next_ticket );
00863     if ( TCR_4( lck->lk.now_serving ) == my_ticket ) {
00864         kmp_uint32 next_ticket = my_ticket + 1;
00865         if ( KMP_COMPARE_AND_STORE_ACQ32( (kmp_int32 *) &lck->lk.next_ticket,
00866           my_ticket, next_ticket ) ) {
00867             return TRUE;
00868         }
00869     }
00870     return FALSE;
00871 }
00872 
00873 static int
00874 __kmp_test_ticket_lock_with_checks( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00875 {
00876     if ( __kmp_env_consistency_check ) {
00877         char const * const func = "omp_test_lock";
00878         if ( lck->lk.initialized != lck ) {
00879             KMP_FATAL( LockIsUninitialized, func );
00880         }
00881         if ( __kmp_is_ticket_lock_nestable( lck ) ) {
00882             KMP_FATAL( LockNestableUsedAsSimple, func );
00883         }
00884     }
00885 
00886     int retval = __kmp_test_ticket_lock( lck, gtid );
00887 
00888     if ( __kmp_env_consistency_check && retval ) {
00889         lck->lk.owner_id = gtid + 1;
00890     }
00891     return retval;
00892 }
00893 
00894 void
00895 __kmp_release_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00896 {
00897     kmp_uint32  distance;
00898 
00899     KMP_MB();       /* Flush all pending memory write invalidates.  */
00900 
00901     distance = ( TCR_4( lck->lk.next_ticket ) - TCR_4( lck->lk.now_serving ) );
00902 
00903     lck->lk.now_serving += 1;
00904 
00905     KMP_MB();       /* Flush all pending memory write invalidates.  */
00906 
00907     KMP_YIELD( distance
00908       > (kmp_uint32) (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc) );
00909 }
00910 
00911 static void
00912 __kmp_release_ticket_lock_with_checks( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00913 {
00914     if ( __kmp_env_consistency_check ) {
00915         char const * const func = "omp_unset_lock";
00916         KMP_MB();  /* in case another processor initialized lock */
00917         if ( lck->lk.initialized != lck ) {
00918             KMP_FATAL( LockIsUninitialized, func );
00919         }
00920         if ( __kmp_is_ticket_lock_nestable( lck ) ) {
00921             KMP_FATAL( LockNestableUsedAsSimple, func );
00922         }
00923         if ( __kmp_get_ticket_lock_owner( lck ) == -1 ) {
00924             KMP_FATAL( LockUnsettingFree, func );
00925         }
00926         if ( ( gtid >= 0 ) && ( __kmp_get_ticket_lock_owner( lck ) >= 0 )
00927           && ( __kmp_get_ticket_lock_owner( lck ) != gtid ) ) {
00928             KMP_FATAL( LockUnsettingSetByAnother, func );
00929         }
00930         lck->lk.owner_id = 0;
00931     }
00932     __kmp_release_ticket_lock( lck, gtid );
00933 }
00934 
00935 void
00936 __kmp_init_ticket_lock( kmp_ticket_lock_t * lck )
00937 {
00938     lck->lk.location = NULL;
00939     TCW_4( lck->lk.next_ticket, 0 );
00940     TCW_4( lck->lk.now_serving, 0 );
00941     lck->lk.owner_id = 0;      // no thread owns the lock.
00942     lck->lk.depth_locked = -1; // -1 => not a nested lock.
00943     lck->lk.initialized = (kmp_ticket_lock *)lck;
00944 }
00945 
00946 static void
00947 __kmp_init_ticket_lock_with_checks( kmp_ticket_lock_t * lck )
00948 {
00949     __kmp_init_ticket_lock( lck );
00950 }
00951 
00952 void
00953 __kmp_destroy_ticket_lock( kmp_ticket_lock_t *lck )
00954 {
00955     lck->lk.initialized = NULL;
00956     lck->lk.location    = NULL;
00957     lck->lk.next_ticket = 0;
00958     lck->lk.now_serving = 0;
00959     lck->lk.owner_id = 0;
00960     lck->lk.depth_locked = -1;
00961 }
00962 
00963 static void
00964 __kmp_destroy_ticket_lock_with_checks( kmp_ticket_lock_t *lck )
00965 {
00966     if ( __kmp_env_consistency_check ) {
00967         char const * const func = "omp_destroy_lock";
00968         if ( lck->lk.initialized != lck ) {
00969             KMP_FATAL( LockIsUninitialized, func );
00970         }
00971         if ( __kmp_is_ticket_lock_nestable( lck ) ) {
00972             KMP_FATAL( LockNestableUsedAsSimple, func );
00973         }
00974         if ( __kmp_get_ticket_lock_owner( lck ) != -1 ) {
00975             KMP_FATAL( LockStillOwned, func );
00976         }
00977     }
00978     __kmp_destroy_ticket_lock( lck );
00979 }
00980 
00981 
00982 //
00983 // nested ticket locks
00984 //
00985 
00986 void
00987 __kmp_acquire_nested_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
00988 {
00989     KMP_DEBUG_ASSERT( gtid >= 0 );
00990 
00991     if ( __kmp_get_ticket_lock_owner( lck ) == gtid ) {
00992         lck->lk.depth_locked += 1;
00993     }
00994     else {
00995         __kmp_acquire_ticket_lock_timed_template( lck, gtid );
00996         KMP_MB();
00997         lck->lk.depth_locked = 1;
00998         KMP_MB();
00999         lck->lk.owner_id = gtid + 1;
01000     }
01001 }
01002 
01003 static void
01004 __kmp_acquire_nested_ticket_lock_with_checks( kmp_ticket_lock_t *lck, kmp_int32 gtid )
01005 {
01006     if ( __kmp_env_consistency_check ) {
01007         char const * const func = "omp_set_nest_lock";
01008         if ( lck->lk.initialized != lck ) {
01009             KMP_FATAL( LockIsUninitialized, func );
01010         }
01011         if ( ! __kmp_is_ticket_lock_nestable( lck ) ) {
01012             KMP_FATAL( LockSimpleUsedAsNestable, func );
01013         }
01014     }
01015     __kmp_acquire_nested_ticket_lock( lck, gtid );
01016 }
01017 
01018 int
01019 __kmp_test_nested_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
01020 {
01021     int retval;
01022 
01023     KMP_DEBUG_ASSERT( gtid >= 0 );
01024 
01025     if ( __kmp_get_ticket_lock_owner( lck ) == gtid ) {
01026         retval = ++lck->lk.depth_locked;
01027     }
01028     else if ( !__kmp_test_ticket_lock( lck, gtid ) ) {
01029         retval = 0;
01030     }
01031     else {
01032         KMP_MB();
01033         retval = lck->lk.depth_locked = 1;
01034         KMP_MB();
01035         lck->lk.owner_id = gtid + 1;
01036     }
01037     return retval;
01038 }
01039 
01040 static int
01041 __kmp_test_nested_ticket_lock_with_checks( kmp_ticket_lock_t *lck,
01042   kmp_int32 gtid )
01043 {
01044     if ( __kmp_env_consistency_check ) {
01045         char const * const func = "omp_test_nest_lock";
01046         if ( lck->lk.initialized != lck ) {
01047             KMP_FATAL( LockIsUninitialized, func );
01048         }
01049         if ( ! __kmp_is_ticket_lock_nestable( lck ) ) {
01050             KMP_FATAL( LockSimpleUsedAsNestable, func );
01051         }
01052     }
01053     return __kmp_test_nested_ticket_lock( lck, gtid );
01054 }
01055 
01056 int
01057 __kmp_release_nested_ticket_lock( kmp_ticket_lock_t *lck, kmp_int32 gtid )
01058 {
01059     KMP_DEBUG_ASSERT( gtid >= 0 );
01060 
01061     KMP_MB();
01062     if ( --(lck->lk.depth_locked) == 0 ) {
01063         KMP_MB();
01064         lck->lk.owner_id = 0;
01065         __kmp_release_ticket_lock( lck, gtid );
01066     return KMP_NESTED_LOCK_RELEASED;
01067     }
01068     return KMP_NESTED_LOCK_HELD;
01069 }
01070 
01071 static int
01072 __kmp_release_nested_ticket_lock_with_checks( kmp_ticket_lock_t *lck, kmp_int32 gtid )
01073 {
01074     if ( __kmp_env_consistency_check ) {
01075         char const * const func = "omp_unset_nest_lock";
01076         KMP_MB();  /* in case another processor initialized lock */
01077         if ( lck->lk.initialized != lck ) {
01078             KMP_FATAL( LockIsUninitialized, func );
01079         }
01080         if ( ! __kmp_is_ticket_lock_nestable( lck ) ) {
01081             KMP_FATAL( LockSimpleUsedAsNestable, func );
01082         }
01083         if ( __kmp_get_ticket_lock_owner( lck ) == -1 ) {
01084             KMP_FATAL( LockUnsettingFree, func );
01085         }
01086         if ( __kmp_get_ticket_lock_owner( lck ) != gtid ) {
01087             KMP_FATAL( LockUnsettingSetByAnother, func );
01088         }
01089     }
01090     return __kmp_release_nested_ticket_lock( lck, gtid );
01091 }
01092 
01093 void
01094 __kmp_init_nested_ticket_lock( kmp_ticket_lock_t * lck )
01095 {
01096     __kmp_init_ticket_lock( lck );
01097     lck->lk.depth_locked = 0; // >= 0 for nestable locks, -1 for simple locks
01098 }
01099 
01100 static void
01101 __kmp_init_nested_ticket_lock_with_checks( kmp_ticket_lock_t * lck )
01102 {
01103     __kmp_init_nested_ticket_lock( lck );
01104 }
01105 
01106 void
01107 __kmp_destroy_nested_ticket_lock( kmp_ticket_lock_t *lck )
01108 {
01109     __kmp_destroy_ticket_lock( lck );
01110     lck->lk.depth_locked = 0;
01111 }
01112 
01113 static void
01114 __kmp_destroy_nested_ticket_lock_with_checks( kmp_ticket_lock_t *lck )
01115 {
01116     if ( __kmp_env_consistency_check ) {
01117         char const * const func = "omp_destroy_nest_lock";
01118         if ( lck->lk.initialized != lck ) {
01119             KMP_FATAL( LockIsUninitialized, func );
01120         }
01121         if ( ! __kmp_is_ticket_lock_nestable( lck ) ) {
01122             KMP_FATAL( LockSimpleUsedAsNestable, func );
01123         }
01124         if ( __kmp_get_ticket_lock_owner( lck ) != -1 ) {
01125             KMP_FATAL( LockStillOwned, func );
01126         }
01127     }
01128     __kmp_destroy_nested_ticket_lock( lck );
01129 }
01130 
01131 
01132 //
01133 // access functions to fields which don't exist for all lock kinds.
01134 //
01135 
01136 static int
01137 __kmp_is_ticket_lock_initialized( kmp_ticket_lock_t *lck )
01138 {
01139     return lck == lck->lk.initialized;
01140 }
01141 
01142 static const ident_t *
01143 __kmp_get_ticket_lock_location( kmp_ticket_lock_t *lck )
01144 {
01145     return lck->lk.location;
01146 }
01147 
01148 static void
01149 __kmp_set_ticket_lock_location( kmp_ticket_lock_t *lck, const ident_t *loc )
01150 {
01151     lck->lk.location = loc;
01152 }
01153 
01154 static kmp_lock_flags_t
01155 __kmp_get_ticket_lock_flags( kmp_ticket_lock_t *lck )
01156 {
01157     return lck->lk.flags;
01158 }
01159 
01160 static void
01161 __kmp_set_ticket_lock_flags( kmp_ticket_lock_t *lck, kmp_lock_flags_t flags )
01162 {
01163     lck->lk.flags = flags;
01164 }
01165 
01166 /* ------------------------------------------------------------------------ */
01167 /* queuing locks */
01168 
01169 /*
01170  * First the states
01171  * (head,tail) =  0, 0  means lock is unheld, nobody on queue
01172  *   UINT_MAX or -1, 0  means lock is held, nobody on queue
01173  *                h, h  means lock is held or about to transition, 1 element on queue
01174  *                h, t  h <> t, means lock is held or about to transition, >1 elements on queue
01175  *
01176  * Now the transitions
01177  *    Acquire(0,0)  = -1 ,0
01178  *    Release(0,0)  = Error
01179  *    Acquire(-1,0) =  h ,h    h > 0
01180  *    Release(-1,0) =  0 ,0
01181  *    Acquire(h,h)  =  h ,t    h > 0, t > 0, h <> t
01182  *    Release(h,h)  = -1 ,0    h > 0
01183  *    Acquire(h,t)  =  h ,t'   h > 0, t > 0, t' > 0, h <> t, h <> t', t <> t'
01184  *    Release(h,t)  =  h',t    h > 0, t > 0, h <> t, h <> h', h' maybe = t
01185  *
01186  * And pictorially
01187  *
01188  *
01189  *          +-----+
01190  *          | 0, 0|------- release -------> Error
01191  *          +-----+
01192  *            |  ^
01193  *     acquire|  |release
01194  *            |  |
01195  *            |  |
01196  *            v  |
01197  *          +-----+
01198  *          |-1, 0|
01199  *          +-----+
01200  *            |  ^
01201  *     acquire|  |release
01202  *            |  |
01203  *            |  |
01204  *            v  |
01205  *          +-----+
01206  *          | h, h|
01207  *          +-----+
01208  *            |  ^
01209  *     acquire|  |release
01210  *            |  |
01211  *            |  |
01212  *            v  |
01213  *          +-----+
01214  *          | h, t|----- acquire, release loopback ---+
01215  *          +-----+                                   |
01216  *               ^                                    |
01217  *               |                                    |
01218  *               +------------------------------------+
01219  *
01220  */
01221 
01222 #ifdef DEBUG_QUEUING_LOCKS
01223 
01224 /* Stuff for circular trace buffer */
01225 #define TRACE_BUF_ELE   1024
01226 static char traces[TRACE_BUF_ELE][128] = { 0 }
01227 static int tc = 0;
01228 #define TRACE_LOCK(X,Y)          sprintf( traces[tc++ % TRACE_BUF_ELE], "t%d at %s\n", X, Y );
01229 #define TRACE_LOCK_T(X,Y,Z)      sprintf( traces[tc++ % TRACE_BUF_ELE], "t%d at %s%d\n", X,Y,Z );
01230 #define TRACE_LOCK_HT(X,Y,Z,Q)   sprintf( traces[tc++ % TRACE_BUF_ELE], "t%d at %s %d,%d\n", X, Y, Z, Q );
01231 
01232 static void
01233 __kmp_dump_queuing_lock( kmp_info_t *this_thr, kmp_int32 gtid,
01234   kmp_queuing_lock_t *lck, kmp_int32 head_id, kmp_int32 tail_id )
01235 {
01236     kmp_int32 t, i;
01237 
01238     __kmp_printf_no_lock( "\n__kmp_dump_queuing_lock: TRACE BEGINS HERE! \n" );
01239 
01240     i = tc % TRACE_BUF_ELE;
01241     __kmp_printf_no_lock( "%s\n", traces[i] );
01242     i = (i+1) % TRACE_BUF_ELE;
01243     while ( i != (tc % TRACE_BUF_ELE) ) {
01244         __kmp_printf_no_lock( "%s", traces[i] );
01245         i = (i+1) % TRACE_BUF_ELE;
01246     }
01247     __kmp_printf_no_lock( "\n" );
01248 
01249     __kmp_printf_no_lock(
01250              "\n__kmp_dump_queuing_lock: gtid+1:%d, spin_here:%d, next_wait:%d, head_id:%d, tail_id:%d\n",
01251              gtid+1, this_thr->th.th_spin_here, this_thr->th.th_next_waiting,
01252              head_id, tail_id );
01253 
01254     __kmp_printf_no_lock( "\t\thead: %d ", lck->lk.head_id );
01255 
01256     if ( lck->lk.head_id >= 1 ) {
01257         t = __kmp_threads[lck->lk.head_id-1]->th.th_next_waiting;
01258         while (t > 0) {
01259             __kmp_printf_no_lock( "-> %d ", t );
01260             t = __kmp_threads[t-1]->th.th_next_waiting;
01261         }
01262     }
01263     __kmp_printf_no_lock( ";  tail: %d ", lck->lk.tail_id );
01264     __kmp_printf_no_lock( "\n\n" );
01265 }
01266 
01267 #endif /* DEBUG_QUEUING_LOCKS */
01268 
01269 static kmp_int32
01270 __kmp_get_queuing_lock_owner( kmp_queuing_lock_t *lck )
01271 {
01272     return TCR_4( lck->lk.owner_id ) - 1;
01273 }
01274 
01275 static inline bool
01276 __kmp_is_queuing_lock_nestable( kmp_queuing_lock_t *lck )
01277 {
01278     return lck->lk.depth_locked != -1;
01279 }
01280 
01281 /* Acquire a lock using a the queuing lock implementation */
01282 template <bool takeTime>
01283 /* [TLW] The unused template above is left behind because of what BEB believes is a 
01284    potential compiler problem with __forceinline. */
01285 __forceinline static void
01286 __kmp_acquire_queuing_lock_timed_template( kmp_queuing_lock_t *lck,
01287   kmp_int32 gtid )
01288 {
01289     register kmp_info_t *this_thr    = __kmp_thread_from_gtid( gtid );
01290     volatile kmp_int32  *head_id_p   = & lck->lk.head_id;
01291     volatile kmp_int32  *tail_id_p   = & lck->lk.tail_id;
01292     volatile kmp_uint32 *spin_here_p;
01293     kmp_int32 need_mf = 1;
01294 
01295 #if OMPT_SUPPORT
01296     ompt_state_t prev_state = ompt_state_undefined;
01297 #endif
01298 
01299     KA_TRACE( 1000, ("__kmp_acquire_queuing_lock: lck:%p, T#%d entering\n", lck, gtid ));
01300 
01301     KMP_DEBUG_ASSERT( this_thr != NULL );
01302     spin_here_p = & this_thr->th.th_spin_here;
01303 
01304 #ifdef DEBUG_QUEUING_LOCKS
01305     TRACE_LOCK( gtid+1, "acq ent" );
01306     if ( *spin_here_p )
01307         __kmp_dump_queuing_lock( this_thr, gtid, lck, *head_id_p, *tail_id_p );
01308     if ( this_thr->th.th_next_waiting != 0 )
01309         __kmp_dump_queuing_lock( this_thr, gtid, lck, *head_id_p, *tail_id_p );
01310 #endif
01311     KMP_DEBUG_ASSERT( !*spin_here_p );
01312     KMP_DEBUG_ASSERT( this_thr->th.th_next_waiting == 0 );
01313 
01314 
01315     /* The following st.rel to spin_here_p needs to precede the cmpxchg.acq to head_id_p
01316        that may follow, not just in execution order, but also in visibility order.  This way,
01317        when a releasing thread observes the changes to the queue by this thread, it can
01318        rightly assume that spin_here_p has already been set to TRUE, so that when it sets
01319        spin_here_p to FALSE, it is not premature.  If the releasing thread sets spin_here_p
01320        to FALSE before this thread sets it to TRUE, this thread will hang.
01321     */
01322     *spin_here_p = TRUE;  /* before enqueuing to prevent race */
01323 
01324     while( 1 ) {
01325         kmp_int32 enqueued;
01326         kmp_int32 head;
01327         kmp_int32 tail;
01328 
01329         head = *head_id_p;
01330 
01331         switch ( head ) {
01332 
01333             case -1:
01334             {
01335 #ifdef DEBUG_QUEUING_LOCKS
01336                 tail = *tail_id_p;
01337                 TRACE_LOCK_HT( gtid+1, "acq read: ", head, tail );
01338 #endif
01339                 tail = 0;  /* to make sure next link asynchronously read is not set accidentally;
01340                            this assignment prevents us from entering the if ( t > 0 )
01341                            condition in the enqueued case below, which is not necessary for
01342                            this state transition */
01343 
01344                 need_mf = 0;
01345                 /* try (-1,0)->(tid,tid) */
01346                 enqueued = KMP_COMPARE_AND_STORE_ACQ64( (volatile kmp_int64 *) tail_id_p,
01347                   KMP_PACK_64( -1, 0 ),
01348                   KMP_PACK_64( gtid+1, gtid+1 ) );
01349 #ifdef DEBUG_QUEUING_LOCKS
01350                   if ( enqueued ) TRACE_LOCK( gtid+1, "acq enq: (-1,0)->(tid,tid)" );
01351 #endif
01352             }
01353             break;
01354 
01355             default:
01356             {
01357                 tail = *tail_id_p;
01358                 KMP_DEBUG_ASSERT( tail != gtid + 1 );
01359 
01360 #ifdef DEBUG_QUEUING_LOCKS
01361                 TRACE_LOCK_HT( gtid+1, "acq read: ", head, tail );
01362 #endif
01363 
01364                 if ( tail == 0 ) {
01365                     enqueued = FALSE;
01366                 }
01367                 else {
01368                     need_mf = 0;
01369                     /* try (h,t) or (h,h)->(h,tid) */
01370                     enqueued = KMP_COMPARE_AND_STORE_ACQ32( tail_id_p, tail, gtid+1 );
01371 
01372 #ifdef DEBUG_QUEUING_LOCKS
01373                         if ( enqueued ) TRACE_LOCK( gtid+1, "acq enq: (h,t)->(h,tid)" );
01374 #endif
01375                 }
01376             }
01377             break;
01378 
01379             case 0: /* empty queue */
01380             {
01381                 kmp_int32 grabbed_lock;
01382 
01383 #ifdef DEBUG_QUEUING_LOCKS
01384                 tail = *tail_id_p;
01385                 TRACE_LOCK_HT( gtid+1, "acq read: ", head, tail );
01386 #endif
01387                 /* try (0,0)->(-1,0) */
01388 
01389                 /* only legal transition out of head = 0 is head = -1 with no change to tail */
01390                 grabbed_lock = KMP_COMPARE_AND_STORE_ACQ32( head_id_p, 0, -1 );
01391 
01392                 if ( grabbed_lock ) {
01393 
01394                     *spin_here_p = FALSE;
01395 
01396                     KA_TRACE( 1000, ("__kmp_acquire_queuing_lock: lck:%p, T#%d exiting: no queuing\n",
01397                               lck, gtid ));
01398 #ifdef DEBUG_QUEUING_LOCKS
01399                     TRACE_LOCK_HT( gtid+1, "acq exit: ", head, 0 );
01400 #endif
01401         
01402 #if OMPT_SUPPORT
01403                     if ((ompt_status & ompt_status_track) && (prev_state != ompt_state_undefined)) {
01404               /* change the state before clearing wait_id */
01405               this_thr->th.ompt_thread_info.state = prev_state;
01406               this_thr->th.ompt_thread_info.wait_id = 0;
01407                     }
01408 #endif
01409 
01410                     return; /* lock holder cannot be on queue */
01411                 }
01412                 enqueued = FALSE;
01413             }
01414             break;
01415         }
01416 
01417 #if OMPT_SUPPORT
01418         if (ompt_status & ompt_status_track && prev_state == ompt_state_undefined) {
01419       /* this thread will spin; set wait_id before entering wait state */
01420        prev_state = this_thr->th.ompt_thread_info.state;
01421        this_thr->th.ompt_thread_info.wait_id = (uint64_t) lck;
01422        this_thr->th.ompt_thread_info.state = ompt_state_wait_lock;
01423         }
01424 #endif
01425 
01426         if ( enqueued ) {
01427             if ( tail > 0 ) {
01428                 kmp_info_t *tail_thr = __kmp_thread_from_gtid( tail - 1 );
01429                 KMP_ASSERT( tail_thr != NULL );
01430                 tail_thr->th.th_next_waiting = gtid+1;
01431                 /* corresponding wait for this write in release code */
01432             }
01433             KA_TRACE( 1000, ("__kmp_acquire_queuing_lock: lck:%p, T#%d waiting for lock\n", lck, gtid ));
01434 
01435 
01436             /* ToDo: May want to consider using __kmp_wait_sleep  or something that sleeps for
01437              *       throughput only here.
01438              */
01439             KMP_MB();
01440             KMP_WAIT_YIELD(spin_here_p, FALSE, KMP_EQ, lck);
01441 
01442 #ifdef DEBUG_QUEUING_LOCKS
01443             TRACE_LOCK( gtid+1, "acq spin" );
01444 
01445             if ( this_thr->th.th_next_waiting != 0 )
01446                 __kmp_dump_queuing_lock( this_thr, gtid, lck, *head_id_p, *tail_id_p );
01447 #endif
01448             KMP_DEBUG_ASSERT( this_thr->th.th_next_waiting == 0 );
01449             KA_TRACE( 1000, ("__kmp_acquire_queuing_lock: lck:%p, T#%d exiting: after waiting on queue\n",
01450                       lck, gtid ));
01451 
01452 #ifdef DEBUG_QUEUING_LOCKS
01453             TRACE_LOCK( gtid+1, "acq exit 2" );
01454 #endif
01455         
01456 #if OMPT_SUPPORT
01457         /* change the state before clearing wait_id */
01458         this_thr->th.ompt_thread_info.state = prev_state;
01459         this_thr->th.ompt_thread_info.wait_id = 0;
01460 #endif
01461 
01462             /* got lock, we were dequeued by the thread that released lock */
01463             return;
01464         }
01465 
01466         /* Yield if number of threads > number of logical processors */
01467         /* ToDo: Not sure why this should only be in oversubscription case,
01468            maybe should be traditional YIELD_INIT/YIELD_WHEN loop */
01469         KMP_YIELD( TCR_4( __kmp_nth ) > (__kmp_avail_proc ? __kmp_avail_proc :
01470           __kmp_xproc ) );
01471 #ifdef DEBUG_QUEUING_LOCKS
01472         TRACE_LOCK( gtid+1, "acq retry" );
01473 #endif
01474 
01475     }
01476     KMP_ASSERT2( 0, "should not get here" );
01477 }
01478 
01479 void
01480 __kmp_acquire_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01481 {
01482     KMP_DEBUG_ASSERT( gtid >= 0 );
01483 
01484     __kmp_acquire_queuing_lock_timed_template<false>( lck, gtid );
01485 }
01486 
01487 static void
01488 __kmp_acquire_queuing_lock_with_checks( kmp_queuing_lock_t *lck,
01489   kmp_int32 gtid )
01490 {
01491     if ( __kmp_env_consistency_check ) {
01492         char const * const func = "omp_set_lock";
01493         if ( lck->lk.initialized != lck ) {
01494             KMP_FATAL( LockIsUninitialized, func );
01495         }
01496         if ( __kmp_is_queuing_lock_nestable( lck ) ) {
01497             KMP_FATAL( LockNestableUsedAsSimple, func );
01498         }
01499         if ( __kmp_get_queuing_lock_owner( lck ) == gtid ) {
01500             KMP_FATAL( LockIsAlreadyOwned, func );
01501         }
01502     }
01503 
01504     __kmp_acquire_queuing_lock( lck, gtid );
01505 
01506     if ( __kmp_env_consistency_check ) {
01507         lck->lk.owner_id = gtid + 1;
01508     }
01509 }
01510 
01511 int
01512 __kmp_test_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01513 {
01514     volatile kmp_int32 *head_id_p  = & lck->lk.head_id;
01515     kmp_int32 head;
01516 #ifdef KMP_DEBUG
01517     kmp_info_t *this_thr;
01518 #endif
01519 
01520     KA_TRACE( 1000, ("__kmp_test_queuing_lock: T#%d entering\n", gtid ));
01521     KMP_DEBUG_ASSERT( gtid >= 0 );
01522 #ifdef KMP_DEBUG
01523     this_thr = __kmp_thread_from_gtid( gtid );
01524     KMP_DEBUG_ASSERT( this_thr != NULL );
01525     KMP_DEBUG_ASSERT( !this_thr->th.th_spin_here );
01526 #endif
01527 
01528     head = *head_id_p;
01529 
01530     if ( head == 0 ) { /* nobody on queue, nobody holding */
01531 
01532         /* try (0,0)->(-1,0) */
01533 
01534         if ( KMP_COMPARE_AND_STORE_ACQ32( head_id_p, 0, -1 ) ) {
01535             KA_TRACE( 1000, ("__kmp_test_queuing_lock: T#%d exiting: holding lock\n", gtid ));
01536             return TRUE;
01537         }
01538     }
01539 
01540     KA_TRACE( 1000, ("__kmp_test_queuing_lock: T#%d exiting: without lock\n", gtid ));
01541     return FALSE;
01542 }
01543 
01544 static int
01545 __kmp_test_queuing_lock_with_checks( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01546 {
01547     if ( __kmp_env_consistency_check ) {
01548         char const * const func = "omp_test_lock";
01549         if ( lck->lk.initialized != lck ) {
01550             KMP_FATAL( LockIsUninitialized, func );
01551         }
01552         if ( __kmp_is_queuing_lock_nestable( lck ) ) {
01553             KMP_FATAL( LockNestableUsedAsSimple, func );
01554         }
01555     }
01556 
01557     int retval = __kmp_test_queuing_lock( lck, gtid );
01558 
01559     if ( __kmp_env_consistency_check && retval ) {
01560         lck->lk.owner_id = gtid + 1;
01561     }
01562     return retval;
01563 }
01564 
01565 void
01566 __kmp_release_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01567 {
01568     register kmp_info_t *this_thr;
01569     volatile kmp_int32 *head_id_p = & lck->lk.head_id;
01570     volatile kmp_int32 *tail_id_p = & lck->lk.tail_id;
01571 
01572     KA_TRACE( 1000, ("__kmp_release_queuing_lock: lck:%p, T#%d entering\n", lck, gtid ));
01573     KMP_DEBUG_ASSERT( gtid >= 0 );
01574     this_thr    = __kmp_thread_from_gtid( gtid );
01575     KMP_DEBUG_ASSERT( this_thr != NULL );
01576 #ifdef DEBUG_QUEUING_LOCKS
01577     TRACE_LOCK( gtid+1, "rel ent" );
01578 
01579     if ( this_thr->th.th_spin_here )
01580         __kmp_dump_queuing_lock( this_thr, gtid, lck, *head_id_p, *tail_id_p );
01581     if ( this_thr->th.th_next_waiting != 0 )
01582         __kmp_dump_queuing_lock( this_thr, gtid, lck, *head_id_p, *tail_id_p );
01583 #endif
01584     KMP_DEBUG_ASSERT( !this_thr->th.th_spin_here );
01585     KMP_DEBUG_ASSERT( this_thr->th.th_next_waiting == 0 );
01586 
01587     while( 1 ) {
01588         kmp_int32 dequeued;
01589         kmp_int32 head;
01590         kmp_int32 tail;
01591 
01592         head = *head_id_p;
01593 
01594 #ifdef DEBUG_QUEUING_LOCKS
01595         tail = *tail_id_p;
01596         TRACE_LOCK_HT( gtid+1, "rel read: ", head, tail );
01597         if ( head == 0 ) __kmp_dump_queuing_lock( this_thr, gtid, lck, head, tail );
01598 #endif
01599         KMP_DEBUG_ASSERT( head != 0 ); /* holding the lock, head must be -1 or queue head */
01600 
01601         if ( head == -1 ) { /* nobody on queue */
01602 
01603             /* try (-1,0)->(0,0) */
01604             if ( KMP_COMPARE_AND_STORE_REL32( head_id_p, -1, 0 ) ) {
01605                 KA_TRACE( 1000, ("__kmp_release_queuing_lock: lck:%p, T#%d exiting: queue empty\n",
01606                           lck, gtid ));
01607 #ifdef DEBUG_QUEUING_LOCKS
01608                 TRACE_LOCK_HT( gtid+1, "rel exit: ", 0, 0 );
01609 #endif
01610 
01611 #if OMPT_SUPPORT
01612                 /* nothing to do - no other thread is trying to shift blame */
01613 #endif
01614 
01615                 return;
01616             }
01617             dequeued = FALSE;
01618 
01619         }
01620         else {
01621 
01622             tail = *tail_id_p;
01623             if ( head == tail ) {  /* only one thread on the queue */
01624 
01625 #ifdef DEBUG_QUEUING_LOCKS
01626                 if ( head <= 0 ) __kmp_dump_queuing_lock( this_thr, gtid, lck, head, tail );
01627 #endif
01628                 KMP_DEBUG_ASSERT( head > 0 );
01629 
01630                 /* try (h,h)->(-1,0) */
01631                 dequeued = KMP_COMPARE_AND_STORE_REL64( (kmp_int64 *) tail_id_p,
01632                   KMP_PACK_64( head, head ), KMP_PACK_64( -1, 0 ) );
01633 #ifdef DEBUG_QUEUING_LOCKS
01634                 TRACE_LOCK( gtid+1, "rel deq: (h,h)->(-1,0)" );
01635 #endif
01636 
01637             }
01638             else {
01639                 volatile kmp_int32 *waiting_id_p;
01640                 kmp_info_t         *head_thr = __kmp_thread_from_gtid( head - 1 );
01641                 KMP_DEBUG_ASSERT( head_thr != NULL );
01642                 waiting_id_p = & head_thr->th.th_next_waiting;
01643 
01644                 /* Does this require synchronous reads? */
01645 #ifdef DEBUG_QUEUING_LOCKS
01646                 if ( head <= 0 || tail <= 0 ) __kmp_dump_queuing_lock( this_thr, gtid, lck, head, tail );
01647 #endif
01648                 KMP_DEBUG_ASSERT( head > 0 && tail > 0 );
01649 
01650                 /* try (h,t)->(h',t) or (t,t) */
01651 
01652                 KMP_MB();
01653                 /* make sure enqueuing thread has time to update next waiting thread field */
01654                 *head_id_p = (kmp_int32) KMP_WAIT_YIELD((volatile kmp_uint*) waiting_id_p, 0, KMP_NEQ, NULL);
01655 #ifdef DEBUG_QUEUING_LOCKS
01656                 TRACE_LOCK( gtid+1, "rel deq: (h,t)->(h',t)" );
01657 #endif
01658                 dequeued = TRUE;
01659             }
01660         }
01661 
01662         if ( dequeued ) {
01663             kmp_info_t *head_thr = __kmp_thread_from_gtid( head - 1 );
01664             KMP_DEBUG_ASSERT( head_thr != NULL );
01665 
01666             /* Does this require synchronous reads? */
01667 #ifdef DEBUG_QUEUING_LOCKS
01668             if ( head <= 0 || tail <= 0 ) __kmp_dump_queuing_lock( this_thr, gtid, lck, head, tail );
01669 #endif
01670             KMP_DEBUG_ASSERT( head > 0 && tail > 0 );
01671 
01672             /* For clean code only.
01673              * Thread not released until next statement prevents race with acquire code.
01674              */
01675             head_thr->th.th_next_waiting = 0;
01676 #ifdef DEBUG_QUEUING_LOCKS
01677             TRACE_LOCK_T( gtid+1, "rel nw=0 for t=", head );
01678 #endif
01679 
01680             KMP_MB();
01681             /* reset spin value */
01682             head_thr->th.th_spin_here = FALSE;
01683 
01684             KA_TRACE( 1000, ("__kmp_release_queuing_lock: lck:%p, T#%d exiting: after dequeuing\n",
01685                       lck, gtid ));
01686 #ifdef DEBUG_QUEUING_LOCKS
01687             TRACE_LOCK( gtid+1, "rel exit 2" );
01688 #endif
01689             return;
01690         }
01691         /* KMP_CPU_PAUSE( );  don't want to make releasing thread hold up acquiring threads */
01692 
01693 #ifdef DEBUG_QUEUING_LOCKS
01694         TRACE_LOCK( gtid+1, "rel retry" );
01695 #endif
01696 
01697     } /* while */
01698     KMP_ASSERT2( 0, "should not get here" );
01699 }
01700 
01701 static void
01702 __kmp_release_queuing_lock_with_checks( kmp_queuing_lock_t *lck,
01703   kmp_int32 gtid )
01704 {
01705     if ( __kmp_env_consistency_check ) {
01706         char const * const func = "omp_unset_lock";
01707         KMP_MB();  /* in case another processor initialized lock */
01708         if ( lck->lk.initialized != lck ) {
01709             KMP_FATAL( LockIsUninitialized, func );
01710         }
01711         if ( __kmp_is_queuing_lock_nestable( lck ) ) {
01712             KMP_FATAL( LockNestableUsedAsSimple, func );
01713         }
01714         if ( __kmp_get_queuing_lock_owner( lck ) == -1 ) {
01715             KMP_FATAL( LockUnsettingFree, func );
01716         }
01717         if ( __kmp_get_queuing_lock_owner( lck ) != gtid ) {
01718             KMP_FATAL( LockUnsettingSetByAnother, func );
01719         }
01720         lck->lk.owner_id = 0;
01721     }
01722     __kmp_release_queuing_lock( lck, gtid );
01723 }
01724 
01725 void
01726 __kmp_init_queuing_lock( kmp_queuing_lock_t *lck )
01727 {
01728     lck->lk.location = NULL;
01729     lck->lk.head_id = 0;
01730     lck->lk.tail_id = 0;
01731     lck->lk.next_ticket = 0;
01732     lck->lk.now_serving = 0;
01733     lck->lk.owner_id = 0;      // no thread owns the lock.
01734     lck->lk.depth_locked = -1; // >= 0 for nestable locks, -1 for simple locks.
01735     lck->lk.initialized = lck;
01736 
01737     KA_TRACE(1000, ("__kmp_init_queuing_lock: lock %p initialized\n", lck));
01738 }
01739 
01740 static void
01741 __kmp_init_queuing_lock_with_checks( kmp_queuing_lock_t * lck )
01742 {
01743     __kmp_init_queuing_lock( lck );
01744 }
01745 
01746 void
01747 __kmp_destroy_queuing_lock( kmp_queuing_lock_t *lck )
01748 {
01749     lck->lk.initialized = NULL;
01750     lck->lk.location = NULL;
01751     lck->lk.head_id = 0;
01752     lck->lk.tail_id = 0;
01753     lck->lk.next_ticket = 0;
01754     lck->lk.now_serving = 0;
01755     lck->lk.owner_id = 0;
01756     lck->lk.depth_locked = -1;
01757 }
01758 
01759 static void
01760 __kmp_destroy_queuing_lock_with_checks( kmp_queuing_lock_t *lck )
01761 {
01762     if ( __kmp_env_consistency_check ) {
01763         char const * const func = "omp_destroy_lock";
01764         if ( lck->lk.initialized != lck ) {
01765             KMP_FATAL( LockIsUninitialized, func );
01766         }
01767         if ( __kmp_is_queuing_lock_nestable( lck ) ) {
01768             KMP_FATAL( LockNestableUsedAsSimple, func );
01769         }
01770         if ( __kmp_get_queuing_lock_owner( lck ) != -1 ) {
01771             KMP_FATAL( LockStillOwned, func );
01772         }
01773     }
01774     __kmp_destroy_queuing_lock( lck );
01775 }
01776 
01777 
01778 //
01779 // nested queuing locks
01780 //
01781 
01782 void
01783 __kmp_acquire_nested_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01784 {
01785     KMP_DEBUG_ASSERT( gtid >= 0 );
01786 
01787     if ( __kmp_get_queuing_lock_owner( lck ) == gtid ) {
01788         lck->lk.depth_locked += 1;
01789     }
01790     else {
01791         __kmp_acquire_queuing_lock_timed_template<false>( lck, gtid );
01792         KMP_MB();
01793         lck->lk.depth_locked = 1;
01794         KMP_MB();
01795         lck->lk.owner_id = gtid + 1;
01796     }
01797 }
01798 
01799 static void
01800 __kmp_acquire_nested_queuing_lock_with_checks( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01801 {
01802     if ( __kmp_env_consistency_check ) {
01803         char const * const func = "omp_set_nest_lock";
01804         if ( lck->lk.initialized != lck ) {
01805             KMP_FATAL( LockIsUninitialized, func );
01806         }
01807         if ( ! __kmp_is_queuing_lock_nestable( lck ) ) {
01808             KMP_FATAL( LockSimpleUsedAsNestable, func );
01809         }
01810     }
01811     __kmp_acquire_nested_queuing_lock( lck, gtid );
01812 }
01813 
01814 int
01815 __kmp_test_nested_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01816 {
01817     int retval;
01818 
01819     KMP_DEBUG_ASSERT( gtid >= 0 );
01820 
01821     if ( __kmp_get_queuing_lock_owner( lck ) == gtid ) {
01822         retval = ++lck->lk.depth_locked;
01823     }
01824     else if ( !__kmp_test_queuing_lock( lck, gtid ) ) {
01825         retval = 0;
01826     }
01827     else {
01828         KMP_MB();
01829         retval = lck->lk.depth_locked = 1;
01830         KMP_MB();
01831         lck->lk.owner_id = gtid + 1;
01832     }
01833     return retval;
01834 }
01835 
01836 static int
01837 __kmp_test_nested_queuing_lock_with_checks( kmp_queuing_lock_t *lck,
01838   kmp_int32 gtid )
01839 {
01840     if ( __kmp_env_consistency_check ) {
01841         char const * const func = "omp_test_nest_lock";
01842         if ( lck->lk.initialized != lck ) {
01843             KMP_FATAL( LockIsUninitialized, func );
01844         }
01845         if ( ! __kmp_is_queuing_lock_nestable( lck ) ) {
01846             KMP_FATAL( LockSimpleUsedAsNestable, func );
01847         }
01848     }
01849     return __kmp_test_nested_queuing_lock( lck, gtid );
01850 }
01851 
01852 int
01853 __kmp_release_nested_queuing_lock( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01854 {
01855     KMP_DEBUG_ASSERT( gtid >= 0 );
01856 
01857     KMP_MB();
01858     if ( --(lck->lk.depth_locked) == 0 ) {
01859         KMP_MB();
01860         lck->lk.owner_id = 0;
01861         __kmp_release_queuing_lock( lck, gtid );
01862     return KMP_NESTED_LOCK_RELEASED;
01863     }
01864     return KMP_NESTED_LOCK_HELD;
01865 }
01866 
01867 static int
01868 __kmp_release_nested_queuing_lock_with_checks( kmp_queuing_lock_t *lck, kmp_int32 gtid )
01869 {
01870     if ( __kmp_env_consistency_check ) {
01871         char const * const func = "omp_unset_nest_lock";
01872         KMP_MB();  /* in case another processor initialized lock */
01873         if ( lck->lk.initialized != lck ) {
01874             KMP_FATAL( LockIsUninitialized, func );
01875         }
01876         if ( ! __kmp_is_queuing_lock_nestable( lck ) ) {
01877             KMP_FATAL( LockSimpleUsedAsNestable, func );
01878         }
01879         if ( __kmp_get_queuing_lock_owner( lck ) == -1 ) {
01880             KMP_FATAL( LockUnsettingFree, func );
01881         }
01882         if ( __kmp_get_queuing_lock_owner( lck ) != gtid ) {
01883             KMP_FATAL( LockUnsettingSetByAnother, func );
01884         }
01885     }
01886     return __kmp_release_nested_queuing_lock( lck, gtid );
01887 }
01888 
01889 void
01890 __kmp_init_nested_queuing_lock( kmp_queuing_lock_t * lck )
01891 {
01892     __kmp_init_queuing_lock( lck );
01893     lck->lk.depth_locked = 0; // >= 0 for nestable locks, -1 for simple locks
01894 }
01895 
01896 static void
01897 __kmp_init_nested_queuing_lock_with_checks( kmp_queuing_lock_t * lck )
01898 {
01899     __kmp_init_nested_queuing_lock( lck );
01900 }
01901 
01902 void
01903 __kmp_destroy_nested_queuing_lock( kmp_queuing_lock_t *lck )
01904 {
01905     __kmp_destroy_queuing_lock( lck );
01906     lck->lk.depth_locked = 0;
01907 }
01908 
01909 static void
01910 __kmp_destroy_nested_queuing_lock_with_checks( kmp_queuing_lock_t *lck )
01911 {
01912     if ( __kmp_env_consistency_check ) {
01913         char const * const func = "omp_destroy_nest_lock";
01914         if ( lck->lk.initialized != lck ) {
01915             KMP_FATAL( LockIsUninitialized, func );
01916         }
01917         if ( ! __kmp_is_queuing_lock_nestable( lck ) ) {
01918             KMP_FATAL( LockSimpleUsedAsNestable, func );
01919         }
01920         if ( __kmp_get_queuing_lock_owner( lck ) != -1 ) {
01921             KMP_FATAL( LockStillOwned, func );
01922         }
01923     }
01924     __kmp_destroy_nested_queuing_lock( lck );
01925 }
01926 
01927 
01928 //
01929 // access functions to fields which don't exist for all lock kinds.
01930 //
01931 
01932 static int
01933 __kmp_is_queuing_lock_initialized( kmp_queuing_lock_t *lck )
01934 {
01935     return lck == lck->lk.initialized;
01936 }
01937 
01938 static const ident_t *
01939 __kmp_get_queuing_lock_location( kmp_queuing_lock_t *lck )
01940 {
01941     return lck->lk.location;
01942 }
01943 
01944 static void
01945 __kmp_set_queuing_lock_location( kmp_queuing_lock_t *lck, const ident_t *loc )
01946 {
01947     lck->lk.location = loc;
01948 }
01949 
01950 static kmp_lock_flags_t
01951 __kmp_get_queuing_lock_flags( kmp_queuing_lock_t *lck )
01952 {
01953     return lck->lk.flags;
01954 }
01955 
01956 void
01957 __kmp_set_queuing_lock_flags( kmp_queuing_lock_t *lck, kmp_lock_flags_t flags )
01958 {
01959     lck->lk.flags = flags;
01960 }
01961 
01962 /* ------------------------------------------------------------------------ */
01963 /* DRDPA ticket locks                                                */
01964 /* "DRDPA" means Dynamically Reconfigurable Distributed Polling Area */
01965 
01966 static kmp_int32
01967 __kmp_get_drdpa_lock_owner( kmp_drdpa_lock_t *lck )
01968 {
01969     return TCR_4( lck->lk.owner_id ) - 1;
01970 }
01971 
01972 static inline bool
01973 __kmp_is_drdpa_lock_nestable( kmp_drdpa_lock_t *lck )
01974 {
01975     return lck->lk.depth_locked != -1;
01976 }
01977 
01978 __forceinline static void
01979 __kmp_acquire_drdpa_lock_timed_template( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
01980 {
01981     kmp_uint64 ticket = KMP_TEST_THEN_INC64((kmp_int64 *)&lck->lk.next_ticket);
01982     kmp_uint64 mask = TCR_8(lck->lk.mask);              // volatile load
01983     volatile struct kmp_base_drdpa_lock::kmp_lock_poll *polls
01984       = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
01985       TCR_PTR(lck->lk.polls);                           // volatile load
01986 
01987 #ifdef USE_LOCK_PROFILE
01988     if (TCR_8(polls[ticket & mask].poll) != ticket)
01989         __kmp_printf("LOCK CONTENTION: %p\n", lck);
01990     /* else __kmp_printf( "." );*/
01991 #endif /* USE_LOCK_PROFILE */
01992 
01993     //
01994     // Now spin-wait, but reload the polls pointer and mask, in case the
01995     // polling area has been reconfigured.  Unless it is reconfigured, the
01996     // reloads stay in L1 cache and are cheap.
01997     //
01998     // Keep this code in sync with KMP_WAIT_YIELD, in kmp_dispatch.c !!!
01999     //
02000     // The current implementation of KMP_WAIT_YIELD doesn't allow for mask
02001     // and poll to be re-read every spin iteration.
02002     //
02003     kmp_uint32 spins;
02004     KMP_INIT_YIELD(spins);
02005     while (TCR_8(polls[ticket & mask]).poll < ticket) { // volatile load
02006         __kmp_static_delay(TRUE);
02007 
02008         //
02009         // If we are oversubscribed,
02010         // or ahve waited a bit (and KMP_LIBRARY=turnaround), then yield.
02011         // CPU Pause is in the macros for yield.
02012         //
02013         KMP_YIELD(TCR_4(__kmp_nth)
02014           > (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc));
02015         KMP_YIELD_SPIN(spins);
02016 
02017         // Re-read the mask and the poll pointer from the lock structure.
02018         //
02019         // Make certain that "mask" is read before "polls" !!!
02020         //
02021         // If another thread picks reconfigures the polling area and updates
02022         // their values, and we get the new value of mask and the old polls
02023         // pointer, we could access memory beyond the end of the old polling
02024         // area.
02025         //
02026         mask = TCR_8(lck->lk.mask);                     // volatile load
02027         polls = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02028           TCR_PTR(lck->lk.polls);                       // volatile load
02029     }
02030 
02031     //
02032     // Critical section starts here
02033     //
02034     KA_TRACE(1000, ("__kmp_acquire_drdpa_lock: ticket #%lld acquired lock %p\n",
02035       ticket, lck));
02036     lck->lk.now_serving = ticket;                       // non-volatile store
02037 
02038     //
02039     // Deallocate a garbage polling area if we know that we are the last
02040     // thread that could possibly access it.
02041     //
02042     // The >= check is in case __kmp_test_drdpa_lock() allocated the cleanup
02043     // ticket.
02044     //
02045     if ((lck->lk.old_polls != NULL) && (ticket >= lck->lk.cleanup_ticket)) {
02046         __kmp_free((void *)lck->lk.old_polls);
02047         lck->lk.old_polls = NULL;
02048         lck->lk.cleanup_ticket = 0;
02049     }
02050 
02051     //
02052     // Check to see if we should reconfigure the polling area.
02053     // If there is still a garbage polling area to be deallocated from a
02054     // previous reconfiguration, let a later thread reconfigure it.
02055     //
02056     if (lck->lk.old_polls == NULL) {
02057         bool reconfigure = false;
02058         volatile struct kmp_base_drdpa_lock::kmp_lock_poll *old_polls = polls;
02059         kmp_uint32 num_polls = TCR_4(lck->lk.num_polls);
02060 
02061         if (TCR_4(__kmp_nth)
02062           > (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc)) {
02063             //
02064             // We are in oversubscription mode.  Contract the polling area
02065             // down to a single location, if that hasn't been done already.
02066             //
02067             if (num_polls > 1) {
02068                 reconfigure = true;
02069                 num_polls = TCR_4(lck->lk.num_polls);
02070                 mask = 0;
02071                 num_polls = 1;
02072                 polls = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02073                   __kmp_allocate(num_polls * sizeof(*polls));
02074                 polls[0].poll = ticket;
02075             }
02076         }
02077         else {
02078             //
02079             // We are in under/fully subscribed mode.  Check the number of
02080             // threads waiting on the lock.  The size of the polling area
02081             // should be at least the number of threads waiting.
02082             //
02083             kmp_uint64 num_waiting = TCR_8(lck->lk.next_ticket) - ticket - 1;
02084             if (num_waiting > num_polls) {
02085                 kmp_uint32 old_num_polls = num_polls;
02086                 reconfigure = true;
02087                 do {
02088                     mask = (mask << 1) | 1;
02089                     num_polls *= 2;
02090                 } while (num_polls <= num_waiting);
02091 
02092                 //
02093                 // Allocate the new polling area, and copy the relevant portion
02094                 // of the old polling area to the new area.  __kmp_allocate()
02095                 // zeroes the memory it allocates, and most of the old area is
02096                 // just zero padding, so we only copy the release counters.
02097                 //
02098                 polls = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02099                   __kmp_allocate(num_polls * sizeof(*polls));
02100                 int i;
02101                 for (i = 0; i < old_num_polls; i++) {
02102                     polls[i].poll = old_polls[i].poll;
02103                 }
02104             }
02105         }
02106 
02107         if (reconfigure) {
02108             //
02109             // Now write the updated fields back to the lock structure.
02110             //
02111             // Make certain that "polls" is written before "mask" !!!
02112             //
02113             // If another thread picks up the new value of mask and the old
02114             // polls pointer , it could access memory beyond the end of the
02115             // old polling area.
02116             //
02117             // On x86, we need memory fences.
02118             //
02119             KA_TRACE(1000, ("__kmp_acquire_drdpa_lock: ticket #%lld reconfiguring lock %p to %d polls\n",
02120               ticket, lck, num_polls));
02121 
02122             lck->lk.old_polls = old_polls;              // non-volatile store
02123             lck->lk.polls = polls;                      // volatile store
02124 
02125             KMP_MB();
02126 
02127             lck->lk.num_polls = num_polls;              // non-volatile store
02128             lck->lk.mask = mask;                        // volatile store
02129 
02130             KMP_MB();
02131 
02132             //
02133             // Only after the new polling area and mask have been flushed
02134             // to main memory can we update the cleanup ticket field.
02135             //
02136             // volatile load / non-volatile store
02137             //
02138             lck->lk.cleanup_ticket = TCR_8(lck->lk.next_ticket);
02139         }
02140     }
02141 }
02142 
02143 void
02144 __kmp_acquire_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02145 {
02146     __kmp_acquire_drdpa_lock_timed_template( lck, gtid );
02147 }
02148 
02149 static void
02150 __kmp_acquire_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02151 {
02152     if ( __kmp_env_consistency_check ) {
02153         char const * const func = "omp_set_lock";
02154         if ( lck->lk.initialized != lck ) {
02155             KMP_FATAL( LockIsUninitialized, func );
02156         }
02157         if ( __kmp_is_drdpa_lock_nestable( lck ) ) {
02158             KMP_FATAL( LockNestableUsedAsSimple, func );
02159         }
02160         if ( ( gtid >= 0 ) && ( __kmp_get_drdpa_lock_owner( lck ) == gtid ) ) {
02161             KMP_FATAL( LockIsAlreadyOwned, func );
02162         }
02163     }
02164 
02165     __kmp_acquire_drdpa_lock( lck, gtid );
02166 
02167     if ( __kmp_env_consistency_check ) {
02168         lck->lk.owner_id = gtid + 1;
02169     }
02170 }
02171 
02172 int
02173 __kmp_test_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02174 {
02175     //
02176     // First get a ticket, then read the polls pointer and the mask.
02177     // The polls pointer must be read before the mask!!! (See above)
02178     //
02179     kmp_uint64 ticket = TCR_8(lck->lk.next_ticket);     // volatile load
02180     volatile struct kmp_base_drdpa_lock::kmp_lock_poll *polls
02181       = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02182       TCR_PTR(lck->lk.polls);                           // volatile load
02183     kmp_uint64 mask = TCR_8(lck->lk.mask);              // volatile load
02184     if (TCR_8(polls[ticket & mask].poll) == ticket) {
02185         kmp_uint64 next_ticket = ticket + 1;
02186         if (KMP_COMPARE_AND_STORE_ACQ64((kmp_int64 *)&lck->lk.next_ticket,
02187           ticket, next_ticket)) {
02188             KA_TRACE(1000, ("__kmp_test_drdpa_lock: ticket #%lld acquired lock %p\n",
02189                ticket, lck));
02190             lck->lk.now_serving = ticket;               // non-volatile store
02191 
02192             //
02193             // Since no threads are waiting, there is no possiblity that
02194             // we would want to reconfigure the polling area.  We might
02195             // have the cleanup ticket value (which says that it is now
02196             // safe to deallocate old_polls), but we'll let a later thread
02197             // which calls __kmp_acquire_lock do that - this routine
02198             // isn't supposed to block, and we would risk blocks if we
02199             // called __kmp_free() to do the deallocation.
02200             //
02201             return TRUE;
02202         }
02203     }
02204     return FALSE;
02205 }
02206 
02207 static int
02208 __kmp_test_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02209 {
02210     if ( __kmp_env_consistency_check ) {
02211         char const * const func = "omp_test_lock";
02212         if ( lck->lk.initialized != lck ) {
02213             KMP_FATAL( LockIsUninitialized, func );
02214         }
02215         if ( __kmp_is_drdpa_lock_nestable( lck ) ) {
02216             KMP_FATAL( LockNestableUsedAsSimple, func );
02217         }
02218     }
02219 
02220     int retval = __kmp_test_drdpa_lock( lck, gtid );
02221 
02222     if ( __kmp_env_consistency_check && retval ) {
02223         lck->lk.owner_id = gtid + 1;
02224     }
02225     return retval;
02226 }
02227 
02228 void
02229 __kmp_release_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02230 {
02231     //
02232     // Read the ticket value from the lock data struct, then the polls
02233     // pointer and the mask.  The polls pointer must be read before the
02234     // mask!!! (See above)
02235     //
02236     kmp_uint64 ticket = lck->lk.now_serving + 1;        // non-volatile load
02237     volatile struct kmp_base_drdpa_lock::kmp_lock_poll *polls
02238       = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02239       TCR_PTR(lck->lk.polls);                           // volatile load
02240     kmp_uint64 mask = TCR_8(lck->lk.mask);              // volatile load
02241     KA_TRACE(1000, ("__kmp_release_drdpa_lock: ticket #%lld released lock %p\n",
02242        ticket - 1, lck));
02243     TCW_8(polls[ticket & mask].poll, ticket);           // volatile store
02244 }
02245 
02246 static void
02247 __kmp_release_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02248 {
02249     if ( __kmp_env_consistency_check ) {
02250         char const * const func = "omp_unset_lock";
02251         KMP_MB();  /* in case another processor initialized lock */
02252         if ( lck->lk.initialized != lck ) {
02253             KMP_FATAL( LockIsUninitialized, func );
02254         }
02255         if ( __kmp_is_drdpa_lock_nestable( lck ) ) {
02256             KMP_FATAL( LockNestableUsedAsSimple, func );
02257         }
02258         if ( __kmp_get_drdpa_lock_owner( lck ) == -1 ) {
02259             KMP_FATAL( LockUnsettingFree, func );
02260         }
02261         if ( ( gtid >= 0 ) && ( __kmp_get_drdpa_lock_owner( lck ) >= 0 )
02262           && ( __kmp_get_drdpa_lock_owner( lck ) != gtid ) ) {
02263             KMP_FATAL( LockUnsettingSetByAnother, func );
02264         }
02265         lck->lk.owner_id = 0;
02266     }
02267     __kmp_release_drdpa_lock( lck, gtid );
02268 }
02269 
02270 void
02271 __kmp_init_drdpa_lock( kmp_drdpa_lock_t *lck )
02272 {
02273     lck->lk.location = NULL;
02274     lck->lk.mask = 0;
02275     lck->lk.num_polls = 1;
02276     lck->lk.polls = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02277       __kmp_allocate(lck->lk.num_polls * sizeof(*(lck->lk.polls)));
02278     lck->lk.cleanup_ticket = 0;
02279     lck->lk.old_polls = NULL;
02280     lck->lk.next_ticket = 0;
02281     lck->lk.now_serving = 0;
02282     lck->lk.owner_id = 0;      // no thread owns the lock.
02283     lck->lk.depth_locked = -1; // >= 0 for nestable locks, -1 for simple locks.
02284     lck->lk.initialized = lck;
02285 
02286     KA_TRACE(1000, ("__kmp_init_drdpa_lock: lock %p initialized\n", lck));
02287 }
02288 
02289 static void
02290 __kmp_init_drdpa_lock_with_checks( kmp_drdpa_lock_t * lck )
02291 {
02292     __kmp_init_drdpa_lock( lck );
02293 }
02294 
02295 void
02296 __kmp_destroy_drdpa_lock( kmp_drdpa_lock_t *lck )
02297 {
02298     lck->lk.initialized = NULL;
02299     lck->lk.location    = NULL;
02300     if (lck->lk.polls != NULL) {
02301         __kmp_free((void *)lck->lk.polls);
02302         lck->lk.polls = NULL;
02303     }
02304     if (lck->lk.old_polls != NULL) {
02305         __kmp_free((void *)lck->lk.old_polls);
02306         lck->lk.old_polls = NULL;
02307     }
02308     lck->lk.mask = 0;
02309     lck->lk.num_polls = 0;
02310     lck->lk.cleanup_ticket = 0;
02311     lck->lk.next_ticket = 0;
02312     lck->lk.now_serving = 0;
02313     lck->lk.owner_id = 0;
02314     lck->lk.depth_locked = -1;
02315 }
02316 
02317 static void
02318 __kmp_destroy_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck )
02319 {
02320     if ( __kmp_env_consistency_check ) {
02321         char const * const func = "omp_destroy_lock";
02322         if ( lck->lk.initialized != lck ) {
02323             KMP_FATAL( LockIsUninitialized, func );
02324         }
02325         if ( __kmp_is_drdpa_lock_nestable( lck ) ) {
02326             KMP_FATAL( LockNestableUsedAsSimple, func );
02327         }
02328         if ( __kmp_get_drdpa_lock_owner( lck ) != -1 ) {
02329             KMP_FATAL( LockStillOwned, func );
02330         }
02331     }
02332     __kmp_destroy_drdpa_lock( lck );
02333 }
02334 
02335 
02336 //
02337 // nested drdpa ticket locks
02338 //
02339 
02340 void
02341 __kmp_acquire_nested_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02342 {
02343     KMP_DEBUG_ASSERT( gtid >= 0 );
02344 
02345     if ( __kmp_get_drdpa_lock_owner( lck ) == gtid ) {
02346         lck->lk.depth_locked += 1;
02347     }
02348     else {
02349         __kmp_acquire_drdpa_lock_timed_template( lck, gtid );
02350         KMP_MB();
02351         lck->lk.depth_locked = 1;
02352         KMP_MB();
02353         lck->lk.owner_id = gtid + 1;
02354     }
02355 }
02356 
02357 static void
02358 __kmp_acquire_nested_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02359 {
02360     if ( __kmp_env_consistency_check ) {
02361         char const * const func = "omp_set_nest_lock";
02362         if ( lck->lk.initialized != lck ) {
02363             KMP_FATAL( LockIsUninitialized, func );
02364         }
02365         if ( ! __kmp_is_drdpa_lock_nestable( lck ) ) {
02366             KMP_FATAL( LockSimpleUsedAsNestable, func );
02367         }
02368     }
02369     __kmp_acquire_nested_drdpa_lock( lck, gtid );
02370 }
02371 
02372 int
02373 __kmp_test_nested_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02374 {
02375     int retval;
02376 
02377     KMP_DEBUG_ASSERT( gtid >= 0 );
02378 
02379     if ( __kmp_get_drdpa_lock_owner( lck ) == gtid ) {
02380         retval = ++lck->lk.depth_locked;
02381     }
02382     else if ( !__kmp_test_drdpa_lock( lck, gtid ) ) {
02383         retval = 0;
02384     }
02385     else {
02386         KMP_MB();
02387         retval = lck->lk.depth_locked = 1;
02388         KMP_MB();
02389         lck->lk.owner_id = gtid + 1;
02390     }
02391     return retval;
02392 }
02393 
02394 static int
02395 __kmp_test_nested_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02396 {
02397     if ( __kmp_env_consistency_check ) {
02398         char const * const func = "omp_test_nest_lock";
02399         if ( lck->lk.initialized != lck ) {
02400             KMP_FATAL( LockIsUninitialized, func );
02401         }
02402         if ( ! __kmp_is_drdpa_lock_nestable( lck ) ) {
02403             KMP_FATAL( LockSimpleUsedAsNestable, func );
02404         }
02405     }
02406     return __kmp_test_nested_drdpa_lock( lck, gtid );
02407 }
02408 
02409 int
02410 __kmp_release_nested_drdpa_lock( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02411 {
02412     KMP_DEBUG_ASSERT( gtid >= 0 );
02413 
02414     KMP_MB();
02415     if ( --(lck->lk.depth_locked) == 0 ) {
02416         KMP_MB();
02417         lck->lk.owner_id = 0;
02418         __kmp_release_drdpa_lock( lck, gtid );
02419     return KMP_NESTED_LOCK_RELEASED;
02420     }
02421     return KMP_NESTED_LOCK_HELD;
02422 }
02423 
02424 static int
02425 __kmp_release_nested_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck, kmp_int32 gtid )
02426 {
02427     if ( __kmp_env_consistency_check ) {
02428         char const * const func = "omp_unset_nest_lock";
02429         KMP_MB();  /* in case another processor initialized lock */
02430         if ( lck->lk.initialized != lck ) {
02431             KMP_FATAL( LockIsUninitialized, func );
02432         }
02433         if ( ! __kmp_is_drdpa_lock_nestable( lck ) ) {
02434             KMP_FATAL( LockSimpleUsedAsNestable, func );
02435         }
02436         if ( __kmp_get_drdpa_lock_owner( lck ) == -1 ) {
02437             KMP_FATAL( LockUnsettingFree, func );
02438         }
02439         if ( __kmp_get_drdpa_lock_owner( lck ) != gtid ) {
02440             KMP_FATAL( LockUnsettingSetByAnother, func );
02441         }
02442     }
02443     return __kmp_release_nested_drdpa_lock( lck, gtid );
02444 }
02445 
02446 void
02447 __kmp_init_nested_drdpa_lock( kmp_drdpa_lock_t * lck )
02448 {
02449     __kmp_init_drdpa_lock( lck );
02450     lck->lk.depth_locked = 0; // >= 0 for nestable locks, -1 for simple locks
02451 }
02452 
02453 static void
02454 __kmp_init_nested_drdpa_lock_with_checks( kmp_drdpa_lock_t * lck )
02455 {
02456     __kmp_init_nested_drdpa_lock( lck );
02457 }
02458 
02459 void
02460 __kmp_destroy_nested_drdpa_lock( kmp_drdpa_lock_t *lck )
02461 {
02462     __kmp_destroy_drdpa_lock( lck );
02463     lck->lk.depth_locked = 0;
02464 }
02465 
02466 static void
02467 __kmp_destroy_nested_drdpa_lock_with_checks( kmp_drdpa_lock_t *lck )
02468 {
02469     if ( __kmp_env_consistency_check ) {
02470         char const * const func = "omp_destroy_nest_lock";
02471         if ( lck->lk.initialized != lck ) {
02472             KMP_FATAL( LockIsUninitialized, func );
02473         }
02474         if ( ! __kmp_is_drdpa_lock_nestable( lck ) ) {
02475             KMP_FATAL( LockSimpleUsedAsNestable, func );
02476         }
02477         if ( __kmp_get_drdpa_lock_owner( lck ) != -1 ) {
02478             KMP_FATAL( LockStillOwned, func );
02479         }
02480     }
02481     __kmp_destroy_nested_drdpa_lock( lck );
02482 }
02483 
02484 
02485 //
02486 // access functions to fields which don't exist for all lock kinds.
02487 //
02488 
02489 static int
02490 __kmp_is_drdpa_lock_initialized( kmp_drdpa_lock_t *lck )
02491 {
02492     return lck == lck->lk.initialized;
02493 }
02494 
02495 static const ident_t *
02496 __kmp_get_drdpa_lock_location( kmp_drdpa_lock_t *lck )
02497 {
02498     return lck->lk.location;
02499 }
02500 
02501 static void
02502 __kmp_set_drdpa_lock_location( kmp_drdpa_lock_t *lck, const ident_t *loc )
02503 {
02504     lck->lk.location = loc;
02505 }
02506 
02507 static kmp_lock_flags_t
02508 __kmp_get_drdpa_lock_flags( kmp_drdpa_lock_t *lck )
02509 {
02510     return lck->lk.flags;
02511 }
02512 
02513 static void
02514 __kmp_set_drdpa_lock_flags( kmp_drdpa_lock_t *lck, kmp_lock_flags_t flags )
02515 {
02516     lck->lk.flags = flags;
02517 }
02518 
02519 /* ------------------------------------------------------------------------ */
02520 /* user locks
02521  *
02522  * They are implemented as a table of function pointers which are set to the
02523  * lock functions of the appropriate kind, once that has been determined.
02524  */
02525 
02526 enum kmp_lock_kind __kmp_user_lock_kind = lk_default;
02527 
02528 size_t __kmp_base_user_lock_size = 0;
02529 size_t __kmp_user_lock_size = 0;
02530 
02531 kmp_int32 ( *__kmp_get_user_lock_owner_ )( kmp_user_lock_p lck ) = NULL;
02532 void ( *__kmp_acquire_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02533 
02534 int ( *__kmp_test_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02535 void ( *__kmp_release_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02536 void ( *__kmp_init_user_lock_with_checks_ )( kmp_user_lock_p lck ) = NULL;
02537 void ( *__kmp_destroy_user_lock_ )( kmp_user_lock_p lck ) = NULL;
02538 void ( *__kmp_destroy_user_lock_with_checks_ )( kmp_user_lock_p lck ) = NULL;
02539 void ( *__kmp_acquire_nested_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02540 
02541 int ( *__kmp_test_nested_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02542 int ( *__kmp_release_nested_user_lock_with_checks_ )( kmp_user_lock_p lck, kmp_int32 gtid ) = NULL;
02543 void ( *__kmp_init_nested_user_lock_with_checks_ )( kmp_user_lock_p lck ) = NULL;
02544 void ( *__kmp_destroy_nested_user_lock_with_checks_ )( kmp_user_lock_p lck ) = NULL;
02545 
02546 int ( *__kmp_is_user_lock_initialized_ )( kmp_user_lock_p lck ) = NULL;
02547 const ident_t * ( *__kmp_get_user_lock_location_ )( kmp_user_lock_p lck ) = NULL;
02548 void ( *__kmp_set_user_lock_location_ )( kmp_user_lock_p lck, const ident_t *loc ) = NULL;
02549 kmp_lock_flags_t ( *__kmp_get_user_lock_flags_ )( kmp_user_lock_p lck ) = NULL;
02550 void ( *__kmp_set_user_lock_flags_ )( kmp_user_lock_p lck, kmp_lock_flags_t flags ) = NULL;
02551 
02552 void __kmp_set_user_lock_vptrs( kmp_lock_kind_t user_lock_kind )
02553 {
02554     switch ( user_lock_kind ) {
02555         case lk_default:
02556         default:
02557         KMP_ASSERT( 0 );
02558 
02559         case lk_tas: {
02560             __kmp_base_user_lock_size = sizeof( kmp_base_tas_lock_t );
02561             __kmp_user_lock_size = sizeof( kmp_tas_lock_t );
02562 
02563             __kmp_get_user_lock_owner_ =
02564               ( kmp_int32 ( * )( kmp_user_lock_p ) )
02565               ( &__kmp_get_tas_lock_owner );
02566 
02567             __kmp_acquire_user_lock_with_checks_ =
02568               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02569               ( &__kmp_acquire_tas_lock_with_checks );
02570 
02571             __kmp_test_user_lock_with_checks_ =
02572               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02573               ( &__kmp_test_tas_lock_with_checks );
02574 
02575             __kmp_release_user_lock_with_checks_ =
02576               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02577               ( &__kmp_release_tas_lock_with_checks );
02578 
02579             __kmp_init_user_lock_with_checks_ =
02580               ( void ( * )( kmp_user_lock_p ) )
02581               ( &__kmp_init_tas_lock_with_checks );
02582 
02583             __kmp_destroy_user_lock_ =
02584               ( void ( * )( kmp_user_lock_p ) )
02585               ( &__kmp_destroy_tas_lock );
02586 
02587             __kmp_destroy_user_lock_with_checks_ =
02588               ( void ( * )( kmp_user_lock_p ) )
02589               ( &__kmp_destroy_tas_lock_with_checks );
02590 
02591             __kmp_acquire_nested_user_lock_with_checks_ =
02592               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02593               ( &__kmp_acquire_nested_tas_lock_with_checks );
02594 
02595             __kmp_test_nested_user_lock_with_checks_ =
02596               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02597               ( &__kmp_test_nested_tas_lock_with_checks );
02598 
02599             __kmp_release_nested_user_lock_with_checks_ =
02600               ( int ( * )( kmp_user_lock_p, kmp_int32 ) )
02601               ( &__kmp_release_nested_tas_lock_with_checks );
02602 
02603             __kmp_init_nested_user_lock_with_checks_ =
02604               ( void ( * )( kmp_user_lock_p ) )
02605               ( &__kmp_init_nested_tas_lock_with_checks );
02606 
02607             __kmp_destroy_nested_user_lock_with_checks_ =
02608               ( void ( * )( kmp_user_lock_p ) )
02609               ( &__kmp_destroy_nested_tas_lock_with_checks );
02610 
02611              __kmp_is_user_lock_initialized_ =
02612                ( int ( * )( kmp_user_lock_p ) ) NULL;
02613 
02614              __kmp_get_user_lock_location_ =
02615                ( const ident_t * ( * )( kmp_user_lock_p ) ) NULL;
02616 
02617              __kmp_set_user_lock_location_ =
02618                ( void ( * )( kmp_user_lock_p, const ident_t * ) ) NULL;
02619 
02620              __kmp_get_user_lock_flags_ =
02621                ( kmp_lock_flags_t ( * )( kmp_user_lock_p ) ) NULL;
02622 
02623              __kmp_set_user_lock_flags_ =
02624                ( void ( * )( kmp_user_lock_p, kmp_lock_flags_t ) ) NULL;
02625         }
02626         break;
02627 
02628 #if KMP_OS_LINUX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
02629 
02630         case lk_futex: {
02631             __kmp_base_user_lock_size = sizeof( kmp_base_futex_lock_t );
02632             __kmp_user_lock_size = sizeof( kmp_futex_lock_t );
02633 
02634             __kmp_get_user_lock_owner_ =
02635               ( kmp_int32 ( * )( kmp_user_lock_p ) )
02636               ( &__kmp_get_futex_lock_owner );
02637 
02638             __kmp_acquire_user_lock_with_checks_ =
02639               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02640               ( &__kmp_acquire_futex_lock_with_checks );
02641 
02642             __kmp_test_user_lock_with_checks_ =
02643               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02644               ( &__kmp_test_futex_lock_with_checks );
02645 
02646             __kmp_release_user_lock_with_checks_ =
02647               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02648               ( &__kmp_release_futex_lock_with_checks );
02649 
02650             __kmp_init_user_lock_with_checks_ =
02651               ( void ( * )( kmp_user_lock_p ) )
02652               ( &__kmp_init_futex_lock_with_checks );
02653 
02654             __kmp_destroy_user_lock_ =
02655               ( void ( * )( kmp_user_lock_p ) )
02656               ( &__kmp_destroy_futex_lock );
02657 
02658             __kmp_destroy_user_lock_with_checks_ =
02659               ( void ( * )( kmp_user_lock_p ) )
02660               ( &__kmp_destroy_futex_lock_with_checks );
02661 
02662             __kmp_acquire_nested_user_lock_with_checks_ =
02663               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02664               ( &__kmp_acquire_nested_futex_lock_with_checks );
02665 
02666             __kmp_test_nested_user_lock_with_checks_ =
02667               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02668               ( &__kmp_test_nested_futex_lock_with_checks );
02669 
02670             __kmp_release_nested_user_lock_with_checks_ =
02671               ( int ( * )( kmp_user_lock_p, kmp_int32 ) )
02672               ( &__kmp_release_nested_futex_lock_with_checks );
02673 
02674             __kmp_init_nested_user_lock_with_checks_ =
02675               ( void ( * )( kmp_user_lock_p ) )
02676               ( &__kmp_init_nested_futex_lock_with_checks );
02677 
02678             __kmp_destroy_nested_user_lock_with_checks_ =
02679               ( void ( * )( kmp_user_lock_p ) )
02680               ( &__kmp_destroy_nested_futex_lock_with_checks );
02681 
02682              __kmp_is_user_lock_initialized_ =
02683                ( int ( * )( kmp_user_lock_p ) ) NULL;
02684 
02685              __kmp_get_user_lock_location_ =
02686                ( const ident_t * ( * )( kmp_user_lock_p ) ) NULL;
02687 
02688              __kmp_set_user_lock_location_ =
02689                ( void ( * )( kmp_user_lock_p, const ident_t * ) ) NULL;
02690 
02691              __kmp_get_user_lock_flags_ =
02692                ( kmp_lock_flags_t ( * )( kmp_user_lock_p ) ) NULL;
02693 
02694              __kmp_set_user_lock_flags_ =
02695                ( void ( * )( kmp_user_lock_p, kmp_lock_flags_t ) ) NULL;
02696         }
02697         break;
02698 
02699 #endif // KMP_OS_LINUX && (KMP_ARCH_X86 || KMP_ARCH_X86_64)
02700 
02701         case lk_ticket: {
02702             __kmp_base_user_lock_size = sizeof( kmp_base_ticket_lock_t );
02703             __kmp_user_lock_size = sizeof( kmp_ticket_lock_t );
02704 
02705             __kmp_get_user_lock_owner_ =
02706               ( kmp_int32 ( * )( kmp_user_lock_p ) )
02707               ( &__kmp_get_ticket_lock_owner );
02708 
02709             __kmp_acquire_user_lock_with_checks_ =
02710               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02711               ( &__kmp_acquire_ticket_lock_with_checks );
02712 
02713             __kmp_test_user_lock_with_checks_ =
02714               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02715               ( &__kmp_test_ticket_lock_with_checks );
02716 
02717             __kmp_release_user_lock_with_checks_ =
02718               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02719               ( &__kmp_release_ticket_lock_with_checks );
02720 
02721             __kmp_init_user_lock_with_checks_ =
02722               ( void ( * )( kmp_user_lock_p ) )
02723               ( &__kmp_init_ticket_lock_with_checks );
02724 
02725             __kmp_destroy_user_lock_ =
02726               ( void ( * )( kmp_user_lock_p ) )
02727               ( &__kmp_destroy_ticket_lock );
02728 
02729             __kmp_destroy_user_lock_with_checks_ =
02730               ( void ( * )( kmp_user_lock_p ) )
02731               ( &__kmp_destroy_ticket_lock_with_checks );
02732 
02733             __kmp_acquire_nested_user_lock_with_checks_ =
02734               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02735               ( &__kmp_acquire_nested_ticket_lock_with_checks );
02736 
02737             __kmp_test_nested_user_lock_with_checks_ =
02738               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02739               ( &__kmp_test_nested_ticket_lock_with_checks );
02740 
02741             __kmp_release_nested_user_lock_with_checks_ =
02742               ( int ( * )( kmp_user_lock_p, kmp_int32 ) )
02743               ( &__kmp_release_nested_ticket_lock_with_checks );
02744 
02745             __kmp_init_nested_user_lock_with_checks_ =
02746               ( void ( * )( kmp_user_lock_p ) )
02747               ( &__kmp_init_nested_ticket_lock_with_checks );
02748 
02749             __kmp_destroy_nested_user_lock_with_checks_ =
02750               ( void ( * )( kmp_user_lock_p ) )
02751               ( &__kmp_destroy_nested_ticket_lock_with_checks );
02752 
02753              __kmp_is_user_lock_initialized_ =
02754                ( int ( * )( kmp_user_lock_p ) )
02755                ( &__kmp_is_ticket_lock_initialized );
02756 
02757              __kmp_get_user_lock_location_ =
02758                ( const ident_t * ( * )( kmp_user_lock_p ) )
02759                ( &__kmp_get_ticket_lock_location );
02760 
02761              __kmp_set_user_lock_location_ =
02762                ( void ( * )( kmp_user_lock_p, const ident_t * ) )
02763                ( &__kmp_set_ticket_lock_location );
02764 
02765              __kmp_get_user_lock_flags_ =
02766                ( kmp_lock_flags_t ( * )( kmp_user_lock_p ) )
02767                ( &__kmp_get_ticket_lock_flags );
02768 
02769              __kmp_set_user_lock_flags_ =
02770                ( void ( * )( kmp_user_lock_p, kmp_lock_flags_t ) )
02771                ( &__kmp_set_ticket_lock_flags );
02772         }
02773         break;
02774 
02775         case lk_queuing: {
02776             __kmp_base_user_lock_size = sizeof( kmp_base_queuing_lock_t );
02777             __kmp_user_lock_size = sizeof( kmp_queuing_lock_t );
02778 
02779             __kmp_get_user_lock_owner_ =
02780               ( kmp_int32 ( * )( kmp_user_lock_p ) )
02781               ( &__kmp_get_queuing_lock_owner );
02782 
02783             __kmp_acquire_user_lock_with_checks_ =
02784               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02785               ( &__kmp_acquire_queuing_lock_with_checks );
02786 
02787             __kmp_test_user_lock_with_checks_ =
02788               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02789               ( &__kmp_test_queuing_lock_with_checks );
02790 
02791             __kmp_release_user_lock_with_checks_ =
02792               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02793               ( &__kmp_release_queuing_lock_with_checks );
02794 
02795             __kmp_init_user_lock_with_checks_ =
02796               ( void ( * )( kmp_user_lock_p ) )
02797               ( &__kmp_init_queuing_lock_with_checks );
02798 
02799             __kmp_destroy_user_lock_ =
02800               ( void ( * )( kmp_user_lock_p ) )
02801               ( &__kmp_destroy_queuing_lock );
02802 
02803             __kmp_destroy_user_lock_with_checks_ =
02804               ( void ( * )( kmp_user_lock_p ) )
02805               ( &__kmp_destroy_queuing_lock_with_checks );
02806 
02807             __kmp_acquire_nested_user_lock_with_checks_ =
02808               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02809               ( &__kmp_acquire_nested_queuing_lock_with_checks );
02810 
02811             __kmp_test_nested_user_lock_with_checks_ =
02812               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02813               ( &__kmp_test_nested_queuing_lock_with_checks );
02814 
02815             __kmp_release_nested_user_lock_with_checks_ =
02816               ( int ( * )( kmp_user_lock_p, kmp_int32 ) )
02817               ( &__kmp_release_nested_queuing_lock_with_checks );
02818 
02819             __kmp_init_nested_user_lock_with_checks_ =
02820               ( void ( * )( kmp_user_lock_p ) )
02821               ( &__kmp_init_nested_queuing_lock_with_checks );
02822 
02823             __kmp_destroy_nested_user_lock_with_checks_ =
02824               ( void ( * )( kmp_user_lock_p ) )
02825               ( &__kmp_destroy_nested_queuing_lock_with_checks );
02826 
02827              __kmp_is_user_lock_initialized_ =
02828                ( int ( * )( kmp_user_lock_p ) )
02829                ( &__kmp_is_queuing_lock_initialized );
02830 
02831              __kmp_get_user_lock_location_ =
02832                ( const ident_t * ( * )( kmp_user_lock_p ) )
02833                ( &__kmp_get_queuing_lock_location );
02834 
02835              __kmp_set_user_lock_location_ =
02836                ( void ( * )( kmp_user_lock_p, const ident_t * ) )
02837                ( &__kmp_set_queuing_lock_location );
02838 
02839              __kmp_get_user_lock_flags_ =
02840                ( kmp_lock_flags_t ( * )( kmp_user_lock_p ) )
02841                ( &__kmp_get_queuing_lock_flags );
02842 
02843              __kmp_set_user_lock_flags_ =
02844                ( void ( * )( kmp_user_lock_p, kmp_lock_flags_t ) )
02845                ( &__kmp_set_queuing_lock_flags );
02846         }
02847         break;
02848 
02849         case lk_drdpa: {
02850             __kmp_base_user_lock_size = sizeof( kmp_base_drdpa_lock_t );
02851             __kmp_user_lock_size = sizeof( kmp_drdpa_lock_t );
02852 
02853             __kmp_get_user_lock_owner_ =
02854               ( kmp_int32 ( * )( kmp_user_lock_p ) )
02855               ( &__kmp_get_drdpa_lock_owner );
02856 
02857             __kmp_acquire_user_lock_with_checks_ =
02858               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02859               ( &__kmp_acquire_drdpa_lock_with_checks );
02860 
02861             __kmp_test_user_lock_with_checks_ =
02862               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02863               ( &__kmp_test_drdpa_lock_with_checks );
02864 
02865             __kmp_release_user_lock_with_checks_ =
02866               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02867               ( &__kmp_release_drdpa_lock_with_checks );
02868 
02869             __kmp_init_user_lock_with_checks_ =
02870               ( void ( * )( kmp_user_lock_p ) )
02871               ( &__kmp_init_drdpa_lock_with_checks );
02872 
02873             __kmp_destroy_user_lock_ =
02874               ( void ( * )( kmp_user_lock_p ) )
02875               ( &__kmp_destroy_drdpa_lock );
02876 
02877             __kmp_destroy_user_lock_with_checks_ =
02878               ( void ( * )( kmp_user_lock_p ) )
02879               ( &__kmp_destroy_drdpa_lock_with_checks );
02880 
02881             __kmp_acquire_nested_user_lock_with_checks_ =
02882               ( void ( * )( kmp_user_lock_p, kmp_int32 ) )
02883               ( &__kmp_acquire_nested_drdpa_lock_with_checks );
02884 
02885             __kmp_test_nested_user_lock_with_checks_ =
02886               ( int  ( * )( kmp_user_lock_p, kmp_int32 ) )
02887               ( &__kmp_test_nested_drdpa_lock_with_checks );
02888 
02889             __kmp_release_nested_user_lock_with_checks_ =
02890               ( int ( * )( kmp_user_lock_p, kmp_int32 ) )
02891               ( &__kmp_release_nested_drdpa_lock_with_checks );
02892 
02893             __kmp_init_nested_user_lock_with_checks_ =
02894               ( void ( * )( kmp_user_lock_p ) )
02895               ( &__kmp_init_nested_drdpa_lock_with_checks );
02896 
02897             __kmp_destroy_nested_user_lock_with_checks_ =
02898               ( void ( * )( kmp_user_lock_p ) )
02899               ( &__kmp_destroy_nested_drdpa_lock_with_checks );
02900 
02901              __kmp_is_user_lock_initialized_ =
02902                ( int ( * )( kmp_user_lock_p ) )
02903                ( &__kmp_is_drdpa_lock_initialized );
02904 
02905              __kmp_get_user_lock_location_ =
02906                ( const ident_t * ( * )( kmp_user_lock_p ) )
02907                ( &__kmp_get_drdpa_lock_location );
02908 
02909              __kmp_set_user_lock_location_ =
02910                ( void ( * )( kmp_user_lock_p, const ident_t * ) )
02911                ( &__kmp_set_drdpa_lock_location );
02912 
02913              __kmp_get_user_lock_flags_ =
02914                ( kmp_lock_flags_t ( * )( kmp_user_lock_p ) )
02915                ( &__kmp_get_drdpa_lock_flags );
02916 
02917              __kmp_set_user_lock_flags_ =
02918                ( void ( * )( kmp_user_lock_p, kmp_lock_flags_t ) )
02919                ( &__kmp_set_drdpa_lock_flags );
02920         }
02921         break;
02922     }
02923 }
02924 
02925 
02926 // ----------------------------------------------------------------------------
02927 // User lock table & lock allocation
02928 
02929 kmp_lock_table_t __kmp_user_lock_table = { 1, 0, NULL };
02930 kmp_user_lock_p __kmp_lock_pool = NULL;
02931 
02932 // Lock block-allocation support.
02933 kmp_block_of_locks* __kmp_lock_blocks = NULL;
02934 int __kmp_num_locks_in_block = 1;             // FIXME - tune this value
02935 
02936 static kmp_lock_index_t
02937 __kmp_lock_table_insert( kmp_user_lock_p lck )
02938 {
02939     // Assume that kmp_global_lock is held upon entry/exit.
02940     kmp_lock_index_t index;
02941     if ( __kmp_user_lock_table.used >= __kmp_user_lock_table.allocated ) {
02942         kmp_lock_index_t size;
02943         kmp_user_lock_p *table;
02944         kmp_lock_index_t i;
02945         // Reallocate lock table.
02946         if ( __kmp_user_lock_table.allocated == 0 ) {
02947             size = 1024;
02948         }
02949         else {
02950             size = __kmp_user_lock_table.allocated * 2;
02951         }
02952         table = (kmp_user_lock_p *)__kmp_allocate( sizeof( kmp_user_lock_p ) * size );
02953         memcpy( table + 1, __kmp_user_lock_table.table + 1, sizeof( kmp_user_lock_p ) * ( __kmp_user_lock_table.used - 1 ) );
02954         table[ 0 ] = (kmp_user_lock_p)__kmp_user_lock_table.table;
02955             // We cannot free the previos table now, sinse it may be in use by other
02956             // threads. So save the pointer to the previous table in in the first element of the
02957             // new table. All the tables will be organized into a list, and could be freed when
02958             // library shutting down.
02959         __kmp_user_lock_table.table = table;
02960         __kmp_user_lock_table.allocated = size;
02961     }
02962     KMP_DEBUG_ASSERT( __kmp_user_lock_table.used < __kmp_user_lock_table.allocated );
02963     index = __kmp_user_lock_table.used;
02964     __kmp_user_lock_table.table[ index ] = lck;
02965     ++ __kmp_user_lock_table.used;
02966     return index;
02967 }
02968 
02969 static kmp_user_lock_p
02970 __kmp_lock_block_allocate()
02971 {
02972     // Assume that kmp_global_lock is held upon entry/exit.
02973     static int last_index = 0;
02974     if ( ( last_index >= __kmp_num_locks_in_block )
02975       || ( __kmp_lock_blocks == NULL ) ) {
02976         // Restart the index.
02977         last_index = 0;
02978         // Need to allocate a new block.
02979         KMP_DEBUG_ASSERT( __kmp_user_lock_size > 0 );
02980         size_t space_for_locks = __kmp_user_lock_size * __kmp_num_locks_in_block;
02981         char* buffer = (char*)__kmp_allocate( space_for_locks + sizeof( kmp_block_of_locks ) );
02982         // Set up the new block.
02983         kmp_block_of_locks *new_block = (kmp_block_of_locks *)(& buffer[space_for_locks]);
02984         new_block->next_block = __kmp_lock_blocks;
02985         new_block->locks = (void *)buffer;
02986         // Publish the new block.
02987         KMP_MB();
02988         __kmp_lock_blocks = new_block;
02989     }
02990     kmp_user_lock_p ret = (kmp_user_lock_p)(& ( ( (char *)( __kmp_lock_blocks->locks ) )
02991       [ last_index * __kmp_user_lock_size ] ) );
02992     last_index++;
02993     return ret;
02994 }
02995 
02996 //
02997 // Get memory for a lock. It may be freshly allocated memory or reused memory
02998 // from lock pool.
02999 //
03000 kmp_user_lock_p
03001 __kmp_user_lock_allocate( void **user_lock, kmp_int32 gtid,
03002   kmp_lock_flags_t flags )
03003 {
03004     kmp_user_lock_p lck;
03005     kmp_lock_index_t index;
03006     KMP_DEBUG_ASSERT( user_lock );
03007 
03008     __kmp_acquire_lock( &__kmp_global_lock, gtid );
03009 
03010     if ( __kmp_lock_pool == NULL ) {
03011         // Lock pool is empty. Allocate new memory.
03012         if ( __kmp_num_locks_in_block <= 1 ) { // Tune this cutoff point.
03013             lck = (kmp_user_lock_p) __kmp_allocate( __kmp_user_lock_size );
03014         }
03015         else {
03016             lck = __kmp_lock_block_allocate();
03017         }
03018 
03019         // Insert lock in the table so that it can be freed in __kmp_cleanup,
03020         // and debugger has info on all allocated locks.
03021         index = __kmp_lock_table_insert( lck );
03022     }
03023     else {
03024         // Pick up lock from pool.
03025         lck = __kmp_lock_pool;
03026         index = __kmp_lock_pool->pool.index;
03027         __kmp_lock_pool = __kmp_lock_pool->pool.next;
03028     }
03029 
03030     //
03031     // We could potentially differentiate between nested and regular locks
03032     // here, and do the lock table lookup for regular locks only.
03033     //
03034     if ( OMP_LOCK_T_SIZE < sizeof(void *) ) {
03035         * ( (kmp_lock_index_t *) user_lock ) = index;
03036     }
03037     else {
03038         * ( (kmp_user_lock_p *) user_lock ) = lck;
03039     }
03040 
03041     // mark the lock if it is critical section lock.
03042     __kmp_set_user_lock_flags( lck, flags );
03043 
03044     __kmp_release_lock( & __kmp_global_lock, gtid ); // AC: TODO: move this line upper
03045 
03046     return lck;
03047 }
03048 
03049 // Put lock's memory to pool for reusing.
03050 void
03051 __kmp_user_lock_free( void **user_lock, kmp_int32 gtid, kmp_user_lock_p lck )
03052 {
03053     kmp_lock_pool_t * lock_pool;
03054 
03055     KMP_DEBUG_ASSERT( user_lock != NULL );
03056     KMP_DEBUG_ASSERT( lck != NULL );
03057 
03058     __kmp_acquire_lock( & __kmp_global_lock, gtid );
03059 
03060     lck->pool.next = __kmp_lock_pool;
03061     __kmp_lock_pool = lck;
03062     if ( OMP_LOCK_T_SIZE < sizeof(void *) ) {
03063         kmp_lock_index_t index = * ( (kmp_lock_index_t *) user_lock );
03064         KMP_DEBUG_ASSERT( 0 < index && index <= __kmp_user_lock_table.used );
03065         lck->pool.index = index;
03066     }
03067 
03068     __kmp_release_lock( & __kmp_global_lock, gtid );
03069 }
03070 
03071 kmp_user_lock_p
03072 __kmp_lookup_user_lock( void **user_lock, char const *func )
03073 {
03074     kmp_user_lock_p lck = NULL;
03075 
03076     if ( __kmp_env_consistency_check ) {
03077         if ( user_lock == NULL ) {
03078             KMP_FATAL( LockIsUninitialized, func );
03079         }
03080     }
03081 
03082     if ( OMP_LOCK_T_SIZE < sizeof(void *) ) {
03083         kmp_lock_index_t index = *( (kmp_lock_index_t *)user_lock );
03084         if ( __kmp_env_consistency_check ) {
03085             if ( ! ( 0 < index && index < __kmp_user_lock_table.used ) ) {
03086                 KMP_FATAL( LockIsUninitialized, func );
03087             }
03088         }
03089         KMP_DEBUG_ASSERT( 0 < index && index < __kmp_user_lock_table.used );
03090         KMP_DEBUG_ASSERT( __kmp_user_lock_size > 0 );
03091         lck = __kmp_user_lock_table.table[index];
03092     }
03093     else {
03094         lck = *( (kmp_user_lock_p *)user_lock );
03095     }
03096 
03097     if ( __kmp_env_consistency_check ) {
03098         if ( lck == NULL ) {
03099             KMP_FATAL( LockIsUninitialized, func );
03100         }
03101     }
03102 
03103     return lck;
03104 }
03105 
03106 void
03107 __kmp_cleanup_user_locks( void )
03108 {
03109     //
03110     // Reset lock pool. Do not worry about lock in the pool -- we will free
03111     // them when iterating through lock table (it includes all the locks,
03112     // dead or alive).
03113     //
03114     __kmp_lock_pool = NULL;
03115 
03116 #define IS_CRITICAL(lck) \
03117         ( ( __kmp_get_user_lock_flags_ != NULL ) && \
03118         ( ( *__kmp_get_user_lock_flags_ )( lck ) & kmp_lf_critical_section ) )
03119 
03120     //
03121     // Loop through lock table, free all locks.
03122     //
03123     // Do not free item [0], it is reserved for lock tables list.
03124     //
03125     // FIXME - we are iterating through a list of (pointers to) objects of
03126     // type union kmp_user_lock, but we have no way of knowing whether the
03127     // base type is currently "pool" or whatever the global user lock type
03128     // is.
03129     //
03130     // We are relying on the fact that for all of the user lock types
03131     // (except "tas"), the first field in the lock struct is the "initialized"
03132     // field, which is set to the address of the lock object itself when
03133     // the lock is initialized.  When the union is of type "pool", the
03134     // first field is a pointer to the next object in the free list, which
03135     // will not be the same address as the object itself.
03136     //
03137     // This means that the check ( *__kmp_is_user_lock_initialized_ )( lck )
03138     // will fail for "pool" objects on the free list.  This must happen as
03139     // the "location" field of real user locks overlaps the "index" field
03140     // of "pool" objects.
03141     //
03142     // It would be better to run through the free list, and remove all "pool"
03143     // objects from the lock table before executing this loop.  However,
03144     // "pool" objects do not always have their index field set (only on
03145     // lin_32e), and I don't want to search the lock table for the address
03146     // of every "pool" object on the free list.
03147     //
03148     while ( __kmp_user_lock_table.used > 1 ) {
03149         const ident *loc;
03150 
03151         //
03152         // reduce __kmp_user_lock_table.used before freeing the lock,
03153         // so that state of locks is consistent
03154         //
03155         kmp_user_lock_p lck = __kmp_user_lock_table.table[
03156           --__kmp_user_lock_table.used ];
03157 
03158         if ( ( __kmp_is_user_lock_initialized_ != NULL ) &&
03159           ( *__kmp_is_user_lock_initialized_ )( lck ) ) {
03160             //
03161             // Issue a warning if: KMP_CONSISTENCY_CHECK AND lock is
03162             // initialized AND it is NOT a critical section (user is not
03163             // responsible for destroying criticals) AND we know source
03164             // location to report.
03165             //
03166             if ( __kmp_env_consistency_check && ( ! IS_CRITICAL( lck ) ) &&
03167               ( ( loc = __kmp_get_user_lock_location( lck ) ) != NULL ) &&
03168               ( loc->psource != NULL ) ) {
03169                 kmp_str_loc_t str_loc = __kmp_str_loc_init( loc->psource, 0 );
03170                 KMP_WARNING( CnsLockNotDestroyed, str_loc.file, str_loc.func,
03171                   str_loc.line, str_loc.col );
03172                 __kmp_str_loc_free( &str_loc);
03173             }
03174 
03175 #ifdef KMP_DEBUG
03176             if ( IS_CRITICAL( lck ) ) {
03177                 KA_TRACE( 20, ("__kmp_cleanup_user_locks: free critical section lock %p (%p)\n", lck, *(void**)lck ) );
03178             }
03179             else {
03180                 KA_TRACE( 20, ("__kmp_cleanup_user_locks: free lock %p (%p)\n", lck, *(void**)lck ) );
03181             }
03182 #endif // KMP_DEBUG
03183 
03184             //
03185             // Cleanup internal lock dynamic resources
03186             // (for drdpa locks particularly).
03187             //
03188             __kmp_destroy_user_lock( lck );
03189         }
03190 
03191         //
03192         // Free the lock if block allocation of locks is not used.
03193         //
03194         if ( __kmp_lock_blocks == NULL ) {
03195             __kmp_free( lck );
03196         }
03197     }
03198 
03199 #undef IS_CRITICAL
03200 
03201     //
03202     // delete lock table(s).
03203     //
03204     kmp_user_lock_p *table_ptr = __kmp_user_lock_table.table;
03205     __kmp_user_lock_table.table = NULL;
03206     __kmp_user_lock_table.allocated = 0;
03207 
03208     while ( table_ptr != NULL ) {
03209         //
03210         // In the first element we saved the pointer to the previous
03211         // (smaller) lock table.
03212         //
03213         kmp_user_lock_p *next = (kmp_user_lock_p *)( table_ptr[ 0 ] );
03214         __kmp_free( table_ptr );
03215         table_ptr = next;
03216     }
03217 
03218     //
03219     // Free buffers allocated for blocks of locks.
03220     //
03221     kmp_block_of_locks_t *block_ptr = __kmp_lock_blocks;
03222     __kmp_lock_blocks = NULL;
03223 
03224     while ( block_ptr != NULL ) {
03225         kmp_block_of_locks_t *next = block_ptr->next_block;
03226         __kmp_free( block_ptr->locks );
03227         //
03228         // *block_ptr itself was allocated at the end of the locks vector.
03229         //
03230     block_ptr = next;
03231     }
03232 
03233     TCW_4(__kmp_init_user_locks, FALSE);
03234 }
03235 

Generated on 25 Aug 2013 for libomp_oss by  doxygen 1.6.1