BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI_RT / src / RTwinnt.c
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * $Id: RTwinnt.c,v 1.10 2005/02/25 07:04:48 jaw Exp $
44  * RTwinnt.c: runtime instrumentation functions for Windows NT
45  ************************************************************************/
46 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
47 #if !defined (EXPORT_SPINLOCKS_AS_HEADER)
48 /* everything should be under this flag except for the assembly code
49    that handles the runtime spinlocks  -- this is imported into the
50    test suite for direct testing */
51
52
53 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
54 #include <assert.h>
55 #endif
56 #include <stdio.h>
57 #include <stdlib.h>
58 //#define WIN32_LEAN_AND_MEAN
59 #include <windows.h>
60 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
61 #include <mmsystem.h>
62 #include <errno.h>
63 #include <limits.h>
64 #endif
65 #include <process.h>
66 #include <fcntl.h>
67 #include <sys/types.h>
68 #include <sys/stat.h>
69 #include <io.h>
70 #include <stdio.h>
71 //#include <winsock2.h>
72
73 /************************************************************************
74  * void DYNINSTbreakPoint(void)
75  *
76  * stop oneself.
77 ************************************************************************/
78
79 void
80 DYNINSTbreakPoint(void) {
81   /* TODO: how do we stop all threads? */
82   DebugBreak();
83 }
84
85
86 void DYNINSTos_init(int calledByFork, int calledByAttach)
87 {
88 #ifndef mips_unknown_ce2_11 //ccw 23 july 2001
89   RTprintf("DYNINSTos_init(%d,%d)\n", calledByFork, calledByAttach);
90 #endif
91 }
92
93 char gLoadLibraryErrorString[ERROR_STRING_LENGTH];
94 int DYNINSTloadLibrary(char *libname)
95 {
96     HMODULE res;
97     gLoadLibraryErrorString[0] = '\0';
98     //fprintf(stderr, "Attempting to load %s\n", libname);
99     
100     res = LoadLibrary(libname);
101     if (res == NULL) {
102         perror("DYNINSTloadLibrary - load of library failed");
103         return 0;
104     }
105     return 1;
106 }
107 int DYNINSTwriteEvent(void *ev, int sz);
108 /************************************************************************
109  * void DYNINSTasyncConnect(int pid)
110  *
111  * Connect to mutator's async handler thread. <pid> is pid of mutator
112 ************************************************************************/
113 //CRITICAL_SECTION comms_mutex;
114 dyninst_spinlock thelock;
115 int async_socket = -1;
116 int connect_port = 0;
117 int DYNINSTasyncConnect()
118 {
119
120   int sock_fd;
121   struct sockaddr_in sadr;
122   struct in_addr *inadr;
123   struct hostent *hostptr;
124   WORD wsversion = MAKEWORD(2,0);
125   WSADATA wsadata;
126   rtBPatch_asyncEventRecord ev;
127
128   fprintf(stderr, "%s[%d]:  inside DYNINSTasyncConnect\n", __FILE__, __LINE__);
129   if (0 == connect_port) {
130     fprintf(stderr, "%s[%d]:  DYNINSTasyncConnect, no port no\n",
131             __FILE__, __LINE__);
132     abort() ;
133   }
134
135   WSAStartup(wsversion, &wsadata);
136
137   fprintf(stderr, "%s[%d]:  inside DYNINSTasyncConnect before gethostbyname\n", __FILE__, __LINE__);
138   hostptr = gethostbyname("localhost");
139   inadr = (struct in_addr *) ((void*) hostptr->h_addr_list[0]);
140   fprintf(stderr, "%s[%d]:  inside DYNINSTasyncConnect before memset\n", __FILE__, __LINE__);
141   memset((void*) &sadr, 0, sizeof(sadr));
142   sadr.sin_family = PF_INET;
143   sadr.sin_port = htons((u_short)connect_port);
144   sadr.sin_addr = *inadr;
145
146   fprintf(stderr, "%s[%d]:   DYNINSTasyncConnect before socket\n", __FILE__, __LINE__);
147   sock_fd = socket(PF_INET, SOCK_STREAM, 0);
148   if (sock_fd == INVALID_SOCKET) {
149     fprintf(stderr, "DYNINST: socket failed: %d\n", WSAGetLastError());
150     abort();
151   }
152
153   fprintf(stderr, "%s[%d]:   DYNINSTasyncConnect before connect\n", __FILE__, __LINE__);
154   if (connect(sock_fd, (struct sockaddr *) &sadr, sizeof(sadr)) == SOCKET_ERROR) {
155     fprintf(stderr, "DYNINSTasyncConnect: connect failed: %d\n", WSAGetLastError());
156     abort();
157   }
158
159   /* maybe need to do fcntl to set nonblocking writes on this fd */
160
161   async_socket = sock_fd;
162
163   fprintf(stderr, "%s[%d]:   DYNINSTasyncConnect before write\n", __FILE__, __LINE__);
164   /* after connecting, we need to send along our pid */
165   ev.type = rtBPatch_newConnectionEvent;
166   ev.pid = _getpid();
167   if (!DYNINSTwriteEvent((void *) &ev, sizeof(rtBPatch_asyncEventRecord))) {
168     fprintf(stderr, "%s[%d]:  DYNINSTwriteEventFailed\n", __FILE__, __LINE__);
169   }
170   /* initialize comms mutex */
171
172   //InitializeCriticalSection(&comms_mutex);
173   //fprintf(stderr, "%s[%d]: DYNINSTasyncConnect appears to have succeeded\n", __FILE__, __LINE__);
174   thelock.lock = 0;
175   fprintf(stderr, "%s[%d]:  leaving DYNINSTasyncConnect\n", __FILE__, __LINE__);
176   return 1; /*true*/
177 }
178
179 int DYNINSTasyncDisconnect()
180 {
181   return _close (async_socket);
182 }
183
184 int DYNINSTwriteEvent(void *ev, int sz)
185 {
186   if (send((SOCKET)async_socket, ev, sz, 0) != sz) {
187     printf("DYNINSTwriteTrace: send error %d, %d %d\n",
188            WSAGetLastError(), sz, async_socket);
189     if (async_socket == -1)
190       return 1;
191     return 0;
192   }
193   return 1;
194
195 #ifdef NOTDEF
196   int res;
197
198 try_again:
199   res = write(async_socket, ev, sz);
200   if (-1 == res) {
201     if (errno == EINTR || errno == EAGAIN)
202        goto try_again;
203     else {
204        perror("write");
205        abort();
206     }
207   }
208   if (res != sz) {
209     /*  maybe we need logic to handle partial writes? */
210     fprintf(stderr, "%s[%d]:  partial ? write error, %d bytes, should be %d\n",
211             __FILE__, __LINE__, res, sz);
212     abort();
213   }
214   return res;
215 #endif
216 }
217 void DYNINSTlock_spinlock(dyninst_spinlock *mut);
218 extern void DYNINSTunlock_spinlock(dyninst_spinlock *mut);
219 void LockCommsMutex()
220 {
221   //fprintf(stderr, "%s[%d]:  before enter crit\n", __FILE__, __LINE__);
222   //EnterCriticalSection(&comms_mutex);
223   //fprintf(stderr, "%s[%d]:  after enter crit\n", __FILE__, __LINE__);
224   DYNINSTlock_spinlock(&thelock);
225 }
226 void UnlockCommsMutex()
227 {
228   //fprintf(stderr, "%s[%d]:  before leave crit\n", __FILE__, __LINE__);
229   //LeaveCriticalSection(&comms_mutex);
230   //fprintf(stderr, "%s[%d]:  after leave crit\n", __FILE__, __LINE__);
231   DYNINSTunlock_spinlock(&thelock);
232 }
233 #endif /* EXPORT SPINLOCKS */
234 void DYNINSTlock_spinlock(dyninst_spinlock *mut)
235 {
236   /*  same assembly as for x86 linux, just different format for asm stmt */
237   /*  so if you change one, make the same changes in the other, please */
238   /*msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref___asm.asp*/
239
240  /* seperate command to get arg into ecx */
241  __asm mov ecx,mut 
242
243  /* thus this should work whether or not we compiler with __fastcall */
244  /* (which passes args in registers instead of on the stack */
245
246  __asm  {
247            a_loop:
248                                           ; movl        8(%ebp), %ecx
249            mov        eax,0 ;
250            mov        edx,1 ;
251            lock cmpxchg   [ecx], edx ;
252
253            jnz         a_loop
254      }
255
256 }
257