More complete implementation of the SetCtrlHandler() function (and the
[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 "windows.h"
11 #include "winbase.h"
12 #include "winerror.h"
13 #include "debug.h"
14
15
16 /*
17  * FIXME: 
18  * The c functions do not protect from non-interlocked accesses
19  * This is no problem as long as we do not have multiple Win32 threads 
20  * or processes. 
21  * The assembly macro's do protect from non-interlocked access,
22  * but they will only work for i386 systems with GCC.  
23  */
24  
25 /************************************************************************
26 *           InterlockedIncrement                        [KERNEL32]      *
27 *                                                                       *
28 * InterlockedIncrement adds 1 to a long variable and returns            *
29 *  -  a negative number if the result < 0                               *
30 *  -  zero if the result == 0                                           *
31 *  -  a positive number if the result > 0                               *
32 *                                                                       *
33 * The returned number need not be equal to the result!!!!               *
34 ************************************************************************/
35
36 LONG WINAPI InterlockedIncrement(LPLONG lpAddend)
37 {
38 #if defined(__i386__)&&defined(__GNUC__)
39         long ret;
40         __asm__
41         (                
42            "\tlock\n"   /* for SMP systems */
43            "\tincl      (%1)\n"
44            "\tje        2f\n"
45            "\tjl        1f\n"
46            "\tincl      %0\n"
47            "\tjmp       2f\n"
48            "1:\tdec     %0\n"             
49            "2:\n"
50            :"=r" (ret):"r" (lpAddend), "0" (0): "memory"
51         );
52         return ret;
53 #else      
54         LONG ret;
55         /* StopAllThreadsAndProcesses() */
56         
57         (*lpAddend)++;
58         ret=*lpAddend;
59
60         /* ResumeAllThreadsAndProcesses() */
61         return ret;
62 #endif   
63 }
64
65 /************************************************************************
66 *           InterlockedDecrement                        [KERNEL32]      *
67 *                                                                       *
68 * InterlockedIncrement adds 1 to a long variable and returns            *
69 *  -  a negative number if the result < 0                               *
70 *  -  zero if the result == 0                                           *
71 *  -  a positive number if the result > 0                               *
72 *                                                                       *
73 * The returned number need not be equal to the result!!!!               *
74 ************************************************************************/
75
76 LONG WINAPI InterlockedDecrement(LPLONG lpAddend)
77 {
78 #if defined(__i386__)&&defined(__GNUC__)        
79         LONG ret;
80         __asm__
81         (                
82            "\tlock\n"   /* for SMP systems */
83            "\tdecl      (%1)\n"
84            "\tje        2f\n"
85            "\tjl        1f\n"
86            "\tincl      %0\n"
87            "\tjmp       2f\n"
88            "1:\tdec     %0\n"             
89            "2:\n"
90            :"=r" (ret):"r" (lpAddend), "0" (0): "memory"          
91         );
92         return ret;
93 #else   
94         LONG ret;
95         /* StopAllThreadsAndProcesses() */
96
97         (*lpAddend)--;
98         ret=*lpAddend;
99
100         /* ResumeAllThreadsAndProcesses() */
101         return ret;
102 #endif  
103 }
104
105 /************************************************************************
106  *           InterlockedExchange                                [KERNEL32.???]
107  *
108  * Atomically exchanges a pair of values.
109  *
110  * RETURNS
111  *      Prior value of value pointed to by Target
112  */
113 LONG WINAPI InterlockedExchange(
114             LPLONG target, /* Address of 32-bit value to exchange */
115             LONG value     /* New value for the value pointed to by target */
116 ) {
117 #if defined(__i386__)&&defined(__GNUC__)        
118         LONG ret;
119         __asm__ ( /* lock for SMP systems */
120                   "lock\n\txchgl %0,(%1)"
121                   :"=r" (ret):"r" (target), "0" (value):"memory" );
122         return ret;
123 #else
124         LONG ret;
125         /* StopAllThreadsAndProcesses() */      
126
127         ret=*target;
128         *target=value;
129
130         /* ResumeAllThreadsAndProcesses() */
131         return ret;
132 #endif  
133 }