X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=threads2h.c;h=2c4deaaec7fc1df404ce042bd5d8f972b146ac22;hb=fe2ddf2193540d99fa9fb6ecf93beed5b66b8808;hp=1b4d630a03a256b3c8a90a916cfe80575d61a116;hpb=b4a0a87a0f8a88ac689ea1b27f8fef3670a3d00a;p=btree diff --git a/threads2h.c b/threads2h.c index 1b4d630..2c4deaa 100644 --- a/threads2h.c +++ b/threads2h.c @@ -86,9 +86,10 @@ typedef enum{ // mode & definition for latch implementation enum { - Write = 1, - Pending = 2, - Share = 4 + Mutex = 1, + Write = 2, + Pending = 4, + Share = 8 } LockMode; // exclusive is set for write access @@ -96,9 +97,10 @@ enum { // grant write lock when share == 0 typedef struct { - volatile uint exclusive:1; - volatile uint request:1; - volatile uint share:30; + volatile ushort mutex:1; + volatile ushort exclusive:1; + volatile ushort pending:1; + volatile ushort share:13; } BtLatch; typedef struct { @@ -594,6 +596,8 @@ BtDb *bt = malloc (sizeof(*bt)); bt->frame = (BtPage)bt->mem; bt->zero = (BtPage)(bt->mem + 1 * mgr->page_size); bt->cursor = (BtPage)(bt->mem + 2 * mgr->page_size); + + memset (bt->zero, 0, mgr->page_size); return bt; } @@ -623,89 +627,75 @@ int ans; void bt_readlock(BtLatch *latch) { +ushort prev; + do { - // see if exclusive request is pending, or granted + // obtain latch mutex +#ifdef unix + if( __sync_fetch_and_or((ushort *)latch, Mutex) & Mutex ) + continue; +#else + if( prev = _InterlockedOr16((ushort *)latch, Mutex) & Mutex ) + continue; +#endif + // see if exclusive request is granted or pending - if( !(volatile int)latch->request && !(volatile int)latch->exclusive ) { - // add one to counter, check write bit + if( prev = !(latch->exclusive | latch->pending) ) #ifdef unix - if( ~__sync_fetch_and_add((volatile int *)latch, Share) & Write ) - return; + __sync_fetch_and_add((ushort *)latch, Share); #else - if( ~_InterlockedExchangeAdd((volatile int *)latch, Share) & Write ) - return; + _InterlockedExchangeAdd16 ((ushort *)latch, Share); #endif - // didn't get latch, reduce counter by one #ifdef unix - __sync_fetch_and_add((volatile int *)latch, -Share); + __sync_fetch_and_and ((ushort *)latch, ~Mutex); #else - _InterlockedExchangeAdd ((volatile int *)latch, -Share); + _InterlockedAnd16((ushort *)latch, ~Mutex); #endif - } - // and yield + if( prev ) + return; #ifdef unix - sched_yield(); + } while( sched_yield(), 1 ); #else - SwitchToThread(); + } while( SwitchToThread(), 1 ); #endif - } while( 1 ); } // wait for other read and write latches to relinquish void bt_writelock(BtLatch *latch) { -int prev; +ushort prev; do { - // set exclusive access pending - -#ifdef unix - __sync_fetch_and_or((int *)latch, Pending); +#ifdef unix + if( __sync_fetch_and_or((ushort *)latch, Mutex | Pending) & Mutex ) + continue; #else - _InterlockedOr((int *)latch, Pending); + if( _InterlockedOr16((ushort *)latch, Mutex | Pending) & Mutex ) + continue; #endif - - // see if we can get write access - // with no readers + if( prev = !(latch->share | latch->exclusive) ) #ifdef unix - prev = __sync_fetch_and_or((volatile int *)latch, Write); + __sync_fetch_and_or((ushort *)latch, Write); #else - prev = _InterlockedOr((volatile int *)latch, Write); + _InterlockedOr16((ushort *)latch, Write); #endif - // did we get exclusive access? - // if so, clear write pending - - if( !(prev & ~Pending) ) { #ifdef unix - __sync_fetch_and_and((volatile int *)latch, ~Pending); + __sync_fetch_and_and ((ushort *)latch, ~(Mutex | Pending)); #else - _InterlockedAnd((volatile int *)latch, ~Pending); + _InterlockedAnd16((ushort *)latch, ~(Mutex | Pending)); #endif - return; - } - - // reset our Write mode if it was clear before - - if( !(prev & Write) ) { -#ifdef unix - __sync_fetch_and_and((volatile int *)latch, ~Write); -#else - _InterlockedAnd((volatile int *)latch, ~Write); -#endif - } - - // otherwise yield + if( prev ) + return; #ifdef unix - sched_yield(); + } while( sched_yield(), 1 ); #else - SwitchToThread(); + } while( SwitchToThread(), 1 ); #endif - } while( 1 ); } // try to obtain write lock @@ -715,32 +705,30 @@ int prev; int bt_writetry(BtLatch *latch) { -int prev; +ushort prev; - // see if we can get write access - // with no readers #ifdef unix - prev = __sync_fetch_and_or((volatile int *)latch, Write); + if( prev = __sync_fetch_and_or((ushort *)latch, Mutex), prev & Mutex ) + return 0; #else - prev = _InterlockedOr((volatile int *)latch, Write); + if( prev = _InterlockedOr16((ushort *)latch, Mutex), prev & Mutex ) + return 0; #endif + // take write access if all bits are clear - // did we get exclusive access? - // if so, return OK - - if( !(prev & ~Pending) ) - return 1; - - // reset our Write mode if it was clear before + if( !prev ) +#ifdef unix + __sync_fetch_and_or ((ushort *)latch, Write); +#else + _InterlockedOr16((ushort *)latch, Write); +#endif - if( !(prev & Write) ) { #ifdef unix - __sync_fetch_and_and((volatile int *)latch, ~Write); + __sync_fetch_and_and ((ushort *)latch, ~Mutex); #else - _InterlockedAnd((volatile int *)latch, ~Write); + _InterlockedAnd16((ushort *)latch, ~Mutex); #endif - } - return 0; + return !prev; } // clear write mode @@ -748,9 +736,9 @@ int prev; void bt_releasewrite(BtLatch *latch) { #ifdef unix - __sync_fetch_and_and((int *)latch, ~Write); + __sync_fetch_and_and ((ushort *)latch, ~Write); #else - _InterlockedAnd ((int *)latch, ~Write); + _InterlockedAnd16((ushort *)latch, ~Write); #endif } @@ -759,9 +747,9 @@ void bt_releasewrite(BtLatch *latch) void bt_releaseread(BtLatch *latch) { #ifdef unix - __sync_fetch_and_add((int *)latch, -Share); + __sync_fetch_and_add((ushort *)latch, -Share); #else - _InterlockedExchangeAdd((int *)latch, -Share); + _InterlockedExchangeAdd16 ((ushort *)latch, -Share); #endif } @@ -1166,7 +1154,6 @@ BTERR bt_freepage(BtDb *bt, uid page_no) uid bt_newpage(BtDb *bt, BtPage page) { -BtPool *pool; uid new_page; BtPage pmap; int subpage; @@ -1174,7 +1161,7 @@ int reuse; // lock page zero - if ( bt_lockpage(bt, ALLOC_page, BtLockWrite, &bt->alloc) ) + if( bt_lockpage(bt, ALLOC_page, BtLockWrite, &bt->alloc) ) return 0; // use empty chain first @@ -1194,36 +1181,29 @@ int reuse; } #ifdef unix - memset(bt->zero, 0, sizeof(BtLatchSet)); // clear locks - memcpy((char *)bt->zero + sizeof(BtLatchSet), (char *)page + sizeof(BtLatchSet), bt->mgr->page_size - sizeof(BtLatchSet)); + // if writing first page of pool block + // expand file thru last page in the block - if ( pwrite(bt->mgr->idx, bt->zero, bt->mgr->page_size, new_page << bt->mgr->page_bits) < bt->mgr->page_size ) + if( !reuse && (new_page & bt->mgr->poolmask) == 0 ) + if( pwrite(bt->mgr->idx, bt->zero, bt->mgr->page_size, (new_page | bt->mgr->poolmask) << bt->mgr->page_bits) < bt->mgr->page_size ) return bt->err = BTERR_wrt, 0; +#endif + // unlock page allocation page - // if writing first page of pool block, zero last page in the block + if( bt_unlockpage(bt, ALLOC_page, BtLockWrite) ) + return 0; - if ( !reuse && bt->mgr->poolmask > 0 && (new_page & bt->mgr->poolmask) == 0 ) - { - // use zero buffer to write zeros - memset(bt->zero, 0, bt->mgr->page_size); - if ( pwrite(bt->mgr->idx,bt->zero, bt->mgr->page_size, (new_page | bt->mgr->poolmask) << bt->mgr->page_bits) < bt->mgr->page_size ) - return bt->err = BTERR_wrt, 0; - } -#else // bring new page into pool and copy page. - // this will extend the file into the new pages. + // on Windows, this will extend the file into the new page. if( bt_lockpage(bt, new_page, BtLockWrite, &pmap) ) return 0; - memcpy(pmap, page, bt->mgr->page_size); + // copy source page but leave latch area intact - if( bt_unlockpage (bt, new_page, BtLockWrite) ) - return 0; -#endif - // unlock page allocation page + memcpy((char *)pmap + sizeof(BtLatchSet), (char *)page + sizeof(BtLatchSet), bt->mgr->page_size - sizeof(BtLatchSet)); - if ( bt_unlockpage(bt, ALLOC_page, BtLockWrite) ) + if( bt_unlockpage (bt, new_page, BtLockWrite) ) return 0; return new_page;