ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

lock_free_slist.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1997-1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 
00019 #ifndef _STLP_LOCK_FREE_SLIST_H
00020 #define _STLP_LOCK_FREE_SLIST_H
00021 
00022 #if defined(_STLP_PTHREADS)
00023 #  include <pthread.h>
00024 
00025 #  if defined (__GNUC__) && defined (__i386__)
00026 
00027 #    define _STLP_HAS_ATOMIC_FREELIST
00028 
00034 class _STLP_atomic_freelist {
00035 public:
00039   struct item {
00040     item* _M_next;
00041   };
00042 
00043   _STLP_atomic_freelist() {
00044     // Statically assert layout of member is as expected by assembly code
00045     _STLP_STATIC_ASSERT(sizeof(_M) == 8)
00046     _M._M_data._M_top       = 0;
00047     _M._M_data._M_sequence  = 0;
00048   }
00049 
00055   void push(item* __item) {
00056     // NOTE: GCC uses ebx as the PIC register for globals in shared libraries.
00057     //       The GCC version I'm using (3.4.1) won't temporarily spill it if it's
00058     //       used as input, output, or clobber.  Instead, it complains with a
00059     //       "can't find a register in class `BREG' while reloading `asm'" error.
00060     //       This is probably a compiler bug, but as the cmpxchg8b instruction
00061     //       requires ebx, I work around this here by using ecx for the '__item'
00062     //       input and spilling ebx into edi.  This also precludes us from using
00063     //       a "m" operand for the cmpxchg8b argument (GCC might think it can make
00064     //       it relative to ebx).  Instead, we're using esi for the address of _M_data.
00065     //
00066     int __tmp1;     // These dummy variables are used to tell GCC that the eax, ecx,
00067     int __tmp2;     // and edx registers will not have the same value as their input.
00068     int __tmp3;     // The optimizer will remove them as their values are not used.
00069     __asm__ __volatile__
00070       ("       movl       %%ebx, %%edi\n\t"
00071        "       movl       %%ecx, %%ebx\n\t"
00072        "L1_%=: movl       %%eax, (%%ebx)\n\t"     // __item._M_next = _M._M_data._M_top
00073        "       leal       1(%%edx),%%ecx\n\t"     // new sequence = _M._M_data._M_sequence + 1
00074        "lock;  cmpxchg8b  (%%esi)\n\t"
00075        "       jne        L1_%=\n\t"              // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00076        "       movl       %%edi, %%ebx"
00077       :"=a" (__tmp1), "=d" (__tmp2), "=c" (__tmp3)
00078       :"a" (_M._M_data._M_top), "d" (_M._M_data._M_sequence), "c" (__item), "S" (&_M._M_data)
00079       :"edi", "memory", "cc");
00080   }
00081 
00088   item* pop() {
00089     item*   __result;
00090     int     __tmp;
00091     __asm__ __volatile__
00092       ("       movl       %%ebx, %%edi\n\t"
00093        "L1_%=: testl      %%eax, %%eax\n\t"       // _M_top == NULL?
00094        "       je         L2_%=\n\t"              // If yes, we're done
00095        "       movl       (%%eax), %%ebx\n\t"     // new top = _M._M_data._M_top->_M_next
00096        "       leal       1(%%edx),%%ecx\n\t"     // new sequence = _M._M_data._M_sequence + 1
00097        "lock;  cmpxchg8b  (%%esi)\n\t"
00098        "       jne        L1_%=\n\t"              // We failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00099        "L2_%=: movl       %%edi, %%ebx"
00100       :"=a" (__result), "=d" (__tmp)
00101       :"a" (_M._M_data._M_top), "d" (_M._M_data._M_sequence), "S" (&_M._M_data)
00102       :"edi", "ecx", "memory", "cc");
00103     return __result;
00104   }
00105 
00113   item* clear() {
00114     item*   __result;
00115     int     __tmp;
00116     __asm__ __volatile__
00117       ("       movl       %%ebx, %%edi\n\t"
00118        "L1_%=: testl      %%eax, %%eax\n\t"       // _M_top == NULL?
00119        "       je         L2_%=\n\t"              // If yes, we're done
00120        "       xorl       %%ebx, %%ebx\n\t"       // We're attempting to set _M_top to NULL
00121        "       leal       1(%%edx),%%ecx\n\t"     // new sequence = _M._M_data._M_sequence + 1
00122        "lock;  cmpxchg8b  (%%esi)\n\t"
00123        "       jne        L1_%=\n\t"              // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00124        "L2_%=: movl       %%edi, %%ebx"
00125       :"=a" (__result), "=d" (__tmp)
00126       :"a" (_M._M_data._M_top), "d" (_M._M_data._M_sequence), "S" (&_M._M_data)
00127       :"edi", "ecx", "memory", "cc");
00128     return __result;
00129   }
00130 
00131 private:
00132     union {
00133       long long   _M_align;
00134       struct {
00135         item*           _M_top;         // Topmost element in the freelist
00136         unsigned int    _M_sequence;    // Sequence counter to prevent "ABA problem"
00137       } _M_data;
00138     } _M;
00139 
00140   _STLP_atomic_freelist(const _STLP_atomic_freelist&);
00141   _STLP_atomic_freelist& operator=(const _STLP_atomic_freelist&);
00142 };
00143 
00144 #  endif /* if defined(__GNUC__) && defined(__i386__) */
00145 
00146 #elif defined (_STLP_WIN32THREADS)
00147 
00148 #  if !defined (_WIN64)
00149 #    define _STLP_USE_ASM_IMPLEMENTATION
00150 #  endif
00151 
00152 // Here are the compiler/platform requirements for the thread safe and
00153 // lock free singly linked list implementation:
00154 #  if defined (_STLP_USE_ASM_IMPLEMENTATION)
00155 // For the asm version:
00156 #    if defined (_STLP_MSVC) && defined (_M_IX86) && (_M_IX86 >= 500)
00157 #      define _STLP_HAS_ATOMIC_FREELIST
00158 #    endif
00159 #  else
00160 // For the API based version:
00161 #    if defined (_STLP_NEW_PLATFORM_SDK) && (!defined (WINVER) || (WINVER >= 0x0501)) && \
00162                                             (!defined (_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501))
00163 #      define _STLP_HAS_ATOMIC_FREELIST
00164 #    endif
00165 #  endif
00166 
00167 #  if defined (_STLP_HAS_ATOMIC_FREELIST)
00168 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00169 #      if defined (_STLP_MSVC) && (_STLP_MSVC < 1300) || defined (__ICL)
00170 #        pragma warning (push)
00171 #        pragma warning (disable : 4035) //function has no return value
00172 #      endif
00173 #    endif
00174 
00180 class _STLP_atomic_freelist {
00181 public:
00185 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00186   struct item {
00187       item*   _M_next;
00188   };
00189 #    else
00190   typedef SLIST_ENTRY item;
00191 #    endif
00192 
00193   _STLP_atomic_freelist() {
00194     // Statically assert layout of member is as expected by assembly code
00195 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00196     _STLP_STATIC_ASSERT((sizeof(item) == sizeof(item*)) && (sizeof(_M) == 8))
00197     _M._M_data._M_top       = 0;
00198     _M._M_data._M_sequence  = 0;
00199 #    else
00200     InitializeSListHead(&_M_head);
00201 #    endif
00202   }
00203 
00209   void push(item* __item) {
00210 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00211     __asm
00212     {
00213         mov             esi, this
00214         mov             ebx, __item
00215         mov             eax, [esi]              // _M._M_data._M_top
00216         mov             edx, [esi+4]            // _M._M_data._M_sequence
00217     L1: mov             [ebx], eax              // __item._M_next = _M._M_data._M_top
00218         lea             ecx, [edx+1]            // new sequence = _M._M_data._M_sequence + 1
00219         lock cmpxchg8b  qword ptr [esi]
00220         jne             L1                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00221     }
00222 #    else
00223     InterlockedPushEntrySList(&_M_head, __item);
00224 #    endif
00225   }
00226 
00233   item* pop() {
00234 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00235     __asm
00236     {
00237         mov             esi, this
00238         mov             eax, [esi]              // _M._M_data._M_top
00239         mov             edx, [esi+4]            // _M._M_data._M_sequence
00240     L1: test            eax, eax                // _M_top == NULL?
00241         je              L2                      // Yes, we're done
00242         mov             ebx, [eax]              // new top = _M._M_data._M_top->_M_next
00243         lea             ecx, [edx+1]            // new sequence = _M._M_data._M_sequence + 1
00244         lock cmpxchg8b  qword ptr [esi]
00245         jne             L1                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00246     L2:
00247     }
00248 #    else
00249     return InterlockedPopEntrySList(&_M_head);
00250 #    endif
00251   }
00252 
00260   item* clear() {
00261 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00262     __asm
00263     {
00264         mov             esi, this
00265         mov             eax, [esi]              // _M._M_data._M_top
00266         mov             edx, [esi+4]            // _M._M_data._M_sequence
00267     L1: test            eax, eax                // _M_top == NULL?
00268         je              L2                      // Yes, we're done
00269         xor             ebx,ebx                 // We're attempting to set _M._M_data._M_top to NULL
00270         lea             ecx, [edx+1]            // new sequence = _M._M_data._M_sequence + 1
00271         lock cmpxchg8b  qword ptr [esi]
00272         jne             L1                      // Failed, retry! (edx:eax now contain most recent _M_sequence:_M_top)
00273     L2:
00274     }
00275 #    else
00276     return InterlockedFlushSList(&_M_head);
00277 #    endif
00278   }
00279 
00280 private:
00281 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00282   union {
00283     __int64     _M_align;
00284     struct {
00285       item*           _M_top;         // Topmost element in the freelist
00286       unsigned int    _M_sequence;    // Sequence counter to prevent "ABA problem"
00287     } _M_data;
00288   } _M;
00289 #    else
00290   SLIST_HEADER _M_head;
00291 #    endif
00292 
00293   _STLP_atomic_freelist(const _STLP_atomic_freelist&);
00294   _STLP_atomic_freelist& operator = (const _STLP_atomic_freelist&);
00295 };
00296 
00297 #    if defined (_STLP_USE_ASM_IMPLEMENTATION)
00298 #      if defined (_STLP_MSVC) && (_STLP_MSVC < 1300) || defined (__ICL)
00299 #        pragma warning (pop)
00300 #      endif
00301 #    endif
00302 
00303 #  endif /* _STLP_HAS_ATOMIC_FREELIST */
00304 
00305 #endif
00306 
00307 #endif /* _STLP_LOCK_FREE_SLIST_H */

Generated on Sat May 26 2012 04:34:03 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.