From: unknown Date: Wed, 19 Feb 2014 22:50:58 +0000 (-0800) Subject: rework spinlock data structure to survive gcc -O3 optimization X-Git-Url: https://pd.if.org/git/?a=commitdiff_plain;ds=sidebyside;h=38b4bf5e1c011eebca99ebc047f14937df4d5e0f;hp=6b4425e582af0e64d26e45936240f78ac5936d46;p=btree rework spinlock data structure to survive gcc -O3 optimization --- diff --git a/threads2h.c b/threads2h.c index 4a28044..160308a 100644 --- a/threads2h.c +++ b/threads2h.c @@ -93,11 +93,11 @@ typedef enum{ // share is count of read accessors // grant write lock when share == 0 -typedef struct { - volatile unsigned char mutex; - volatile unsigned char exclusive:1; - volatile unsigned char pending:1; - volatile ushort share; +volatile typedef struct { + unsigned char mutex[1]; + unsigned char exclusive:1; + unsigned char pending:1; + ushort share; } BtSpinLatch; // hash table entries @@ -372,10 +372,10 @@ ushort prev; do { // obtain latch mutex #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) continue; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) continue; #endif // see if exclusive request is granted or pending @@ -384,9 +384,9 @@ ushort prev; latch->share++; #ifdef unix - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif if( prev ) @@ -407,10 +407,10 @@ uint prev; do { #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) continue; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) continue; #endif if( prev = !(latch->share | latch->exclusive) ) @@ -418,9 +418,9 @@ uint prev; else latch->pending = 1; #ifdef unix - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif if( prev ) return; @@ -441,10 +441,10 @@ int bt_spinwritetry(BtSpinLatch *latch) uint prev; #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) return 0; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) return 0; #endif // take write access if all bits are clear @@ -453,9 +453,9 @@ uint prev; latch->exclusive = 1; #ifdef unix - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif return prev; } @@ -466,17 +466,17 @@ void bt_spinreleasewrite(BtSpinLatch *latch) { // obtain latch mutex #ifdef unix - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); #else - while( _InterlockedExchange8(&latch->mutex, 1) ) + while( _InterlockedExchange8(latch->mutex, 1) ) SwitchToThread(); #endif latch->exclusive = 0; #ifdef unix - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif } @@ -485,17 +485,17 @@ void bt_spinreleasewrite(BtSpinLatch *latch) void bt_spinreleaseread(BtSpinLatch *latch) { #ifdef unix - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); #else - while( _InterlockedExchange8(&latch->mutex, 1) ) + while( _InterlockedExchange8(latch->mutex, 1) ) SwitchToThread(); #endif latch->share--; #ifdef unix - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif } @@ -783,7 +783,7 @@ uint slot; close (mgr->idx); free (mgr->pool); free (mgr->hash); - free (mgr->latch); + free ((void *)mgr->latch); free (mgr); #else FlushFileBuffers(mgr->idx); diff --git a/threads2i.c b/threads2i.c index c425d18..d8ac6be 100644 --- a/threads2i.c +++ b/threads2i.c @@ -93,11 +93,11 @@ typedef enum{ // share is count of read accessors // grant write lock when share == 0 -typedef struct { - volatile unsigned char mutex; - volatile unsigned char exclusive:1; - volatile unsigned char pending:1; - volatile ushort share; +volatile typedef struct { + unsigned char mutex[1]; + unsigned char exclusive:1; + unsigned char pending:1; + ushort share; } BtSpinLatch; // hash table entries @@ -162,10 +162,9 @@ typedef struct BtPage_ { uint min; // next key offset unsigned char bits:7; // page size in bits unsigned char free:1; // page is on free chain - unsigned char lvl:5; // level of page + unsigned char lvl:6; // level of page unsigned char kill:1; // page is being deleted unsigned char dirty:1; // page has deleted keys - unsigned char posted:1; // page fence is posted unsigned char right[BtId]; // page number to right } *BtPage; @@ -366,10 +365,10 @@ ushort prev; do { // obtain latch mutex #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) continue; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) continue; #endif // see if exclusive request is granted or pending @@ -378,9 +377,9 @@ ushort prev; latch->share++; #ifdef unix - __sync_lock_release (&latch->mutex); + *latch->mutex = 0; #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif if( prev ) @@ -401,10 +400,10 @@ uint prev; do { #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) continue; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) continue; #endif if( prev = !(latch->share | latch->exclusive) ) @@ -412,9 +411,9 @@ uint prev; else latch->pending = 1; #ifdef unix - __sync_lock_release (&latch->mutex); + *latch->mutex = 0; #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif if( prev ) return; @@ -435,10 +434,10 @@ int bt_spinwritetry(BtSpinLatch *latch) uint prev; #ifdef unix - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) return 0; #else - if( _InterlockedExchange8(&latch->mutex, 1) ) + if( _InterlockedExchange8(latch->mutex, 1) ) return 0; #endif // take write access if all bits are clear @@ -447,9 +446,9 @@ uint prev; latch->exclusive = 1; #ifdef unix - __sync_lock_release (&latch->mutex); + *latch->mutex = 0; #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif return prev; } @@ -459,17 +458,17 @@ uint prev; void bt_spinreleasewrite(BtSpinLatch *latch) { #ifdef unix - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); #else - while( _InterlockedExchange8(&latch->mutex, 1) ) + while( _InterlockedExchange8(latch->mutex, 1) ) SwitchToThread(); #endif latch->exclusive = 0; #ifdef unix - __sync_lock_release (&latch->mutex); + *latch->mutex = 0; #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif } @@ -478,17 +477,17 @@ void bt_spinreleasewrite(BtSpinLatch *latch) void bt_spinreleaseread(BtSpinLatch *latch) { #ifdef unix - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); #else - while( _InterlockedExchange8(&latch->mutex, 1) ) + while( _InterlockedExchange8(latch->mutex, 1) ) SwitchToThread(); #endif latch->share--; #ifdef unix - __sync_lock_release (&latch->mutex); + *latch->mutex = 0; #else - _InterlockedExchange8(&latch->mutex, 0); + _InterlockedExchange8(latch->mutex, 0); #endif } @@ -697,7 +696,7 @@ uint slot; close (mgr->idx); free (mgr->pool); free (mgr->hash); - free (mgr->latch); + free ((void *)mgr->latch); free (mgr); #else FlushFileBuffers(mgr->idx); diff --git a/threads2j.c b/threads2j.c index a1081b3..27212ef 100644 --- a/threads2j.c +++ b/threads2j.c @@ -101,15 +101,15 @@ enum { // share is count of read accessors // grant write lock when share == 0 -typedef struct { - volatile unsigned char mutex; // 1 = busy - volatile unsigned char write:1; // 1 = exclusive - volatile unsigned char readwait:1; // readers are waiting - volatile unsigned char writewait:1; // writers are waiting - volatile unsigned char filler:5; - volatile ushort share; // count of readers holding locks - volatile ushort rcnt; // count of waiting readers - volatile ushort wcnt; // count of waiting writers +volatile typedef struct { + unsigned char mutex[1]; // 1 = busy + unsigned char write:1; // 1 = exclusive + unsigned char readwait:1; // readers are waiting + unsigned char writewait:1; // writers are waiting + unsigned char filler:5; + ushort share; // count of readers holding locks + ushort rcnt; // count of waiting readers + ushort wcnt; // count of waiting writers } BtLatch; // Define the length of the page and key pointers @@ -153,10 +153,9 @@ typedef struct BtPage_ { uint min; // next key offset unsigned char bits:7; // page size in bits unsigned char free:1; // page is on free list - unsigned char lvl:5; // level of page + unsigned char lvl:6; // level of page unsigned char kill:1; // page is being deleted unsigned char dirty:1; // page has deleted keys - unsigned char posted:1; // page fence has posted unsigned char right[BtId]; // page number to right } *BtPage; @@ -385,7 +384,7 @@ uint prev; while( 1 ) { // obtain latch mutex - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); if( decr ) @@ -398,7 +397,7 @@ uint prev; latch->readwait = 1; latch->rcnt++; prev = *(uint *)latch & ~1; - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); sys_futex( (uint *)latch, FUTEX_WAIT_BITSET | private, prev, NULL, NULL, QueRd ); decr = 1; continue; @@ -409,7 +408,7 @@ uint prev; latch->readwait = 0; latch->share++; - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); return; } } @@ -426,7 +425,7 @@ uint prev; while( 1 ) { // obtain latch mutex - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); if( decr ) @@ -438,7 +437,7 @@ uint prev; latch->writewait = 1; latch->wcnt++; prev = *(uint *)latch & ~1; - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); sys_futex( (uint *)latch, FUTEX_WAIT_BITSET | private, prev, NULL, NULL, QueWr ); decr = 1; continue; @@ -451,7 +450,7 @@ uint prev; latch->writewait = 0; latch->write = 1; - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); return; } } @@ -468,7 +467,7 @@ int ans; // try for mutex, // abandon request if not taken - if( __sync_lock_test_and_set(&latch->mutex, 1) ) + if( __sync_lock_test_and_set(latch->mutex, 1) ) return 0; // see if write mode is available @@ -480,7 +479,7 @@ int ans; // release latch mutex - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); return ans; } @@ -493,7 +492,7 @@ void bt_spinreleasewrite(BtLatch *latch, int private) // obtain latch mutex - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); latch->write = 0; @@ -510,7 +509,7 @@ void bt_spinreleasewrite(BtLatch *latch, int private) // release latch mutex wakexit: - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); } // decrement reader count @@ -522,19 +521,19 @@ void bt_spinreleaseread(BtLatch *latch, int private) // obtain latch mutex - while( __sync_lock_test_and_set(&latch->mutex, 1) ) + while( __sync_lock_test_and_set(latch->mutex, 1) ) sched_yield(); latch->share--; - // wake waiting writers + // wake one waiting writer if( !latch->share && latch->wcnt ) sys_futex( (uint *)latch, FUTEX_WAKE_BITSET | private, 1, NULL, NULL, QueWr ); // release latch mutex - __sync_lock_release (&latch->mutex); + __sync_lock_release (latch->mutex); } // link latch table entry into latch hash table