diff options
Diffstat (limited to 'libs/pthreads/src/ptw32_OLL_lock.c')
-rw-r--r-- | libs/pthreads/src/ptw32_OLL_lock.c | 734 |
1 files changed, 0 insertions, 734 deletions
diff --git a/libs/pthreads/src/ptw32_OLL_lock.c b/libs/pthreads/src/ptw32_OLL_lock.c deleted file mode 100644 index 789d0ad8c6..0000000000 --- a/libs/pthreads/src/ptw32_OLL_lock.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * ptw32_OLL_lock.c - * - * Description: - * This translation unit implements extended reader/writer queue-based locks. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - * About the OLL lock (Scalable Reader-Writer Lock): - * - * OLL locks are queue-based locks similar to the MCS queue lock, where the queue - * nodes are local to the thread but where reader threads can enter the critical - * section immediately without going through a central guard lock if there are - * already readers holding the lock. - * - * Covered by United States Patent Application 20100241774 (Oracle) - */ - -#include "pthread.h" -#include "sched.h" -#include "implement.h" - -/* - * C-SNZI support - */ -typedef union ptw32_oll_counter_t_ ptw32_oll_counter_t; -typedef struct ptw32_oll_snziRoot_t_ ptw32_oll_snziRoot_t; -typedef struct ptw32_oll_snziNode_t_ ptw32_oll_snziNode_t; -typedef union ptw32_oll_snziNodeOrRoot_t_ ptw32_oll_snziNodeOrRoot_t; -typedef struct ptw32_oll_queryResult_t_ ptw32_oll_queryResult_t; -typedef struct ptw32_oll_ticket_t_ ptw32_oll_ticket_t; -typedef struct ptw32_oll_csnzi_t_ ptw32_oll_csnzi_t; - -enum -{ - ptw32_archWidth = sizeof(size_t)*8, - ptw32_oll_countWidth = ptw32_archWidth-2 -}; - -#define PTW32_OLL_MAXREADERS (((size_t)2<<(ptw32_oll_countWidth-1))-1) - -union ptw32_oll_counter_t_ -{ - size_t word : ptw32_archWidth; - struct - { - /* - * This needs to be a single word - * - * ------------------------------------ - * | STATE | ROOT | COUNT (readers) | - * ------------------------------------ - * 63 / 31 62 / 30 61 / 29 .. 0 - */ - size_t count : ptw32_oll_countWidth; - size_t root : 1; /* ROOT or NODE */ - size_t state : 1; /* OPEN or CLOSED (root only) */ - } internal; -}; - -struct ptw32_oll_snziRoot_t_ -{ - /* - * "counter" must be at same offset in both - * ptw32_oll_snziNode_t and ptw32_oll_snziRoot_t - */ - ptw32_oll_counter_t counter; -}; - -enum -{ - ptw32_oll_snziRoot_open = 0, - ptw32_oll_snziRoot_closed = 1 -}; - -enum -{ - ptw32_oll_snzi_root = 0, - ptw32_oll_snzi_node = 1 -}; - -/* - * Some common SNZI root whole-word states that can be used to set or compare - * root words with a single operation. - */ -ptw32_oll_snziRoot_t ptw32_oll_snziRoot_openAndZero = {.counter.internal.count = 0, - .counter.internal.root = ptw32_oll_snzi_root, - .counter.internal.state = ptw32_oll_snziRoot_open}; -ptw32_oll_snziRoot_t ptw32_oll_snziRoot_closedAndZero = {.counter.internal.count = 0, - .counter.internal.root = ptw32_oll_snzi_root, - .counter.internal.state = ptw32_oll_snziRoot_closed}; - -struct ptw32_oll_queryResult_t_ -{ - BOOL nonZero; - BOOL open; -}; - -union ptw32_oll_snziNodeOrRoot_t_ -{ - ptw32_oll_snziRoot_t* rootPtr; - ptw32_oll_snziNode_t* nodePtr; -}; - -struct ptw32_oll_snziNode_t_ -{ - /* "counter" must be at same offset in both - * ptw32_oll_snziNode_t and ptw32_oll_snziRoot_t - */ - ptw32_oll_counter_t counter; - ptw32_oll_snziNodeOrRoot_t parentPtr; -}; - -struct ptw32_oll_ticket_t_ -{ - ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot; -}; - -ptw32_oll_ticket_t ptw32_oll_ticket_null = {NULL}; - -struct ptw32_oll_csnzi_t_ -{ - ptw32_oll_snziRoot_t proxyRoot; - ptw32_oll_snziNode_t leafs[]; -}; - -/* - * FOLL lock support - */ - -typedef struct ptw32_foll_node_t_ ptw32_foll_node_t; -typedef struct ptw32_foll_local_t_ ptw32_foll_local_t; -typedef struct ptw32_foll_rwlock_t_ ptw32_foll_rwlock_t; - -enum -{ - ptw32_srwl_reader, - ptw32_srwl_writer -}; - -enum -{ - ptw32_srwl_free, - ptw32_srwl_in_use -}; - -struct ptw32_foll_node_t_ -{ - ptw32_foll_node_t* qNextPtr; - ptw32_oll_csnzi_t* csnziPtr; - ptw32_foll_node_t* nextPtr; - int kind; - int allocState; - BOOL spin; -}; - -struct ptw32_foll_local_t_ -{ - ptw32_foll_node_t* rNodePtr; // Default read node. Immutable - ptw32_foll_node_t* wNodePtr; // Write node. Immutable. - ptw32_foll_node_t* departFromPtr; // List node we last arrived at. - ptw32_oll_ticket_t ticket; // C-SNZI ticket -}; - -struct ptw32_foll_rwlock_t_ -{ - ptw32_foll_node_t* tailPtr; - ptw32_foll_node_t* rNodesPtr; // Head of reader node -}; - -/* - * ShouldArriveAtTree() returns true if: - * the compare_exchange in Arrive() fails too often under read access; or - * ?? - * Note that this is measured across all access to - * this lock, not just this attempt, so that highly - * read-contended locks will use C-SNZI. Lightly - * read-contended locks can reduce memory usage and some - * processing by using the root directly. - */ -BOOL -ptw32_oll_ShouldArriveAtTree() -{ - return PTW32_FALSE; -} - -size_t -ptw32_oll_GetLeafForThread() -{ - return 0; -} - -/* - * Only readers call ptw32_oll_Arrive() - * - * Checks whether the C-SNZI state is OPEN, and if so, - * increments the surplus of the C-SNZI by either directly - * arriving at the root node, or calling TreeArrive on one - * of the leaf nodes. Returns a ticket pointing to the node - * that was arrived at. If the state is CLOSED, makes no - * change and returns a ticket that contains no pointer. - */ -ptw32_oll_ticket_t -ptw32_oll_Arrive(ptw32_oll_csnzi_t* csnzi) -{ - for (;;) - { - ptw32_oll_ticket_t ticket; - ptw32_oll_snziRoot_t oldProxy = csnzi->proxyRoot; - if (oldProxy.counter.internal.state != ptw32_oll_snziRoot_open) - { - ticket.snziNodeOrRoot.rootPtr = (ptw32_oll_snziRoot_t*)NULL; - return ticket; - } - if (!ptw32_oll_ShouldArriveAtTree()) - { - ptw32_oll_snziRoot_t newProxy = oldProxy; - newProxy.counter.internal.count++; - if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&csnzi->proxyRoot.counter, - (PTW32_INTERLOCKED_SIZE)newProxy.counter.word, - (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word) - == (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word) - { - /* Exchange successful */ - ticket.snziNodeOrRoot.rootPtr = &csnzi->proxyRoot; - return ticket; - } - } - else - { - ptw32_oll_snziNode_t* leafPtr = &csnzi->leafs[ptw32_oll_GetLeafForThread()]; - ticket.snziNodeOrRoot.nodePtr = (ptw32_oll_TreeArrive(leafPtr) ? leafPtr : (ptw32_oll_snziNode_t*)NULL); - return ticket; - } - } -} - -/* - * Decrements the C-SNZI surplus. Returns false iff the - * resulting state is CLOSED and the surplus is zero. - * Ticket must have been returned by an arrival. Must have - * received this ticket from Arrive more times than Depart - * has been called with the ticket. (Thus, the surplus - * must be greater than zero.) - */ -BOOL -ptw32_oll_Depart(ptw32_oll_ticket_t ticket) -{ - return ptw32_oll_TreeDepart(ticket.snziNodeOrRoot); -} - -/* - * Increments the C-SNZI surplus and returns true if the - * C-SNZI is open or has a surplus. Calls TreeArrive - * recursively on the node’s parent if needed. - * Otherwise, returns false without making any changes. - */ -BOOL -ptw32_oll_TreeArrive(ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot) -{ - if (snziNodeOrRoot.nodePtr->counter.internal.root != ptw32_oll_snzi_root) - { - /* Non-root node */ - ptw32_oll_counter_t newCounter, oldCounter; - BOOL arrivedAtParent = PTW32_FALSE; - do - { - oldCounter = snziNodeOrRoot.nodePtr->counter; - if (0 == oldCounter.internal.count && !arrivedAtParent) - { - if (ptw32_oll_TreeArrive(snziNodeOrRoot.nodePtr->parentPtr)) - arrivedAtParent = PTW32_TRUE; - else - return PTW32_FALSE; - } - newCounter = oldCounter; - newCounter.internal.count++; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.nodePtr->counter, - (PTW32_INTERLOCKED_SIZE)newCounter.word, - (PTW32_INTERLOCKED_SIZE)oldCounter.word) - != (PTW32_INTERLOCKED_SIZE)oldCounter.word); - if (newCounter.internal.count != 0 && arrivedAtParent) - ptw32_oll_TreeDepart(snziNodeOrRoot.nodePtr->parentPtr); - return PTW32_TRUE; - } - else - { - /* Root node */ - ptw32_oll_snziRoot_t newRoot, oldRoot; - do - { - oldRoot = *(ptw32_oll_snziRoot_t*)snziNodeOrRoot.rootPtr; - if (oldRoot.counter.word == ptw32_oll_snziRoot_closedAndZero.counter.word) - return PTW32_FALSE; - newRoot = oldRoot; - newRoot.counter.internal.count++; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.rootPtr->counter, - (PTW32_INTERLOCKED_SIZE)newRoot.counter.word, - (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word) - != (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word); - return PTW32_TRUE; - } -} - -/* - * Decrements the C-SNZI surplus, calling TreeDepart - * recursively on the node’s parent if needed. Returns - * false iff the resulting state of the C-SNZI is CLOSED - * and the surplus is zero. Otherwise, returns true. - */ -BOOL -ptw32_oll_TreeDepart(ptw32_oll_snziNodeOrRoot_t snziNodeOrRoot) -{ - if (snziNodeOrRoot.nodePtr->counter.internal.root != ptw32_oll_snzi_root) - { - /* Non-root node */ - ptw32_oll_counter_t newCounter, oldCounter; - do - { - newCounter = oldCounter = snziNodeOrRoot.nodePtr->counter; - newCounter.internal.count--; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.nodePtr->counter, - (PTW32_INTERLOCKED_SIZE)newCounter.word, - (PTW32_INTERLOCKED_SIZE)oldCounter.word) - != (PTW32_INTERLOCKED_SIZE)oldCounter.word); - return (0 == newCounter.internal.count) - ? ptw32_oll_TreeDepart(snziNodeOrRoot.nodePtr->parentPtr) - : PTW32_TRUE; - } - else - { - /* Root node */ - ptw32_oll_snziRoot_t newRoot, oldRoot; - do - { - newRoot = oldRoot = *(ptw32_oll_snziRoot_t*)snziNodeOrRoot.rootPtr; - newRoot.counter.internal.count--; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&snziNodeOrRoot.rootPtr->counter, - (PTW32_INTERLOCKED_SIZE)newRoot.counter.word, - (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word) - != (PTW32_INTERLOCKED_SIZE)oldRoot.counter.word); - return (newRoot.counter.word != ptw32_oll_snziRoot_closedAndZero.counter.word); - } -} - -/* - * Opens a C-SNZI object. Requires C-SNZI state to be - * CLOSED and the surplus to be zero. - */ -void -ptw32_oll_Open(ptw32_oll_csnzi_t* csnziPtr) -{ - csnziPtr->proxyRoot = ptw32_oll_snziRoot_openAndZero; -} - -/* - * Opens a C-SNZI object while atomically performing count - * arrivals. Requires C-SNZI state to be CLOSED and - * the surplus to be zero. - */ -void -ptw32_oll_OpenWithArrivals(ptw32_oll_csnzi_t* csnziPtr, size_t count, BOOL close) -{ - csnziPtr->proxyRoot.counter.internal.count = count; - csnziPtr->proxyRoot.counter.internal.state = (close ? ptw32_oll_snziRoot_closed : ptw32_oll_snziRoot_open); -} - -/* - * Closes a C-SNZI object. Returns true iff the C-SNZI - * state changed from OPEN to CLOSED and the surplus is - * zero. - */ -BOOL -ptw32_oll_Close(ptw32_oll_csnzi_t* csnziPtr) -{ - ptw32_oll_snziRoot_t newProxy, oldProxy; - do - { - oldProxy = csnziPtr->proxyRoot; - if (oldProxy.counter.internal.state != ptw32_oll_snziRoot_open) - { - return PTW32_FALSE; - } - newProxy = oldProxy; - newProxy.counter.internal.state = ptw32_oll_snziRoot_closed; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&csnziPtr->proxyRoot.counter, - (PTW32_INTERLOCKED_SIZE)newProxy.counter.word, - (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word) - != (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word); - return (newProxy.counter.word == ptw32_oll_snziRoot_closedAndZero.counter.word); -} - -/* - * Closes a C-SNZI if its surplus is zero. Otherwise, does - * nothing. Returns true iff C-SNZI state changed from - * OPEN to CLOSED. - */ -BOOL -ptw32_oll_CloseIfEmpty(ptw32_oll_csnzi_t* csnziPtr) -{ - ptw32_oll_snziRoot_t newProxy, oldProxy; - do - { - oldProxy = csnziPtr->proxyRoot; - if (oldProxy.counter.word != ptw32_oll_snziRoot_openAndZero.counter.word) - { - return PTW32_FALSE; - } - newProxy = ptw32_oll_snziRoot_closedAndZero; - } while (PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE( - (PTW32_INTERLOCKED_SIZEPTR)&csnziPtr->proxyRoot.counter, - (PTW32_INTERLOCKED_SIZE)newProxy.counter.word, - (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word) - != (PTW32_INTERLOCKED_SIZE)oldProxy.counter.word); - return PTW32_TRUE; -} - -/* - * Returns whether the C-SNZI has a nonzero surplus and - * whether the C-SNZI is open. - * "nonZero" doesn't appear to be used anywhere in the algorithms. - */ -ptw32_oll_queryResult_t -ptw32_oll_Query(ptw32_oll_csnzi_t* csnziPtr) -{ - ptw32_oll_queryResult_t query; - ptw32_oll_snziRoot_t proxy = csnziPtr->proxyRoot; - - query.nonZero = (proxy.counter.internal.count > 0); - query.open = (proxy.counter.internal.state == ptw32_oll_snziRoot_open); - return query; -} - -/* - * Returns whether the Arrive operation that returned - * the ticket succeeded. - */ -BOOL -ptw32_oll_Arrived(ptw32_oll_ticket_t t) -{ - return (t.snziNodeOrRoot.nodePtr != NULL); -} - -/* - * Constructs and returns a ticket that can be used to - * depart from the root node. - */ -ptw32_oll_ticket_t -ptw32_oll_DirectTicket(ptw32_oll_csnzi_t* csnziPtr) -{ - ptw32_oll_ticket_t ticket; - ticket.snziNodeOrRoot.rootPtr = &csnziPtr->proxyRoot; - return ticket; -} - -/* Scalable RW Locks */ - -typedef struct ptw32_srwl_rwlock_t_ ptw32_srwl_rwlock_t; -typedef struct ptw32_srwl_node_t_ ptw32_srwl_node_t; -typedef struct ptw32_srwl_local_t_ ptw32_srwl_local_t; - -enum -{ - ptw32_srwl_reader = 0, - ptw32_srwl_writer = 1 -}; - -enum -{ - ptw32_srwl_free = 0, - ptw32_srwl_in_use = 1 -}; - -struct ptw32_srwl_rwlock_t_ -{ - ptw32_srwl_node_t* tailPtr; - ptw32_srwl_node_t* readerNodePtr; -}; - -struct ptw32_srwl_node_t_ -{ - ptw32_srwl_node_t* qNextPtr; - ptw32_oll_csnzi_t* csnziPtr; - ptw32_srwl_node_t* nextReaderPtr; - int kind; /* ptw32_srwl_reader, ptw32_srwl_writer */ - int allocState; /* ptw32_srwl_free, ptw32_srwl_in_use */ - BOOL spin; -}; - -/* - * When a ptw32_srwl_local_t is instantiated the "kind" of each of - * rNode and wNode must be set as appropriate. This is the only - * time "kind" is set. - */ -struct ptw32_srwl_local_t_ -{ - ptw32_srwl_node_t* rNodePtr; - ptw32_srwl_node_t* wNodePtr; - ptw32_srwl_node_t* departFromPtr; - ptw32_oll_ticket_t ticket; -}; - -/* Allocates a new reader node. */ -ptw32_srwl_node_t* -ptw32_srwl_AllocReaderNode(ptw32_srwl_local_t* local) -{ - ptw32_srwl_node_t* currNodePtr = local->rNodePtr; - for (;;) - { - if (currNodePtr->allocState == ptw32_srwl_free) - { - if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG( - (PTW32_INTERLOCKED_LONGPTR)&currNodePtr->allocState, - (PTW32_INTERLOCKED_LONG)ptw32_srwl_in_use, - (PTW32_INTERLOCKED_LONG)ptw32_srwl_free) - == (PTW32_INTERLOCKED_LONG)ptw32_srwl_in_use) - { - return currNodePtr; - } - } - currNodePtr = currNodePtr->next; - } -} - -/* - * Frees a reader node. Requires that its allocState - * is ptw32_srwl_in_use. - */ -void -ptw32_srwl_FreeReaderNode(ptw32_srwl_node_t* nodePtr) -{ - nodePtr->allocState := ptw32_srwl_free; -} - -void -ptw32_srwl_WriterLock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr) -{ - oldTailPtr = (ptw32_srwl_rwlock_t*)PTW32_INTERLOCKED_EXCHANGE_PTR( - (PTW32_INTERLOCKED_PVOID_PTR)&lockPtr->tailPtr, - (PTW32_INTERLOCKED_PVOID)localPtr->wNodePtr); - if (oldTailPtr != NULL) - { - localPtr->wNodePtr->spin := PTW32_TRUE; - oldTailPtr->qNextPtr = localPtr->wNodePtr; - if (oldTailPtr->kind == ptw32_srwl_writer) - { - while (localPtr->wNodePtr->spin); - } - else - { - /* Wait until node is properly recycled */ - while (ptw32_oll_Query(oldTailPtr->csnzi).open); - /* - * Close C-SNZI of previous reader node. - * If there are no readers to signal us, spin on - * previous node and free it before entering - * critical section. - */ - if (ptw32_oll_Close(oldTailPtr->csnzi)) - { - while (oldTailPtr->spin); - ptw32_srwl_FreeReaderNode(oldTailPtr); - } - else - { - while (localPtr->wNodePtr->spin); - } - } - } -} - -void -ptw32_srwl_WriterUnlock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr) -{ - if (localPtr->wNodePtr->qNextPtr == NULL) - { - if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR( - (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr, - (PTW32_INTERLOCKED_PVOID)NULL, - (PTW32_INTERLOCKED_PVOID)localPtr->wNodePtr) - == (PTW32_INTERLOCKED_PVOID)NULL) - { - return; - } - else - { - while (localPtr->wNodePtr->qNextPtr == NULL); - } - } - /* Clean up */ - localPtr->wNodePtr->qNextPtr->spin = PTW32_FALSE; - localPtr->wNodePtr->qNextPtr = NULL; -} - -void -ptw32_srwl_ReaderLock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr) -{ - ptw32_srwl_node_t* rNodePtr = NULL; - for (;;) - { - ptw32_srwl_node_t* tailPtr = lockPtr->tailPtr; - /* If no nodes are in the queue */ - if (tailPtr == NULL) - { - if (rNodePtr == NULL) - { - rNodePtr = ptw32_srwl_AllocReaderNode(localPtr); - } - rNodePtr->spin = PTW32_FALSE; - if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR( - (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr, - (PTW32_INTERLOCKED_PVOID)rNodePtr, - (PTW32_INTERLOCKED_PVOID)NULL) - == (PTW32_INTERLOCKED_PVOID)rNodePtr) - { - ptw32_oll_Open(rNodePtr->csnzi); - localPtr->ticket = ptw32_oll_Arrive(rNodePtr->csnzi); - if (ptw32_oll_Arrived(localPtr->ticket)) - { - localPtr->departFromPtr = rNodePtr; - return; - } - /* Avoid reusing inserted node */ - rNodePtr = NULL; - } - } - /* Otherwise, there is a node in the queue */ - else - { - /* Is last node a writer node? */ - if (tailPtr->kind == ptw32_srwl_writer) - { - if (rNodePtr == NULL) - { - rNodePtr = ptw32_srwl_AllocReaderNode(localPtr); - } - rNodePtr->spin = PTW32_TRUE; - if (PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR( - (PTW32_INTERLOCKED_PVOIDPTR)&lockPtr->tailPtr, - (PTW32_INTERLOCKED_PVOID)rNodePtr, - (PTW32_INTERLOCKED_PVOID)tailPtr) - == (PTW32_INTERLOCKED_PVOID)rNodePtr) - { - tailPtr->qNextPtr = rNodePtr; - localPtr->ticket = ptw32_oll_Arrive(rNodePtr->csnzi); - if (ptw32_oll_Arrived(localPtr->ticket)) - { - localPtr->departFromPtr = rNodePtr; - while (rNodePtr->spin); - return; - } - /* Avoid reusing inserted node */ - rNodePtr = NULL; - } - } - /* - * Otherwise, last node is a reader node. - * (tailPtr->kind == ptw32_srwl_reader) - */ - else - { - localPtr->ticket = ptw32_oll_Arrive(tailPtr->csnzi); - if (ptw32_oll_Arrived(localPtr->ticket)) - { - if (rNodePtr != NULL) - { - ptw32_srwl_FreeReaderNode(rNodePtr); - } - localPtr->departFromPtr = tailPtr; - while (tailPtr->spin); - return; - } - } - } - } -} - -void -ptw32_srwl_ReaderUnlock(ptw32_srwl_rwlock_t* lockPtr, ptw32_srwl_local_t* localPtr) -{ - if (ptw32_oll_Depart(localPtr->departFromPtr->csnzi, localPtr->ticket)) - { - return; - } - /* Clean up */ - localPtr->departFromPtr->qNextPtr->spin = PTW32_FALSE; - localPtr->departFromPtr->qNextPtr = NULL; - ptw32_srwl_FreeReaderNode(localPtr->departFromPtr); -} - - -#include <stdio.h> - -int main() -{ - printf("%lx\n", PTW32_OLL_MAXREADERS); - return 0; -} - |