@@ -665,6 +665,74 @@ int API_FUNC qthread_empty(const aligned_t *dest)
665
665
return QTHREAD_SUCCESS ;
666
666
} /*}}} */
667
667
668
+ int INTERNAL qthread_feb_adr_init (const aligned_t * dest , const bool is_from_recursive_lock )
669
+ { /*{{{ */
670
+ const aligned_t * alignedaddr ;
671
+
672
+ if (qlib == NULL ) {
673
+ return QTHREAD_SUCCESS ;
674
+ }
675
+ qthread_addrstat_t * m ;
676
+ const int lockbin = QTHREAD_CHOOSE_STRIPE2 (dest );
677
+ qthread_shepherd_t * shep = qthread_internal_getshep ();
678
+
679
+ assert (qthread_library_initialized );
680
+
681
+ if (!shep ) {
682
+ return qthread_feb_blocker_func ((void * )dest , NULL , FILL /*!!!!!!!XXX!!!*/ );
683
+ }
684
+ qthread_debug (FEB_CALLS , "dest=%p (tid=%i)\n" , dest , qthread_id ());
685
+ QALIGN (dest , alignedaddr );
686
+ /* lock hash */
687
+ QTHREAD_COUNT_THREADS_BINCOUNTER (febs , lockbin );
688
+ #ifdef LOCK_FREE_FEBS
689
+ do {
690
+ m = qt_hash_get (FEBs [lockbin ], (void * )alignedaddr );
691
+ if (m ) {
692
+ return QTHREAD_NOT_ALLOWED ;
693
+ } else {
694
+ if (is_from_recursive_lock ) {
695
+ m = qthread_addrstat_new ();
696
+ if (!m ) { return QTHREAD_MALLOC_ERROR ; }
697
+ m -> full = 1 ;
698
+ m -> acq_owner_stat .state = FEB_is_recursive_lock ;
699
+ MACHINE_FENCE ;
700
+
701
+ if (!qt_hash_put (FEBs [lockbin ], (void * )alignedaddr , m )) {
702
+ qthread_addrstat_delete (m );
703
+ continue ;
704
+ }
705
+ }
706
+ /* already full */
707
+ break ;
708
+ }
709
+ } while (1 );
710
+ #else /* ifdef LOCK_FREE_FEBS */
711
+ qt_hash_lock (FEBs [lockbin ]);
712
+ { /* BEGIN CRITICAL SECTION */
713
+ m = (qthread_addrstat_t * )qt_hash_get_locked (FEBs [lockbin ], (void * )alignedaddr );
714
+ if (m ) {
715
+ return QTHREAD_NOT_ALLOWED ;
716
+ } else {
717
+ if (is_from_recursive_lock ) {
718
+ m = qthread_addrstat_new ();
719
+ if (!m ) { return QTHREAD_MALLOC_ERROR ; }
720
+ m -> full = 1 ;
721
+ m -> acq_owner_stat .state = FEB_is_recursive_lock ;
722
+ MACHINE_FENCE ;
723
+
724
+ if (!qt_hash_put_locked (FEBs [lockbin ], (void * )alignedaddr , m )){
725
+ qthread_addrstat_delete (m );
726
+ return QTHREAD_MALLOC_ERROR ;
727
+ }
728
+ }
729
+ }
730
+ } /* END CRITICAL SECTION */
731
+ qt_hash_unlock (FEBs [lockbin ]); /* unlock hash */
732
+ #endif /* ifdef LOCK_FREE_FEBS */
733
+ return QTHREAD_SUCCESS ;
734
+ } /*}}} */
735
+
668
736
int API_FUNC qthread_fill (const aligned_t * dest )
669
737
{ /*{{{ */
670
738
const aligned_t * alignedaddr ;
@@ -708,11 +776,22 @@ int API_FUNC qthread_fill(const aligned_t *dest)
708
776
m = (qthread_addrstat_t * )qt_hash_get_locked (FEBs [lockbin ], (void * )alignedaddr );
709
777
if (m ) {
710
778
QTHREAD_FASTLOCK_LOCK (& m -> lock );
779
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
780
+ -- m -> acq_owner_stat .recursive_access_counter ;
781
+ }
711
782
}
712
783
} /* END CRITICAL SECTION */
713
784
qt_hash_unlock (FEBs [lockbin ]); /* unlock hash */
714
785
#endif /* ifdef LOCK_FREE_FEBS */
715
786
if (m ) {
787
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
788
+ -- m -> acq_owner_stat .recursive_access_counter ;
789
+ if (m -> acq_owner_stat .recursive_access_counter > 0 ){
790
+ qthread_debug (FEB_BEHAVIOR , "dest=%p (tid=%i): decrementing recursive_access_counter\n" , dest , qthread_id ());
791
+ return QTHREAD_SUCCESS ;
792
+ }
793
+ m -> acq_owner_stat .state = FEB_is_recursive_lock ; //reset
794
+ }
716
795
/* if dest wasn't in the hash, it was already full. Since it was,
717
796
* we need to fill it. */
718
797
qthread_debug (FEB_BEHAVIOR , "dest=%p (tid=%i): filling, maybe alerting waiters\n" , dest , qthread_id ());
@@ -785,6 +864,7 @@ int API_FUNC qthread_writeF(aligned_t *restrict dest,
785
864
return QTHREAD_SUCCESS ;
786
865
} /*}}} */
787
866
867
+
788
868
int API_FUNC qthread_writeF_const (aligned_t * dest ,
789
869
aligned_t src )
790
870
{ /*{{{ */
@@ -1357,6 +1437,7 @@ int API_FUNC qthread_readFF_nb(aligned_t *restrict dest,
1357
1437
return QTHREAD_SUCCESS ;
1358
1438
} /*}}} */
1359
1439
1440
+
1360
1441
/* the way this works is that:
1361
1442
* 1 - src's FEB state must be "full"
1362
1443
* 2 - data is copied from src to destination
@@ -1436,7 +1517,17 @@ int API_FUNC qthread_readFE(aligned_t *restrict dest,
1436
1517
assert (m );
1437
1518
qthread_debug (FEB_DETAILS , "data structure locked\n" );
1438
1519
/* by this point m is locked */
1439
- if (m -> full == 0 ) { /* empty, thus, we must block */
1520
+ if (m -> full == 0 ) { /* empty, thus, we must block */
1521
+ /* unless read_FE was taken by qthread_lock() */
1522
+ /* on same thread */
1523
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
1524
+ if (m -> acq_owner_stat .state == qthread_id ()) {
1525
+ ++ m -> acq_owner_stat .recursive_access_counter ;
1526
+ QTHREAD_FASTLOCK_UNLOCK (& m -> lock );
1527
+ QTHREAD_FEB_TIMER_STOP (febblock , me );
1528
+ return QTHREAD_SUCCESS ;
1529
+ }
1530
+ }
1440
1531
QTHREAD_WAIT_TIMER_DECLARATION ;
1441
1532
qthread_addrres_t * X = ALLOC_ADDRRES ();
1442
1533
@@ -1465,13 +1556,22 @@ int API_FUNC qthread_readFE(aligned_t *restrict dest,
1465
1556
* (aligned_t * )dest = * (aligned_t * )src ;
1466
1557
MACHINE_FENCE ;
1467
1558
}
1559
+
1560
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
1561
+ m -> acq_owner_stat .state == qthread_id ();
1562
+ ++ m -> acq_owner_stat .recursive_access_counter ;
1563
+ MACHINE_FENCE ;
1564
+ qthread_debug (FEB_BEHAVIOR , "dest=%p (tid=%i): incrementing recursive_access_counter\n" , dest , qthread_id ());
1565
+ }
1566
+
1468
1567
qthread_debug (FEB_BEHAVIOR , "tid %u succeeded on %p=%p\n" , me -> thread_id , dest , src );
1469
1568
qthread_gotlock_empty (me -> rdata -> shepherd_ptr , m , (void * )alignedaddr );
1470
1569
}
1471
1570
QTHREAD_FEB_TIMER_STOP (febblock , me );
1472
1571
return QTHREAD_SUCCESS ;
1473
1572
} /*}}} */
1474
1573
1574
+
1475
1575
/* the way this works is that:
1476
1576
* 1 - src's FEB state is ignored
1477
1577
* 2 - data is copied from src to destination
@@ -1552,6 +1652,13 @@ int API_FUNC qthread_readFE_nb(aligned_t *restrict dest,
1552
1652
qthread_debug (FEB_DETAILS , "data structure locked\n" );
1553
1653
/* by this point m is locked */
1554
1654
if (m -> full == 0 ) { /* empty, thus, we must fail */
1655
+ /* unless called from qthread_trylock on a recursive lock*/
1656
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
1657
+
1658
+ ++ m -> acq_owner_stat .recursive_access_counter ;
1659
+ QTHREAD_FASTLOCK_UNLOCK (& m -> lock );
1660
+ return QTHREAD_SUCCESS ;
1661
+ }
1555
1662
qthread_debug (FEB_BEHAVIOR , "tid %u non-blocking fail\n" , me -> thread_id );
1556
1663
QTHREAD_FASTLOCK_UNLOCK (& m -> lock );
1557
1664
return QTHREAD_OPFAIL ;
@@ -1560,6 +1667,14 @@ int API_FUNC qthread_readFE_nb(aligned_t *restrict dest,
1560
1667
* (aligned_t * )dest = * (aligned_t * )src ;
1561
1668
MACHINE_FENCE ;
1562
1669
}
1670
+
1671
+ if (m -> acq_owner_stat .state >= FEB_is_recursive_lock ) {
1672
+ m -> acq_owner_stat .state == qthread_id ();
1673
+ ++ m -> acq_owner_stat .recursive_access_counter ;
1674
+ MACHINE_FENCE ;
1675
+ qthread_debug (FEB_BEHAVIOR , "dest=%p (tid=%i): incrementing recursive_access_counter\n" , dest , qthread_id ());
1676
+ }
1677
+
1563
1678
qthread_debug (FEB_BEHAVIOR , "tid %u succeeded on %p=%p\n" , me -> thread_id , dest , src );
1564
1679
qthread_gotlock_empty (me -> rdata -> shepherd_ptr , m , (void * )alignedaddr );
1565
1680
}
0 commit comments