00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
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
00058
00059
00060
00061
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 )
00073 #else
00074
00075 static void
00076 __kmp_static_delay( int arg )
00077 {
00078
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
00086
00087 static void
00088 __kmp_static_yield( int arg )
00089 {
00090 __kmp_yield( arg );
00091 }
00092
00093
00094
00095
00096 void
00097 __kmp_validate_locks( void )
00098 {
00099 int i;
00100 kmp_uint32 x, y;
00101
00102
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
00117
00118
00119
00120
00121
00122
00123
00124
00125
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
00150 #endif
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
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();
00229
00230 TCW_4( lck->lk.poll, 0 );
00231
00232 KMP_MB();
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();
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
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();
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;
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
00428
00429
00430
00431
00432
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
00458 #endif
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
00472
00473
00474
00475
00476
00477
00478 if ( ! cond ) {
00479
00480
00481
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
00510
00511
00512
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();
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();
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();
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
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();
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;
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
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
00822 #endif
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();
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();
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();
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;
00942 lck->lk.depth_locked = -1;
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
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();
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;
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
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
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222 #ifdef DEBUG_QUEUING_LOCKS
01223
01224
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
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
01282 template <bool takeTime>
01283
01284
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
01316
01317
01318
01319
01320
01321
01322 *spin_here_p = TRUE;
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;
01340
01341
01342
01343
01344 need_mf = 0;
01345
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
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:
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
01388
01389
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
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;
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
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
01432 }
01433 KA_TRACE( 1000, ("__kmp_acquire_queuing_lock: lck:%p, T#%d waiting for lock\n", lck, gtid ));
01434
01435
01436
01437
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
01458 this_thr->th.ompt_thread_info.state = prev_state;
01459 this_thr->th.ompt_thread_info.wait_id = 0;
01460 #endif
01461
01462
01463 return;
01464 }
01465
01466
01467
01468
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 ) {
01531
01532
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 );
01600
01601 if ( head == -1 ) {
01602
01603
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
01613 #endif
01614
01615 return;
01616 }
01617 dequeued = FALSE;
01618
01619 }
01620 else {
01621
01622 tail = *tail_id_p;
01623 if ( head == tail ) {
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
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
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
01651
01652 KMP_MB();
01653
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
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
01673
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
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
01692
01693 #ifdef DEBUG_QUEUING_LOCKS
01694 TRACE_LOCK( gtid+1, "rel retry" );
01695 #endif
01696
01697 }
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();
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;
01734 lck->lk.depth_locked = -1;
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
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();
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;
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
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
01964
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);
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);
01986
01987 #ifdef USE_LOCK_PROFILE
01988 if (TCR_8(polls[ticket & mask].poll) != ticket)
01989 __kmp_printf("LOCK CONTENTION: %p\n", lck);
01990
01991 #endif
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003 kmp_uint32 spins;
02004 KMP_INIT_YIELD(spins);
02005 while (TCR_8(polls[ticket & mask]).poll < ticket) {
02006 __kmp_static_delay(TRUE);
02007
02008
02009
02010
02011
02012
02013 KMP_YIELD(TCR_4(__kmp_nth)
02014 > (__kmp_avail_proc ? __kmp_avail_proc : __kmp_xproc));
02015 KMP_YIELD_SPIN(spins);
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026 mask = TCR_8(lck->lk.mask);
02027 polls = (volatile struct kmp_base_drdpa_lock::kmp_lock_poll *)
02028 TCR_PTR(lck->lk.polls);
02029 }
02030
02031
02032
02033
02034 KA_TRACE(1000, ("__kmp_acquire_drdpa_lock: ticket #%lld acquired lock %p\n",
02035 ticket, lck));
02036 lck->lk.now_serving = ticket;
02037
02038
02039
02040
02041
02042
02043
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
02053
02054
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
02065
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
02080
02081
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
02094
02095
02096
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
02110
02111
02112
02113
02114
02115
02116
02117
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;
02123 lck->lk.polls = polls;
02124
02125 KMP_MB();
02126
02127 lck->lk.num_polls = num_polls;
02128 lck->lk.mask = mask;
02129
02130 KMP_MB();
02131
02132
02133
02134
02135
02136
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
02177
02178
02179 kmp_uint64 ticket = TCR_8(lck->lk.next_ticket);
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);
02183 kmp_uint64 mask = TCR_8(lck->lk.mask);
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;
02191
02192
02193
02194
02195
02196
02197
02198
02199
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
02233
02234
02235
02236 kmp_uint64 ticket = lck->lk.now_serving + 1;
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);
02240 kmp_uint64 mask = TCR_8(lck->lk.mask);
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);
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();
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;
02283 lck->lk.depth_locked = -1;
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
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();
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;
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
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
02521
02522
02523
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
02928
02929 kmp_lock_table_t __kmp_user_lock_table = { 1, 0, NULL };
02930 kmp_user_lock_p __kmp_lock_pool = NULL;
02931
02932
02933 kmp_block_of_locks* __kmp_lock_blocks = NULL;
02934 int __kmp_num_locks_in_block = 1;
02935
02936 static kmp_lock_index_t
02937 __kmp_lock_table_insert( kmp_user_lock_p lck )
02938 {
02939
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
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
02956
02957
02958
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
02973 static int last_index = 0;
02974 if ( ( last_index >= __kmp_num_locks_in_block )
02975 || ( __kmp_lock_blocks == NULL ) ) {
02976
02977 last_index = 0;
02978
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
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
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
02998
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
03012 if ( __kmp_num_locks_in_block <= 1 ) {
03013 lck = (kmp_user_lock_p) __kmp_allocate( __kmp_user_lock_size );
03014 }
03015 else {
03016 lck = __kmp_lock_block_allocate();
03017 }
03018
03019
03020
03021 index = __kmp_lock_table_insert( lck );
03022 }
03023 else {
03024
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
03032
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
03042 __kmp_set_user_lock_flags( lck, flags );
03043
03044 __kmp_release_lock( & __kmp_global_lock, gtid );
03045
03046 return lck;
03047 }
03048
03049
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
03111
03112
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
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148 while ( __kmp_user_lock_table.used > 1 ) {
03149 const ident *loc;
03150
03151
03152
03153
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
03162
03163
03164
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
03186
03187
03188 __kmp_destroy_user_lock( lck );
03189 }
03190
03191
03192
03193
03194 if ( __kmp_lock_blocks == NULL ) {
03195 __kmp_free( lck );
03196 }
03197 }
03198
03199 #undef IS_CRITICAL
03200
03201
03202
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
03211
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
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
03229
03230 block_ptr = next;
03231 }
03232
03233 TCW_4(__kmp_init_user_locks, FALSE);
03234 }
03235