Only append .dll if no extension yet.
[wine] / win32 / thread.c
1 /*
2  * Win32 kernel functions
3  *
4  * Copyright 1995 Martin von Loewis
5  * Copyright 1997 Onno Hovers
6  */
7
8 #include <unistd.h>
9 #include <string.h>
10 #include "wintypes.h"
11 #include "winerror.h"
12 #include "debug.h"
13
14
15 /*
16  * FIXME: 
17  * The c functions do not protect from non-interlocked accesses
18  * This is no problem as long as we do not have multiple Win32 threads 
19  * or processes. 
20  * The assembly macro's do protect from non-interlocked access,
21  * but they will only work for i386 systems with GCC.  
22  */
23  
24 /************************************************************************
25 *           InterlockedIncrement                        [KERNEL32]      *
26 *                                                                       *
27 * InterlockedIncrement adds 1 to a long variable and returns            *
28 *  -  a negative number if the result < 0                               *
29 *  -  zero if the result == 0                                           *
30 *  -  a positive number if the result > 0                               *
31 *                                                                       *
32 * The returned number need not be equal to the result!!!!               *
33 ************************************************************************/
34
35 LONG WINAPI InterlockedIncrement(LPLONG lpAddend)
36 {
37 #if defined(__i386__)&&defined(__GNUC__)
38         long ret;
39         __asm__
40         (                
41            "\tlock\n"   /* for SMP systems */
42            "\tincl      (%1)\n"
43            "\tje        2f\n"
44            "\tjl        1f\n"
45            "\tincl      %0\n"
46            "\tjmp       2f\n"
47            "1:\tdec     %0\n"             
48            "2:\n"
49            :"=r" (ret):"r" (lpAddend), "0" (0): "memory"
50         );
51         return ret;
52 #else      
53         LONG ret;
54         /* StopAllThreadsAndProcesses() */
55         
56         (*lpAddend)++;
57         ret=*lpAddend;
58
59         /* ResumeAllThreadsAndProcesses() */
60         return ret;
61 #endif   
62 }
63
64 /************************************************************************
65 *           InterlockedDecrement                        [KERNEL32]      *
66 *                                                                       *
67 * InterlockedIncrement adds 1 to a long variable and returns            *
68 *  -  a negative number if the result < 0                               *
69 *  -  zero if the result == 0                                           *
70 *  -  a positive number if the result > 0                               *
71 *                                                                       *
72 * The returned number need not be equal to the result!!!!               *
73 ************************************************************************/
74
75 LONG WINAPI InterlockedDecrement(LPLONG lpAddend)
76 {
77 #if defined(__i386__)&&defined(__GNUC__)        
78         LONG ret;
79         __asm__
80         (                
81            "\tlock\n"   /* for SMP systems */
82            "\tdecl      (%1)\n"
83            "\tje        2f\n"
84            "\tjl        1f\n"
85            "\tincl      %0\n"
86            "\tjmp       2f\n"
87            "1:\tdec     %0\n"             
88            "2:\n"
89            :"=r" (ret):"r" (lpAddend), "0" (0): "memory"          
90         );
91         return ret;
92 #else   
93         LONG ret;
94         /* StopAllThreadsAndProcesses() */
95
96         (*lpAddend)--;
97         ret=*lpAddend;
98
99         /* ResumeAllThreadsAndProcesses() */
100         return ret;
101 #endif  
102 }
103
104 /************************************************************************
105  *           InterlockedExchange                                [KERNEL32.???]
106  *
107  * Atomically exchanges a pair of values.
108  *
109  * RETURNS
110  *      Prior value of value pointed to by Target
111  */
112 LONG WINAPI InterlockedExchange(
113             LPLONG target, /* Address of 32-bit value to exchange */
114             LONG value     /* New value for the value pointed to by target */
115 ) {
116 #if defined(__i386__)&&defined(__GNUC__)        
117         LONG ret;
118         __asm__ ( /* lock for SMP systems */
119                   "lock\n\txchgl %0,(%1)"
120                   :"=r" (ret):"r" (target), "0" (value):"memory" );
121         return ret;
122 #else
123         LONG ret;
124         /* StopAllThreadsAndProcesses() */      
125
126         ret=*target;
127         *target=value;
128
129         /* ResumeAllThreadsAndProcesses() */
130         return ret;
131 #endif  
132 }
133
134 /************************************************************************
135  *           InterlockedCompareExchange         [KERNEL32.879]
136  *
137  * Atomically compares Destination and Comperand, and if found equal exchanges
138  * the value of Destination with Exchange
139  *
140  * RETURNS
141  *      Prior value of value pointed to by Destination
142  */
143 PVOID WINAPI InterlockedCompareExchange(
144             PVOID *Destination, /* Address of 32-bit value to exchange */
145             PVOID Exchange,      /* change value, 32 bits */ 
146             PVOID Comperand      /* value to compare, 32 bits */
147 ) {
148 #if defined(__i386__)&&defined(__GNUC__)        
149         PVOID ret;
150         __asm__ ( /* lock for SMP systems */
151                   "lock\n\t"
152                   "cmpxchgl %2,(%1)"
153                   :"=r" (ret)
154                   :"r" (Destination),"r" (Exchange), "0" (Comperand)
155                   :"memory" );
156         return ret;
157 #else
158         PVOID ret;
159         /* StopAllThreadsAndProcesses() */      
160
161         ret=*Destination;
162         if(*Destination==Comperand) *Destination=Exchange;
163
164         /* ResumeAllThreadsAndProcesses() */
165         return ret;
166 #endif  
167 }
168
169 /************************************************************************
170  *           InterlockedExchangeAdd                     [KERNEL32.880]
171  *
172  * Atomically adds Increment to Addend and returns the previous value of
173  * Addend
174  *
175  * RETURNS
176  *      Prior value of value pointed to by cwAddendTarget
177  */
178 LONG WINAPI InterlockedExchangeAdd(
179             PLONG Addend, /* Address of 32-bit value to exchange */
180             LONG Increment /* Value to add */
181 ) {
182 #if defined(__i386__)&&defined(__GNUC__)        
183         LONG ret;
184         __asm__ ( /* lock for SMP systems */
185                   "lock\n\t"
186                   "xaddl %0,(%1)"
187                   :"=r" (ret)
188                   :"r" (Addend), "0" (Increment)
189                   :"memory" );
190         return ret;
191 #else
192         LONG ret;
193         /* StopAllThreadsAndProcesses() */      
194
195         ret = *Addend;
196         *Addend += Increment;
197
198         /* ResumeAllThreadsAndProcesses() */
199         return ret;
200 #endif  
201 }