~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to darwin_stop_world.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
   be allocated, is called the red zone. This area as shown in Figure 3-2 may
11
11
   be used for any purpose as long as a new stack frame does not need to be
12
12
   added to the stack."
13
 
   
 
13
 
14
14
   Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
15
15
   it must set up a stack frame just like routines that call other routines."
16
16
*/
30
30
  unsigned long savedRTOC;
31
31
} StackFrame;
32
32
 
33
 
unsigned long FindTopOfStack(unsigned int stack_start) {
 
33
unsigned long FindTopOfStack(unsigned long stack_start)
 
34
{
34
35
  StackFrame    *frame;
35
 
  
 
36
 
36
37
  if (stack_start == 0) {
37
38
# ifdef POWERPC
38
39
#   if CPP_WORDSZ == 32
46
47
  }
47
48
 
48
49
# ifdef DEBUG_THREADS
49
 
    /* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */
 
50
    /* GC_printf("FindTopOfStack start at sp = %p\n", frame); */
50
51
# endif
51
52
  do {
52
 
    if (frame->savedSP == 0) break;
53
 
                /* if there are no more stack frames, stop */
 
53
    if (frame->savedSP == 0)
 
54
      break;
 
55
    /* if there are no more stack frames, stop */
54
56
 
55
57
    frame = (StackFrame*)frame->savedSP;
56
58
 
57
59
    /* we do these next two checks after going to the next frame
58
60
       because the LR for the first stack frame in the loop
59
61
       is not set up on purpose, so we shouldn't check it. */
60
 
    if ((frame->savedLR & ~3) == 0) break; /* if the next LR is bogus, stop */
61
 
    if ((~(frame->savedLR) & ~3) == 0) break; /* ditto */
62
 
  } while (1); 
 
62
    if ((frame->savedLR & ~3) == 0)
 
63
      break; /* if the next LR is bogus, stop */
 
64
    if ((~(frame->savedLR) & ~3) == 0)
 
65
      break; /* ditto */
 
66
  } while (1);
63
67
 
64
68
# ifdef DEBUG_THREADS
65
 
    /* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */
 
69
    /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */
66
70
# endif
67
71
 
68
72
  return (unsigned long)frame;
69
 
}       
 
73
}
70
74
 
71
75
#ifdef DARWIN_DONT_PARSE_STACK
72
 
void GC_push_all_stacks() {
 
76
void GC_push_all_stacks()
 
77
{
73
78
  int i;
74
79
  kern_return_t r;
75
80
  GC_thread p;
76
81
  pthread_t me;
77
82
  ptr_t lo, hi;
78
 
#if defined(POWERPC)
79
 
  ppc_thread_state_t state;
80
 
#elif defined(I386)
81
 
  i386_thread_state_t state;
82
 
#else
83
 
# error FIXME for non-x86 || ppc architectures
84
 
#endif
85
 
  mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
86
 
  
 
83
  GC_THREAD_STATE_T state;
 
84
  /* MACHINE_THREAD_STATE_COUNT doesn't seem to be defined everywhere.  */
 
85
  /* Hence we use our own version.                                      */
 
86
  mach_msg_type_number_t thread_state_count = GC_MACH_THREAD_STATE_COUNT;
 
87
 
87
88
  me = pthread_self();
88
 
  if (!GC_thr_initialized) GC_thr_init();
89
 
  
90
 
  for(i=0;i<THREAD_TABLE_SZ;i++) {
91
 
    for(p=GC_threads[i];p!=0;p=p->next) {
92
 
      if(p -> flags & FINISHED) continue;
93
 
      if(pthread_equal(p->id,me)) {
 
89
  if (!GC_thr_initialized)
 
90
    GC_thr_init();
 
91
 
 
92
  for(i = 0; i < THREAD_TABLE_SZ; i++) {
 
93
    for(p = GC_threads[i]; p != 0; p = p->next) {
 
94
      if(p->flags & FINISHED) continue;
 
95
      if(pthread_equal(p->id, me)) {
94
96
        lo = GC_approx_sp();
95
97
      } else {
96
98
        /* Get the thread state (registers, etc) */
97
 
        r = thread_get_state(
98
 
                             p->stop_info.mach_thread,
99
 
                             MACHINE_THREAD_STATE,
100
 
                             (natural_t*)&state,
101
 
                             &thread_state_count);
102
 
        if(r != KERN_SUCCESS) ABORT("thread_get_state failed");
103
 
        
104
 
#if defined(I386)
105
 
        lo = state.esp;
106
 
 
107
 
        GC_push_one(state.eax); 
108
 
        GC_push_one(state.ebx); 
109
 
        GC_push_one(state.ecx); 
110
 
        GC_push_one(state.edx); 
111
 
        GC_push_one(state.edi); 
112
 
        GC_push_one(state.esi); 
113
 
        GC_push_one(state.ebp); 
114
 
#elif defined(POWERPC)
115
 
        lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
116
 
        
117
 
        GC_push_one(state.r0); 
118
 
        GC_push_one(state.r2); 
119
 
        GC_push_one(state.r3); 
120
 
        GC_push_one(state.r4); 
121
 
        GC_push_one(state.r5); 
122
 
        GC_push_one(state.r6); 
123
 
        GC_push_one(state.r7); 
124
 
        GC_push_one(state.r8); 
125
 
        GC_push_one(state.r9); 
126
 
        GC_push_one(state.r10); 
127
 
        GC_push_one(state.r11); 
128
 
        GC_push_one(state.r12); 
129
 
        GC_push_one(state.r13); 
130
 
        GC_push_one(state.r14); 
131
 
        GC_push_one(state.r15); 
132
 
        GC_push_one(state.r16); 
133
 
        GC_push_one(state.r17); 
134
 
        GC_push_one(state.r18); 
135
 
        GC_push_one(state.r19); 
136
 
        GC_push_one(state.r20); 
137
 
        GC_push_one(state.r21); 
138
 
        GC_push_one(state.r22); 
139
 
        GC_push_one(state.r23); 
140
 
        GC_push_one(state.r24); 
141
 
        GC_push_one(state.r25); 
142
 
        GC_push_one(state.r26); 
143
 
        GC_push_one(state.r27); 
144
 
        GC_push_one(state.r28); 
145
 
        GC_push_one(state.r29); 
146
 
        GC_push_one(state.r30); 
147
 
        GC_push_one(state.r31);
148
 
#else
149
 
# error FIXME for non-x86 || ppc architectures
150
 
#endif
 
99
        r = thread_get_state(p->stop_info.mach_thread, GC_MACH_THREAD_STATE,
 
100
                             (natural_t*)&state, &thread_state_count);
 
101
 
 
102
#       ifdef DEBUG_THREADS
 
103
          GC_printf("thread_get_state return value = %d\n", r);
 
104
#       endif
 
105
 
 
106
        if(r != KERN_SUCCESS)
 
107
          ABORT("thread_get_state failed");
 
108
 
 
109
#       if defined(I386)
 
110
          lo = (void*)state . THREAD_FLD (esp);
 
111
          GC_push_one(state . THREAD_FLD (eax));
 
112
          GC_push_one(state . THREAD_FLD (ebx));
 
113
          GC_push_one(state . THREAD_FLD (ecx));
 
114
          GC_push_one(state . THREAD_FLD (edx));
 
115
          GC_push_one(state . THREAD_FLD (edi));
 
116
          GC_push_one(state . THREAD_FLD (esi));
 
117
          GC_push_one(state . THREAD_FLD (ebp));
 
118
 
 
119
#       elif defined(X86_64)
 
120
          lo = (void*)state . THREAD_FLD (rsp);
 
121
          GC_push_one(state . THREAD_FLD (rax));
 
122
          GC_push_one(state . THREAD_FLD (rbx));
 
123
          GC_push_one(state . THREAD_FLD (rcx));
 
124
          GC_push_one(state . THREAD_FLD (rdx));
 
125
          GC_push_one(state . THREAD_FLD (rdi));
 
126
          GC_push_one(state . THREAD_FLD (rsi));
 
127
          GC_push_one(state . THREAD_FLD (rbp));
 
128
          GC_push_one(state . THREAD_FLD (rsp));
 
129
          GC_push_one(state . THREAD_FLD (r8));
 
130
          GC_push_one(state . THREAD_FLD (r9));
 
131
          GC_push_one(state . THREAD_FLD (r10));
 
132
          GC_push_one(state . THREAD_FLD (r11));
 
133
          GC_push_one(state . THREAD_FLD (r12));
 
134
          GC_push_one(state . THREAD_FLD (r13));
 
135
          GC_push_one(state . THREAD_FLD (r14));
 
136
          GC_push_one(state . THREAD_FLD (r15));
 
137
          GC_push_one(state . THREAD_FLD (rip));
 
138
          GC_push_one(state . THREAD_FLD (rflags));
 
139
          GC_push_one(state . THREAD_FLD (cs));
 
140
          GC_push_one(state . THREAD_FLD (fs));
 
141
          GC_push_one(state . THREAD_FLD (gs));
 
142
 
 
143
#       elif defined(POWERPC)
 
144
          lo = (void*)(state . THREAD_FLD (r1) - PPC_RED_ZONE_SIZE);
 
145
 
 
146
          GC_push_one(state . THREAD_FLD (r0));
 
147
          GC_push_one(state . THREAD_FLD (r2));
 
148
          GC_push_one(state . THREAD_FLD (r3));
 
149
          GC_push_one(state . THREAD_FLD (r4));
 
150
          GC_push_one(state . THREAD_FLD (r5));
 
151
          GC_push_one(state . THREAD_FLD (r6));
 
152
          GC_push_one(state . THREAD_FLD (r7));
 
153
          GC_push_one(state . THREAD_FLD (r8));
 
154
          GC_push_one(state . THREAD_FLD (r9));
 
155
          GC_push_one(state . THREAD_FLD (r10));
 
156
          GC_push_one(state . THREAD_FLD (r11));
 
157
          GC_push_one(state . THREAD_FLD (r12));
 
158
          GC_push_one(state . THREAD_FLD (r13));
 
159
          GC_push_one(state . THREAD_FLD (r14));
 
160
          GC_push_one(state . THREAD_FLD (r15));
 
161
          GC_push_one(state . THREAD_FLD (r16));
 
162
          GC_push_one(state . THREAD_FLD (r17));
 
163
          GC_push_one(state . THREAD_FLD (r18));
 
164
          GC_push_one(state . THREAD_FLD (r19));
 
165
          GC_push_one(state . THREAD_FLD (r20));
 
166
          GC_push_one(state . THREAD_FLD (r21));
 
167
          GC_push_one(state . THREAD_FLD (r22));
 
168
          GC_push_one(state . THREAD_FLD (r23));
 
169
          GC_push_one(state . THREAD_FLD (r24));
 
170
          GC_push_one(state . THREAD_FLD (r25));
 
171
          GC_push_one(state . THREAD_FLD (r26));
 
172
          GC_push_one(state . THREAD_FLD (r27));
 
173
          GC_push_one(state . THREAD_FLD (r28));
 
174
          GC_push_one(state . THREAD_FLD (r29));
 
175
          GC_push_one(state . THREAD_FLD (r30));
 
176
          GC_push_one(state . THREAD_FLD (r31));
 
177
#       else
 
178
#         error FIXME for non-x86 || ppc architectures
 
179
#       endif
151
180
      } /* p != me */
152
181
      if(p->flags & MAIN_THREAD)
153
182
        hi = GC_stackbottom;
154
183
      else
155
184
        hi = p->stack_end;
156
 
#if DEBUG_THREADS
157
 
      GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
158
 
                 (unsigned long) p -> id,
159
 
                 (unsigned long) lo,
160
 
                 (unsigned long) hi
161
 
                 );
162
 
#endif
163
 
      GC_push_all_stack(lo,hi);
 
185
#     if DEBUG_THREADS
 
186
        GC_printf("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
 
187
                  (unsigned long) p -> id, (unsigned long) lo,
 
188
                  (unsigned long) hi);
 
189
#     endif
 
190
      GC_push_all_stack(lo, hi);
164
191
    } /* for(p=GC_threads[i]...) */
165
192
  } /* for(i=0;i<THREAD_TABLE_SZ...) */
166
193
}
167
194
 
168
195
#else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */
169
196
 
170
 
void GC_push_all_stacks() {
171
 
    int i;
172
 
        task_t my_task;
173
 
    kern_return_t r;
174
 
    mach_port_t me;
175
 
    ptr_t lo, hi;
176
 
    thread_act_array_t act_list = 0;
177
 
    mach_msg_type_number_t listcount = 0;
178
 
 
179
 
    me = mach_thread_self();
180
 
    if (!GC_thr_initialized) GC_thr_init();
181
 
    
182
 
        my_task = current_task();
183
 
    r = task_threads(my_task, &act_list, &listcount);
184
 
    if(r != KERN_SUCCESS) ABORT("task_threads failed");
185
 
    for(i = 0; i < listcount; i++) {
186
 
      thread_act_t thread = act_list[i];
187
 
      if (thread == me) {
188
 
        lo = GC_approx_sp();
189
 
        hi = (ptr_t)FindTopOfStack(0);
190
 
      } else {
 
197
void GC_push_all_stacks()
 
198
{
 
199
  unsigned int i;
 
200
  task_t my_task;
 
201
  kern_return_t r;
 
202
  mach_port_t me;
 
203
  ptr_t lo, hi;
 
204
  thread_act_array_t act_list = 0;
 
205
  mach_msg_type_number_t listcount = 0;
 
206
 
 
207
  me = mach_thread_self();
 
208
  if (!GC_thr_initialized)
 
209
    GC_thr_init();
 
210
 
 
211
  my_task = current_task();
 
212
  r = task_threads(my_task, &act_list, &listcount);
 
213
  if(r != KERN_SUCCESS)
 
214
    ABORT("task_threads failed");
 
215
  for(i = 0; i < listcount; i++) {
 
216
    thread_act_t thread = act_list[i];
 
217
    if (thread == me) {
 
218
      lo = GC_approx_sp();
 
219
      hi = (ptr_t)FindTopOfStack(0);
 
220
    } else {
191
221
#     if defined(POWERPC)
192
 
#      if CPP_WORDSZ == 32
193
 
        ppc_thread_state_t info;
194
 
#      else
195
 
        ppc_thread_state64_t info;
196
 
#      endif
 
222
        GC_THREAD_STATE_T info;
197
223
        mach_msg_type_number_t outCount = THREAD_STATE_MAX;
198
 
        r = thread_get_state(thread, MACHINE_THREAD_STATE,
199
 
                             (natural_t *)&info, &outCount);
200
 
        if(r != KERN_SUCCESS) ABORT("task_get_state failed");
201
 
 
202
 
        lo = (void*)(info.r1 - PPC_RED_ZONE_SIZE);
203
 
        hi = (ptr_t)FindTopOfStack(info.r1);
204
 
 
205
 
        GC_push_one(info.r0); 
206
 
        GC_push_one(info.r2); 
207
 
        GC_push_one(info.r3); 
208
 
        GC_push_one(info.r4); 
209
 
        GC_push_one(info.r5); 
210
 
        GC_push_one(info.r6); 
211
 
        GC_push_one(info.r7); 
212
 
        GC_push_one(info.r8); 
213
 
        GC_push_one(info.r9); 
214
 
        GC_push_one(info.r10); 
215
 
        GC_push_one(info.r11); 
216
 
        GC_push_one(info.r12); 
217
 
        GC_push_one(info.r13); 
218
 
        GC_push_one(info.r14); 
219
 
        GC_push_one(info.r15); 
220
 
        GC_push_one(info.r16); 
221
 
        GC_push_one(info.r17); 
222
 
        GC_push_one(info.r18); 
223
 
        GC_push_one(info.r19); 
224
 
        GC_push_one(info.r20); 
225
 
        GC_push_one(info.r21); 
226
 
        GC_push_one(info.r22); 
227
 
        GC_push_one(info.r23); 
228
 
        GC_push_one(info.r24); 
229
 
        GC_push_one(info.r25); 
230
 
        GC_push_one(info.r26); 
231
 
        GC_push_one(info.r27); 
232
 
        GC_push_one(info.r28); 
233
 
        GC_push_one(info.r29); 
234
 
        GC_push_one(info.r30); 
235
 
        GC_push_one(info.r31);
236
 
#      else
 
224
        r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
 
225
                             &outCount);
 
226
        if(r != KERN_SUCCESS)
 
227
          ABORT("task_get_state failed");
 
228
 
 
229
        lo = (void*)(info . THREAD_FLD (r1) - PPC_RED_ZONE_SIZE);
 
230
        hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (r1));
 
231
 
 
232
        GC_push_one(info . THREAD_FLD (r0));
 
233
        GC_push_one(info . THREAD_FLD (r2));
 
234
        GC_push_one(info . THREAD_FLD (r3));
 
235
        GC_push_one(info . THREAD_FLD (r4));
 
236
        GC_push_one(info . THREAD_FLD (r5));
 
237
        GC_push_one(info . THREAD_FLD (r6));
 
238
        GC_push_one(info . THREAD_FLD (r7));
 
239
        GC_push_one(info . THREAD_FLD (r8));
 
240
        GC_push_one(info . THREAD_FLD (r9));
 
241
        GC_push_one(info . THREAD_FLD (r10));
 
242
        GC_push_one(info . THREAD_FLD (r11));
 
243
        GC_push_one(info . THREAD_FLD (r12));
 
244
        GC_push_one(info . THREAD_FLD (r13));
 
245
        GC_push_one(info . THREAD_FLD (r14));
 
246
        GC_push_one(info . THREAD_FLD (r15));
 
247
        GC_push_one(info . THREAD_FLD (r16));
 
248
        GC_push_one(info . THREAD_FLD (r17));
 
249
        GC_push_one(info . THREAD_FLD (r18));
 
250
        GC_push_one(info . THREAD_FLD (r19));
 
251
        GC_push_one(info . THREAD_FLD (r20));
 
252
        GC_push_one(info . THREAD_FLD (r21));
 
253
        GC_push_one(info . THREAD_FLD (r22));
 
254
        GC_push_one(info . THREAD_FLD (r23));
 
255
        GC_push_one(info . THREAD_FLD (r24));
 
256
        GC_push_one(info . THREAD_FLD (r25));
 
257
        GC_push_one(info . THREAD_FLD (r26));
 
258
        GC_push_one(info . THREAD_FLD (r27));
 
259
        GC_push_one(info . THREAD_FLD (r28));
 
260
        GC_push_one(info . THREAD_FLD (r29));
 
261
        GC_push_one(info . THREAD_FLD (r30));
 
262
        GC_push_one(info . THREAD_FLD (r31));
 
263
 
 
264
#     elif defined(I386)
237
265
        /* FIXME: Remove after testing: */
238
266
        WARN("This is completely untested and likely will not work\n", 0);
239
 
        i386_thread_state_t info;
240
 
        mach_msg_type_number_t outCount = THREAD_STATE_MAX;
241
 
        r = thread_get_state(thread, MACHINE_THREAD_STATE,
242
 
                             (natural_t *)&info, &outCount);
243
 
        if(r != KERN_SUCCESS) ABORT("task_get_state failed");
244
 
 
245
 
        lo = (void*)info.esp;
246
 
        hi = (ptr_t)FindTopOfStack(info.esp);
247
 
 
248
 
        GC_push_one(info.eax); 
249
 
        GC_push_one(info.ebx); 
250
 
        GC_push_one(info.ecx); 
251
 
        GC_push_one(info.edx); 
252
 
        GC_push_one(info.edi); 
253
 
        GC_push_one(info.esi); 
254
 
        /* GC_push_one(info.ebp);  */
255
 
        /* GC_push_one(info.esp);  */
256
 
        GC_push_one(info.ss); 
257
 
        GC_push_one(info.eip); 
258
 
        GC_push_one(info.cs); 
259
 
        GC_push_one(info.ds); 
260
 
        GC_push_one(info.es); 
261
 
        GC_push_one(info.fs); 
262
 
        GC_push_one(info.gs); 
263
 
#      endif /* !POWERPC */
 
267
        GC_THREAD_STATE_T info;
 
268
        mach_msg_type_number_t outCount = THREAD_STATE_MAX;
 
269
        r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
 
270
                             &outCount);
 
271
        if(r != KERN_SUCCESS)
 
272
          ABORT("task_get_state failed");
 
273
 
 
274
        lo = (void*)info . THREAD_FLD (esp);
 
275
        hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (esp));
 
276
 
 
277
        GC_push_one(info . THREAD_FLD (eax));
 
278
        GC_push_one(info . THREAD_FLD (ebx));
 
279
        GC_push_one(info . THREAD_FLD (ecx));
 
280
        GC_push_one(info . THREAD_FLD (edx));
 
281
        GC_push_one(info . THREAD_FLD (edi));
 
282
        GC_push_one(info . THREAD_FLD (esi));
 
283
        /* GC_push_one(info . THREAD_FLD (ebp));  */
 
284
        /* GC_push_one(info . THREAD_FLD (esp));  */
 
285
        GC_push_one(info . THREAD_FLD (ss));
 
286
        GC_push_one(info . THREAD_FLD (eip));
 
287
        GC_push_one(info . THREAD_FLD (cs));
 
288
        GC_push_one(info . THREAD_FLD (ds));
 
289
        GC_push_one(info . THREAD_FLD (es));
 
290
        GC_push_one(info . THREAD_FLD (fs));
 
291
        GC_push_one(info . THREAD_FLD (gs));
 
292
 
 
293
#     elif defined(X86_64)
 
294
        GC_THREAD_STATE_T info;
 
295
        mach_msg_type_number_t outCount = THREAD_STATE_MAX;
 
296
        r = thread_get_state(thread, GC_MACH_THREAD_STATE, (natural_t *)&info,
 
297
                             &outCount);
 
298
        if(r != KERN_SUCCESS)
 
299
          ABORT("task_get_state failed");
 
300
 
 
301
        lo = (void*)info . THREAD_FLD (rsp);
 
302
        hi = (ptr_t)FindTopOfStack(info . THREAD_FLD (rsp));
 
303
 
 
304
        GC_push_one(info . THREAD_FLD (rax));
 
305
        GC_push_one(info . THREAD_FLD (rbx));
 
306
        GC_push_one(info . THREAD_FLD (rcx));
 
307
        GC_push_one(info . THREAD_FLD (rdx));
 
308
        GC_push_one(info . THREAD_FLD (rdi));
 
309
        GC_push_one(info . THREAD_FLD (rsi));
 
310
        GC_push_one(info . THREAD_FLD (rbp));
 
311
        GC_push_one(info . THREAD_FLD (rsp));
 
312
        GC_push_one(info . THREAD_FLD (r8));
 
313
        GC_push_one(info . THREAD_FLD (r9));
 
314
        GC_push_one(info . THREAD_FLD (r10));
 
315
        GC_push_one(info . THREAD_FLD (r11));
 
316
        GC_push_one(info . THREAD_FLD (r12));
 
317
        GC_push_one(info . THREAD_FLD (r13));
 
318
        GC_push_one(info . THREAD_FLD (r14));
 
319
        GC_push_one(info . THREAD_FLD (r15));
 
320
        GC_push_one(info . THREAD_FLD (rip));
 
321
        GC_push_one(info . THREAD_FLD (rflags));
 
322
        GC_push_one(info . THREAD_FLD (cs));
 
323
        GC_push_one(info . THREAD_FLD (fs));
 
324
        GC_push_one(info . THREAD_FLD (gs));
 
325
 
 
326
#     else
 
327
#       error FIXME for non-x86 || ppc architectures
 
328
#     endif
264
329
      }
265
330
#     if DEBUG_THREADS
266
 
       GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
267
 
                  (unsigned long) thread,
268
 
                  (unsigned long) lo,
269
 
                  (unsigned long) hi
270
 
                 );
 
331
        GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n",
 
332
                  (unsigned long) thread, lo, hi);
271
333
#     endif
272
 
      GC_push_all_stack(lo, hi); 
273
 
          mach_port_deallocate(my_task, thread);
 
334
      GC_push_all_stack(lo, hi);
 
335
      mach_port_deallocate(my_task, thread);
274
336
    } /* for(p=GC_threads[i]...) */
275
 
    vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
276
 
        mach_port_deallocate(my_task, me);
 
337
    vm_deallocate(my_task, (vm_address_t)act_list,
 
338
                  sizeof(thread_t) * listcount);
 
339
    mach_port_deallocate(my_task, me);
277
340
}
278
341
#endif /* !DARWIN_DONT_PARSE_STACK */
279
342
 
283
346
static struct GC_mach_thread GC_mach_threads[THREAD_TABLE_SZ];
284
347
static int GC_mach_threads_count;
285
348
 
286
 
void GC_stop_init() {
 
349
void GC_stop_init()
 
350
{
287
351
  int i;
288
352
 
289
353
  for (i = 0; i < THREAD_TABLE_SZ; i++) {
294
358
}
295
359
 
296
360
/* returns true if there's a thread in act_list that wasn't in old_list */
297
 
int GC_suspend_thread_list(thread_act_array_t act_list, int count, 
298
 
                           thread_act_array_t old_list, int old_count) {
 
361
int GC_suspend_thread_list(thread_act_array_t act_list, int count,
 
362
                           thread_act_array_t old_list, int old_count)
 
363
{
299
364
  mach_port_t my_thread = mach_thread_self();
300
365
  int i, j;
301
366
 
303
368
 
304
369
  for(i = 0; i < count; i++) {
305
370
    thread_act_t thread = act_list[i];
306
 
#   if DEBUG_THREADS 
307
 
      GC_printf1("Attempting to suspend thread %p\n", thread);
 
371
#   if DEBUG_THREADS
 
372
      GC_printf("Attempting to suspend thread %p\n", thread);
308
373
#   endif
309
374
    /* find the current thread in the old list */
310
375
    int found = 0;
321
386
      /* default is not suspended */
322
387
      GC_mach_threads[GC_mach_threads_count].already_suspended = 0;
323
388
      changed = 1;
324
 
    }      
 
389
    }
325
390
 
326
 
    if (thread != my_thread &&
327
 
        (!GC_use_mach_handler_thread
328
 
         || (GC_use_mach_handler_thread
329
 
             && GC_mach_handler_thread != thread))) {
 
391
    if (thread != my_thread
 
392
        && (!GC_use_mach_handler_thread
 
393
            || (GC_use_mach_handler_thread
 
394
                && GC_mach_handler_thread != thread))) {
330
395
      struct thread_basic_info info;
331
396
      mach_msg_type_number_t outCount = THREAD_INFO_MAX;
332
397
      kern_return_t kern_result = thread_info(thread, THREAD_BASIC_INFO,
333
398
                                (thread_info_t)&info, &outCount);
334
399
      if(kern_result != KERN_SUCCESS) {
335
 
        /* the thread may have quit since the thread_threads () call 
 
400
        /* the thread may have quit since the thread_threads () call
336
401
         * we mark already_suspended so it's not dealt with anymore later
337
402
         */
338
 
        if (!found) {
 
403
        if (!found) {
339
404
          GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
340
 
          GC_mach_threads_count++;
 
405
          GC_mach_threads_count++;
341
406
        }
342
407
        continue;
343
408
      }
344
409
#     if DEBUG_THREADS
345
 
        GC_printf2("Thread state for 0x%lx = %d\n", thread, info.run_state);
 
410
        GC_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread,
 
411
                  info.run_state);
346
412
#     endif
347
413
      if (!found) {
348
 
        GC_mach_threads[GC_mach_threads_count].already_suspended = info.suspend_count;
 
414
        GC_mach_threads[GC_mach_threads_count].already_suspended
 
415
          = info.suspend_count;
349
416
      }
350
 
      if (info.suspend_count) continue;
351
 
      
 
417
      if (info.suspend_count)
 
418
        continue;
 
419
 
352
420
#     if DEBUG_THREADS
353
 
        GC_printf1("Suspending 0x%lx\n", thread);
 
421
        GC_printf("Suspending 0x%lx\n", (unsigned long)thread);
354
422
#     endif
355
423
      /* Suspend the thread */
356
424
      kern_result = thread_suspend(thread);
357
425
      if(kern_result != KERN_SUCCESS) {
358
 
        /* the thread may have quit since the thread_threads () call 
 
426
        /* the thread may have quit since the thread_threads () call
359
427
         * we mark already_suspended so it's not dealt with anymore later
360
428
         */
361
 
        if (!found) {
 
429
        if (!found) {
362
430
          GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
363
 
          GC_mach_threads_count++;
 
431
          GC_mach_threads_count++;
364
432
        }
365
433
        continue;
366
434
      }
367
 
    } 
 
435
    }
368
436
    if (!found) GC_mach_threads_count++;
369
437
  }
370
438
  mach_port_deallocate(current_task(), my_thread);
375
443
/* Caller holds allocation lock.        */
376
444
void GC_stop_world()
377
445
{
378
 
  int i, changes;
379
 
    GC_thread p;
380
 
        task_t my_task = current_task();
 
446
    unsigned int i, changes;
 
447
    task_t my_task = current_task();
381
448
    mach_port_t my_thread = mach_thread_self();
382
449
    kern_return_t kern_result;
383
450
    thread_act_array_t act_list, prev_list;
384
451
    mach_msg_type_number_t listcount, prevcount;
385
 
    
 
452
 
386
453
#   if DEBUG_THREADS
387
 
      GC_printf1("Stopping the world from 0x%lx\n", mach_thread_self());
 
454
      GC_printf("Stopping the world from 0x%lx\n",
 
455
                (unsigned long)mach_thread_self());
388
456
#   endif
389
457
 
390
458
    /* clear out the mach threads list table */
391
 
    GC_stop_init(); 
392
 
       
 
459
    GC_stop_init();
 
460
 
393
461
    /* Make sure all free list construction has stopped before we start. */
394
462
    /* No new construction can start, since free list construction is   */
395
463
    /* required to acquire and release the GC lock before it starts,    */
400
468
      /* We should have previously waited for it to become zero. */
401
469
#   endif /* PARALLEL_MARK */
402
470
 
403
 
      /* Loop stopping threads until you have gone over the whole list
404
 
         twice without a new one appearing. thread_create() won't
405
 
         return (and thus the thread stop) until the new thread
406
 
         exists, so there is no window whereby you could stop a
407
 
         thread, recognise it is stopped, but then have a new thread
408
 
         it created before stopping show up later.
409
 
      */
410
 
      
411
 
      changes = 1;
412
 
      prev_list = NULL;
413
 
      prevcount = 0;
414
 
      do {
415
 
        int result;
416
 
        kern_result = task_threads(my_task, &act_list, &listcount);
417
 
        result = GC_suspend_thread_list(act_list, listcount,
418
 
                                        prev_list, prevcount);
 
471
    /* Loop stopping threads until you have gone over the whole list
 
472
       twice without a new one appearing. thread_create() won't
 
473
       return (and thus the thread stop) until the new thread
 
474
       exists, so there is no window whereby you could stop a
 
475
       thread, recognise it is stopped, but then have a new thread
 
476
       it created before stopping show up later.
 
477
    */
 
478
 
 
479
    /* FIXME: This seems to erroneously stop the parallel marker threads? */
 
480
 
 
481
    changes = 1;
 
482
    prev_list = NULL;
 
483
    prevcount = 0;
 
484
    do {
 
485
      int result;
 
486
      kern_result = task_threads(my_task, &act_list, &listcount);
 
487
 
 
488
      if(kern_result == KERN_SUCCESS) {
 
489
        result = GC_suspend_thread_list(act_list, listcount, prev_list,
 
490
                                        prevcount);
419
491
        changes = result;
 
492
 
 
493
        if(prev_list != NULL) {
 
494
          for(i = 0; i < prevcount; i++)
 
495
            mach_port_deallocate(my_task, prev_list[i]);
 
496
 
 
497
          vm_deallocate(my_task, (vm_address_t)prev_list,
 
498
                        sizeof(thread_t) * prevcount);
 
499
        }
420
500
        prev_list = act_list;
421
501
        prevcount = listcount;
422
 
        
423
 
        if(kern_result == KERN_SUCCESS) {
424
 
                int i;
425
 
                
426
 
                for(i = 0; i < listcount; i++)
427
 
                        mach_port_deallocate(my_task, act_list[i]);
428
 
                
429
 
        vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
430
 
        }
431
 
      } while (changes);
432
 
      
433
 
 
 
502
      }
 
503
    } while (changes);
 
504
    GC_ASSERT(prev_list != 0);
 
505
    for(i = 0; i < prevcount; i++)
 
506
      mach_port_deallocate(my_task, prev_list[i]);
 
507
 
 
508
    vm_deallocate(my_task, (vm_address_t)act_list,
 
509
                  sizeof(thread_t) * listcount);
 
510
 
434
511
#   ifdef MPROTECT_VDB
435
512
      if(GC_incremental) {
436
 
        extern void GC_mprotect_stop();
437
 
        GC_mprotect_stop();
 
513
        extern void GC_mprotect_stop();
 
514
        GC_mprotect_stop();
438
515
      }
439
516
#   endif
440
 
    
 
517
 
441
518
#   ifdef PARALLEL_MARK
442
519
      GC_release_mark_lock();
443
520
#   endif
444
 
    #if DEBUG_THREADS
445
 
      GC_printf1("World stopped from 0x%lx\n", my_thread);
446
 
    #endif
447
 
          
448
 
          mach_port_deallocate(my_task, my_thread);
 
521
#   if DEBUG_THREADS
 
522
      GC_printf("World stopped from 0x%lx\n", (unsigned long)my_thread);
 
523
#   endif
 
524
 
 
525
    mach_port_deallocate(my_task, my_thread);
449
526
}
450
527
 
451
528
/* Caller holds allocation lock, and has held it continuously since     */
454
531
{
455
532
  task_t my_task = current_task();
456
533
  mach_port_t my_thread = mach_thread_self();
457
 
  int i, j;
458
 
  GC_thread p;
 
534
  unsigned int i;
 
535
  int j;
459
536
  kern_return_t kern_result;
460
537
  thread_act_array_t act_list;
461
538
  mach_msg_type_number_t listcount;
462
539
  struct thread_basic_info info;
463
540
  mach_msg_type_number_t outCount = THREAD_INFO_MAX;
464
 
  
 
541
 
465
542
#   if DEBUG_THREADS
466
 
      GC_printf0("World starting\n");
 
543
      GC_printf("World starting\n");
467
544
#   endif
468
545
 
469
546
#   ifdef MPROTECT_VDB
470
547
      if(GC_incremental) {
471
 
        extern void GC_mprotect_resume();
472
 
        GC_mprotect_resume();
 
548
        extern void GC_mprotect_resume();
 
549
        GC_mprotect_resume();
473
550
      }
474
551
#   endif
475
552
 
476
553
    kern_result = task_threads(my_task, &act_list, &listcount);
477
554
    for(i = 0; i < listcount; i++) {
478
555
      thread_act_t thread = act_list[i];
479
 
      if (thread != my_thread &&
480
 
          (!GC_use_mach_handler_thread ||
481
 
           (GC_use_mach_handler_thread && GC_mach_handler_thread != thread))) {
 
556
      if (thread != my_thread
 
557
          && (!GC_use_mach_handler_thread
 
558
              || (GC_use_mach_handler_thread
 
559
                  && GC_mach_handler_thread != thread))) {
482
560
        for(j = 0; j < GC_mach_threads_count; j++) {
483
561
          if (thread == GC_mach_threads[j].thread) {
484
562
            if (GC_mach_threads[j].already_suspended) {
485
563
#             if DEBUG_THREADS
486
 
                GC_printf1("Not resuming already suspended thread %p\n", thread);
 
564
                GC_printf("Not resuming already suspended thread %p\n", thread);
487
565
#             endif
488
566
              continue;
489
567
            }
490
568
            kern_result = thread_info(thread, THREAD_BASIC_INFO,
491
569
                                      (thread_info_t)&info, &outCount);
492
 
            if(kern_result != KERN_SUCCESS) ABORT("thread_info failed");
 
570
            if(kern_result != KERN_SUCCESS)
 
571
              ABORT("thread_info failed");
493
572
#           if DEBUG_THREADS
494
 
              GC_printf2("Thread state for 0x%lx = %d\n", thread,
 
573
              GC_printf("Thread state for 0x%lx = %d\n", (unsigned long)thread,
495
574
                         info.run_state);
496
 
              GC_printf1("Resuming 0x%lx\n", thread);
 
575
              GC_printf("Resuming 0x%lx\n", (unsigned long)thread);
497
576
#           endif
498
577
            /* Resume the thread */
499
578
            kern_result = thread_resume(thread);
500
 
            if(kern_result != KERN_SUCCESS) ABORT("thread_resume failed");
501
 
          } 
 
579
            if(kern_result != KERN_SUCCESS)
 
580
              ABORT("thread_resume failed");
 
581
          }
502
582
        }
503
583
      }
504
 
          
505
 
          mach_port_deallocate(my_task, thread);
 
584
      mach_port_deallocate(my_task, thread);
506
585
    }
507
 
    vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
508
 
        
509
 
        mach_port_deallocate(my_task, my_thread);
 
586
    vm_deallocate(my_task, (vm_address_t)act_list,
 
587
                  sizeof(thread_t) * listcount);
 
588
 
 
589
    mach_port_deallocate(my_task, my_thread);
510
590
#   if DEBUG_THREADS
511
 
     GC_printf0("World started\n");
 
591
      GC_printf("World started\n");
512
592
#   endif
513
593
}
514
594
 
515
 
void GC_darwin_register_mach_handler_thread(mach_port_t thread) {
 
595
void GC_darwin_register_mach_handler_thread(mach_port_t thread)
 
596
{
516
597
  GC_mach_handler_thread = thread;
517
598
  GC_use_mach_handler_thread = 1;
518
599
}