+ continue;
+ }
+
+ // wait for write and reader count to clear
+
+ if( latch->write || latch->share ) {
+ __sync_fetch_and_add ((uint *)latch, PendWr);
+ prev = __sync_fetch_and_and ((uint *)latch, ~Mutex) & ~Mutex;
+ sys_futex( (uint *)latch, FUTEX_WAIT_BITSET | private, prev, NULL, NULL, QueWr );
+ __sync_fetch_and_sub ((uint *)latch, PendWr);
+ continue;
+ }
+
+ // take write mutex
+ // release latch mutex
+
+ __sync_fetch_and_or ((uint *)latch, Write);
+ __sync_fetch_and_and ((uint *)latch, ~Mutex);
+ return;
+ }
+}
+
+// try to obtain write lock
+
+// return 1 if obtained,
+// 0 otherwise
+
+int bt_spinwritetry(BtLatch *latch)
+{
+int ans;
+
+ // try for mutex,
+ // abandon request if not taken
+
+ if( __sync_fetch_and_or((uint *)latch, Mutex) & Mutex )
+ return 0;
+
+ // see if write mode is available
+
+ if( !latch->write && !latch->share ) {
+ __sync_fetch_and_or ((uint *)latch, Write);
+ ans = 1;
+ } else
+ ans = 0;
+
+ // release latch mutex
+
+ __sync_fetch_and_and ((uint *)latch, ~Mutex);
+ return ans;
+}
+
+// clear write lock
+
+void bt_spinreleasewrite(BtLatch *latch, int private)
+{
+ if( private )
+ private = FUTEX_PRIVATE_FLAG;
+
+ // obtain latch mutex
+
+ while( __sync_fetch_and_or((uint *)latch, Mutex) & Mutex )
+ sched_yield();
+
+ __sync_fetch_and_and ((uint *)latch, ~Write);
+
+ // favor writers
+
+ if( latch->writewait )
+ if( sys_futex( (uint *)latch, FUTEX_WAKE_BITSET | private, 1, NULL, NULL, QueWr ) )
+ goto wakexit;
+
+ if( latch->readwait )
+ sys_futex( (uint *)latch, FUTEX_WAKE_BITSET | private, INT_MAX, NULL, NULL, QueRd );
+
+ // release latch mutex
+
+wakexit:
+ __sync_fetch_and_and ((uint *)latch, ~Mutex);
+}
+
+// decrement reader count
+
+void bt_spinreleaseread(BtLatch *latch, int private)
+{
+ if( private )
+ private = FUTEX_PRIVATE_FLAG;
+
+ // obtain latch mutex
+
+ while( __sync_fetch_and_or((uint *)latch, Mutex) & Mutex )
+ sched_yield();
+
+ __sync_fetch_and_sub ((uint *)latch, Share);
+
+ // wake waiting writers
+
+ if( !latch->share && latch->writewait )
+ sys_futex( (uint *)latch, FUTEX_WAKE_BITSET | private, 1, NULL, NULL, QueWr );
+
+ // release latch mutex
+
+ __sync_fetch_and_and ((uint *)latch, ~Mutex);
+}
+
+// link latch table entry into latch hash table
+
+void bt_latchlink (BtDb *bt, ushort hashidx, ushort victim, uid page_no)
+{
+BtLatchSet *set = bt->mgr->latchsets + victim;
+
+ if( set->next = bt->mgr->latchmgr->table[hashidx].slot )
+ bt->mgr->latchsets[set->next].prev = victim;
+
+ bt->mgr->latchmgr->table[hashidx].slot = victim;
+ set->page_no = page_no;
+ set->hash = hashidx;
+ set->prev = 0;
+}
+
+// release latch pin
+
+void bt_unpinlatch (BtLatchSet *set)
+{