summaryrefslogtreecommitdiff
path: root/lang/mono/patches/patch-aj
blob: 72e9e3d3ddd6c3a612927398192c609e8260b8f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
$NetBSD: patch-aj,v 1.4 2005/07/31 15:26:58 recht Exp $

--- libgc/pthread_stop_world.c.orig	2005-07-05 20:46:03.000000000 +0200
+++ libgc/pthread_stop_world.c
@@ -99,6 +99,7 @@ word GC_stop_count;	/* Incremented at th
 #  endif
 #endif
 
+#if !defined(GC_NETBSD_THREADS)
 sem_t GC_suspend_ack_sem;
 
 static void _GC_suspend_handler(int sig)
@@ -208,6 +209,7 @@ static void _GC_restart_handler(int sig)
     GC_printf1("In GC_restart_handler for 0x%lx\n", pthread_self());
 #endif
 }
+#endif /* !GC_NETBSD_THREADS */
 
 # ifdef IA64
 #   define IF_IA64(x) x
@@ -283,12 +285,14 @@ static void pthread_push_all_stacks()
       ABORT("Collecting from unknown thread.");
 }
 
+#if !defined(GC_NETBSD_THREADS)
 void GC_restart_handler(int sig)
 {
 	int old_errno = errno;
 	_GC_restart_handler (sig);
 	errno = old_errno;
 }
+#endif
 
 /* We hold allocation lock.  Should do exactly the right thing if the	*/
 /* world is stopped.  Should not fail if it isn't.			*/
@@ -297,6 +301,28 @@ void GC_push_all_stacks()
     gc_thread_vtable->push_all_stacks();
 }
 
+#if defined(GC_NETBSD_THREADS)
+/* 
+ * Get the stack start address for the specified address.
+ */ 
+int 
+np_stackinfo(pthread_t p, void **addr) 
+{ 
+	pthread_attr_t attr; 
+	int ret = -1; 
+
+	if (pthread_attr_init(&attr)) 
+		return -1;
+
+	if (!pthread_attr_get_np(p, &attr))
+		if (!pthread_attr_getstackaddr(&attr, addr)) 
+			ret = 0;
+
+	pthread_attr_destroy(&attr); 
+	return ret; 
+}
+#endif
+
 /* There seems to be a very rare thread stopping problem.  To help us  */
 /* debug that, we save the ids of the stopping thread. */
 pthread_t GC_stopping_thread;
@@ -322,6 +348,7 @@ int GC_suspend_all()
             if (p -> stop_info.last_stop_count == GC_stop_count) continue;
 	    if (p -> thread_blocked) /* Will wait */ continue;
             n_live_threads++;
+#if !defined(GC_NETBSD_THREADS)
 	    #if DEBUG_THREADS
 	      GC_printf1("Sending suspend signal to 0x%lx\n", p -> id);
 	    #endif
@@ -337,6 +364,23 @@ int GC_suspend_all()
                 default:
                     ABORT("pthread_kill failed");
             }
+#else
+	    #if DEBUG_THREADS
+	      GC_printf1("Suspending 0x%lx ...\n", p -> id);
+	    #endif
+
+		if(pthread_suspend_np(p -> id) != 0)
+			GC_printf1("Could not susend thread... 0x%lx\n", p -> id);
+
+		/* Right now, this is not enough. Retreiving the stack base address is not the correct */
+		/* info to give to the GC, but since there is no way to get the current stack pointer  */
+		/* for the suspended thread, base pointer will have to be enough. Mono seems to be     */
+		/* happy with it so... */
+		if(np_stackinfo(p -> id, &(p -> stop_info.stack_ptr)) != 0)
+			GC_err_printf1("Could not get thread stack address... 0x%lx\n", p -> id);			
+
+        n_live_threads--;
+#endif /* !GC_NETBSD_THREADS */
         }
       }
     }
@@ -356,6 +400,7 @@ static void pthread_stop_world()
        
     n_live_threads = GC_suspend_all();
 
+#if !defined(GC_NETBSD_THREADS)
       if (GC_retry_signals) {
 	  unsigned long wait_usecs = 0;  /* Total wait since retry.	*/
 #	  define WAIT_UNIT 3000
@@ -393,6 +438,8 @@ static void pthread_stop_world()
 	      }
 	  }
     }
+#endif /* !GC_NETBSD_THREADS */
+
     #if DEBUG_THREADS
       GC_printf1("World stopped from 0x%lx\n", pthread_self());
     #endif
@@ -439,6 +486,7 @@ static void pthread_start_world()
             if (p -> flags & FINISHED) continue;
 	    if (p -> thread_blocked) continue;
             n_live_threads++;
+#if !defined(GC_NETBSD_THREADS)
 	    #if DEBUG_THREADS
 	      GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
 	    #endif
@@ -454,10 +502,18 @@ static void pthread_start_world()
                 default:
                     ABORT("pthread_kill failed");
             }
+#else
+	    #if DEBUG_THREADS
+	      GC_printf1("Resuming Thread 0x%lx\n", p -> id);
+	    #endif
+		pthread_resume_np(p -> id);
+		n_live_threads--;
+#endif /* !GC_NETBSD_THREADS */
         }
       }
     }
 
+#if !defined(GC_NETBSD_THREADS)
     #if DEBUG_THREADS
     GC_printf0 ("All threads signaled");
     #endif
@@ -470,6 +526,7 @@ static void pthread_start_world()
 	    }
 	}
     }
+#endif /* !GC_NETBSD_THREADS */
   
     #if DEBUG_THREADS
       GC_printf0("World started\n");
@@ -482,6 +539,8 @@ void GC_start_world()
 }
 
 static void pthread_stop_init() {
+
+#if !defined(GC_NETBSD_THREADS)
     struct sigaction act;
     
     if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
@@ -522,6 +581,16 @@ static void pthread_stop_init() {
               GC_printf0("Will retry suspend signal if necessary.\n");
 	  }
 #     endif
+#else
+    struct sigaction act;
+
+    act.sa_flags = SA_RESTART;
+    if (sigfillset(&act.sa_mask) != 0) {
+    	ABORT("sigfillset() failed");
+    }
+    GC_remove_allowed_signals(&act.sa_mask);
+
+#endif /* !GC_NETBSD_THREADS */
 }
 
 /* We hold the allocation lock.	*/