~ubuntu-branches/ubuntu/natty/clamav/natty-security

« back to all changes in this revision

Viewing changes to win32/3rdparty/pthreads/ptw32_InterlockedCompareExchange.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2011-02-19 09:51:33 UTC
  • mfrom: (0.35.19 sid)
  • Revision ID: james.westby@ubuntu.com-20110219095133-sde2dyj8a6bjbkdh
Tags: 0.97+dfsg-0ubuntu1
* Merge from debian unstable (0ubuntu1 because the Debian upload was
  inadvertently left marked UNRELEASED).  Remaining changes:
  - Drop initial signature definitions from clamav-base
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ptw32_InterlockedCompareExchange.c
 
3
 *
 
4
 * Description:
 
5
 * This translation unit implements routines which are private to
 
6
 * the implementation and may be used throughout it.
 
7
 *
 
8
 * --------------------------------------------------------------------------
 
9
 *
 
10
 *      Pthreads-win32 - POSIX Threads Library for Win32
 
11
 *      Copyright(C) 1998 John E. Bossom
 
12
 *      Copyright(C) 1999,2005 Pthreads-win32 contributors
 
13
 * 
 
14
 *      Contact Email: rpj@callisto.canberra.edu.au
 
15
 * 
 
16
 *      The current list of contributors is contained
 
17
 *      in the file CONTRIBUTORS included with the source
 
18
 *      code distribution. The list can also be seen at the
 
19
 *      following World Wide Web location:
 
20
 *      http://sources.redhat.com/pthreads-win32/contributors.html
 
21
 * 
 
22
 *      This library is free software; you can redistribute it and/or
 
23
 *      modify it under the terms of the GNU Lesser General Public
 
24
 *      License as published by the Free Software Foundation; either
 
25
 *      version 2 of the License, or (at your option) any later version.
 
26
 * 
 
27
 *      This library is distributed in the hope that it will be useful,
 
28
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
30
 *      Lesser General Public License for more details.
 
31
 * 
 
32
 *      You should have received a copy of the GNU Lesser General Public
 
33
 *      License along with this library in the file COPYING.LIB;
 
34
 *      if not, write to the Free Software Foundation, Inc.,
 
35
 *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
36
 */
 
37
 
 
38
#ifndef _WIN64
 
39
 
 
40
#include "pthread.h"
 
41
#include "implement.h"
 
42
 
 
43
 
 
44
/*
 
45
 * ptw32_InterlockedCompareExchange --
 
46
 *
 
47
 * Originally needed because W9x doesn't support InterlockedCompareExchange.
 
48
 * We now use this version wherever possible so we can inline it.
 
49
 */
 
50
 
 
51
PTW32_INTERLOCKED_LONG WINAPI
 
52
ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
 
53
                                  PTW32_INTERLOCKED_LONG value,
 
54
                                  PTW32_INTERLOCKED_LONG comparand)
 
55
{
 
56
 
 
57
#if defined(__WATCOMC__)
 
58
/* Don't report that result is not assigned a value before being referenced */
 
59
#pragma disable_message (200)
 
60
#endif
 
61
 
 
62
  PTW32_INTERLOCKED_LONG result;
 
63
 
 
64
  /*
 
65
   * Using the LOCK prefix on uni-processor machines is significantly slower
 
66
   * and it is not necessary. The overhead of the conditional below is
 
67
   * negligible in comparison. Since an optimised DLL will inline this
 
68
   * routine, this will be faster than calling the system supplied
 
69
   * Interlocked routine, which appears to avoid the LOCK prefix on
 
70
   * uniprocessor systems. So one DLL works for all systems.
 
71
   */
 
72
  if (ptw32_smp_system)
 
73
 
 
74
/* *INDENT-OFF* */
 
75
 
 
76
#if defined(_M_IX86) || defined(_X86_)
 
77
 
 
78
#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
 
79
#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
 
80
    {
 
81
      _asm {
 
82
        PUSH         ecx
 
83
        PUSH         edx
 
84
        MOV          ecx,dword ptr [location]
 
85
        MOV          edx,dword ptr [value]
 
86
        MOV          eax,dword ptr [comparand]
 
87
        LOCK CMPXCHG dword ptr [ecx],edx
 
88
        MOV          dword ptr [result], eax
 
89
        POP          edx
 
90
        POP          ecx
 
91
      }
 
92
    }
 
93
  else
 
94
    {
 
95
      _asm {
 
96
        PUSH         ecx
 
97
        PUSH         edx
 
98
        MOV          ecx,dword ptr [location]
 
99
        MOV          edx,dword ptr [value]
 
100
        MOV          eax,dword ptr [comparand]
 
101
        CMPXCHG      dword ptr [ecx],edx
 
102
        MOV          dword ptr [result], eax
 
103
        POP          edx
 
104
        POP          ecx
 
105
      }
 
106
    }
 
107
 
 
108
#elif defined(__GNUC__)
 
109
#define HAVE_INLINABLE_INTERLOCKED_CMPXCHG
 
110
 
 
111
    {
 
112
      __asm__ __volatile__
 
113
        (
 
114
         "lock\n\t"
 
115
         "cmpxchgl       %2,%1"      /* if (EAX == [location])  */
 
116
                                     /*   [location] = value    */
 
117
                                     /* else                    */
 
118
                                     /*   EAX = [location]      */
 
119
         :"=a" (result)
 
120
         :"m"  (*location), "r" (value), "a" (comparand));
 
121
    }
 
122
  else
 
123
    {
 
124
      __asm__ __volatile__
 
125
        (
 
126
         "cmpxchgl       %2,%1"      /* if (EAX == [location])  */
 
127
                                     /*   [location] = value    */
 
128
                                     /* else                    */
 
129
                                     /*   EAX = [location]      */
 
130
         :"=a" (result)
 
131
         :"m"  (*location), "r" (value), "a" (comparand));
 
132
    }
 
133
 
 
134
#endif
 
135
 
 
136
#else
 
137
 
 
138
  /*
 
139
   * If execution gets to here then we're running on a currently
 
140
   * unsupported processor or compiler.
 
141
   */
 
142
 
 
143
#error Unsupported platform or compiler!
 
144
 
 
145
#endif
 
146
 
 
147
/* *INDENT-ON* */
 
148
 
 
149
  return result;
 
150
 
 
151
#if defined(__WATCOMC__)
 
152
#pragma enable_message (200)
 
153
#endif
 
154
 
 
155
}
 
156
 
 
157
/*
 
158
 * ptw32_InterlockedExchange --
 
159
 *
 
160
 * We now use this version wherever possible so we can inline it.
 
161
 */
 
162
 
 
163
LONG WINAPI
 
164
ptw32_InterlockedExchange (LPLONG location,
 
165
                           LONG value)
 
166
{
 
167
 
 
168
#if defined(__WATCOMC__)
 
169
/* Don't report that result is not assigned a value before being referenced */
 
170
#pragma disable_message (200)
 
171
#endif
 
172
 
 
173
  LONG result;
 
174
 
 
175
  /*
 
176
   * The XCHG instruction always locks the bus with or without the
 
177
   * LOCKED prefix. This makes it significantly slower than CMPXCHG on
 
178
   * uni-processor machines. The Windows InterlockedExchange function
 
179
   * is nearly 3 times faster than the XCHG instruction, so this routine
 
180
   * is not yet very useful for speeding up pthreads.
 
181
   */
 
182
  if (ptw32_smp_system)
 
183
 
 
184
/* *INDENT-OFF* */
 
185
 
 
186
#if defined(_M_IX86) || defined(_X86_)
 
187
 
 
188
#if defined(_MSC_VER) || defined(__WATCOMC__) || (defined(__BORLANDC__) && defined(HAVE_TASM32))
 
189
#define HAVE_INLINABLE_INTERLOCKED_XCHG
 
190
 
 
191
    {
 
192
      _asm {
 
193
        PUSH         ecx
 
194
        MOV          ecx,dword ptr [location]
 
195
        MOV          eax,dword ptr [value]
 
196
        XCHG         dword ptr [ecx],eax
 
197
        MOV          dword ptr [result], eax
 
198
        POP          ecx
 
199
      }
 
200
    }
 
201
  else
 
202
    {
 
203
      /*
 
204
       * Faster version of XCHG for uni-processor systems because
 
205
       * it doesn't lock the bus. If an interrupt or context switch
 
206
       * occurs between the MOV and the CMPXCHG then the value in
 
207
       * 'location' may have changed, in which case we will loop
 
208
       * back to do the MOV again.
 
209
       *
 
210
       * FIXME! Need memory barriers for the MOV+CMPXCHG combo?
 
211
       *
 
212
       * Tests show that this routine has almost identical timing
 
213
       * to Win32's InterlockedExchange(), which is much faster than
 
214
       * using the inlined 'xchg' instruction above, so it's probably
 
215
       * doing something similar to this (on UP systems).
 
216
       *
 
217
       * Can we do without the PUSH/POP instructions?
 
218
       */
 
219
      _asm {
 
220
        PUSH         ecx
 
221
        PUSH         edx
 
222
        MOV          ecx,dword ptr [location]
 
223
        MOV          edx,dword ptr [value]
 
224
L1:     MOV          eax,dword ptr [ecx]
 
225
        CMPXCHG      dword ptr [ecx],edx
 
226
        JNZ          L1
 
227
        MOV          dword ptr [result], eax
 
228
        POP          edx
 
229
        POP          ecx
 
230
      }
 
231
    }
 
232
 
 
233
#elif defined(__GNUC__)
 
234
#define HAVE_INLINABLE_INTERLOCKED_XCHG
 
235
 
 
236
    {
 
237
      __asm__ __volatile__
 
238
        (
 
239
         "xchgl          %2,%1"
 
240
         :"=r" (result)
 
241
         :"m"  (*location), "0" (value));
 
242
    }
 
243
  else
 
244
    {
 
245
      /*
 
246
       * Faster version of XCHG for uni-processor systems because
 
247
       * it doesn't lock the bus. If an interrupt or context switch
 
248
       * occurs between the movl and the cmpxchgl then the value in
 
249
       * 'location' may have changed, in which case we will loop
 
250
       * back to do the movl again.
 
251
       *
 
252
       * FIXME! Need memory barriers for the MOV+CMPXCHG combo?
 
253
       *
 
254
       * Tests show that this routine has almost identical timing
 
255
       * to Win32's InterlockedExchange(), and is much faster than
 
256
       * using an inlined 'xchg' instruction, so Win32 is probably
 
257
       * doing something similar to this (on UP systems).
 
258
       */
 
259
      __asm__ __volatile__
 
260
        (
 
261
         "0:\n\t"
 
262
         "movl           %1,%%eax\n\t"
 
263
         "cmpxchgl       %2,%1\n\t"
 
264
         "jnz            0b"
 
265
         :"=&a" (result)
 
266
         :"m"  (*location), "r" (value));
 
267
    }
 
268
 
 
269
#endif
 
270
 
 
271
#else
 
272
 
 
273
  /*
 
274
   * If execution gets to here then we're running on a currently
 
275
   * unsupported processor or compiler.
 
276
   */
 
277
 
 
278
#error Unsupported platform or compiler!
 
279
 
 
280
#endif
 
281
 
 
282
/* *INDENT-ON* */
 
283
 
 
284
  return result;
 
285
 
 
286
#if defined(__WATCOMC__)
 
287
#pragma enable_message (200)
 
288
#endif
 
289
 
 
290
}
 
291
 
 
292
 
 
293
#if 1
 
294
 
 
295
#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_CMPXCHG)
 
296
#undef PTW32_INTERLOCKED_COMPARE_EXCHANGE
 
297
#define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_InterlockedCompareExchange
 
298
#endif
 
299
 
 
300
#if defined(PTW32_BUILD_INLINED) && defined(HAVE_INLINABLE_INTERLOCKED_XCHG)
 
301
#undef PTW32_INTERLOCKED_EXCHANGE
 
302
#define PTW32_INTERLOCKED_EXCHANGE ptw32_InterlockedExchange
 
303
#endif
 
304
 
 
305
#endif
 
306
 
 
307
#endif