Skip to content

Commit 938131f

Browse files
committed
Don't resume previously suspended threads on gc
1 parent 03ff817 commit 938131f

File tree

4 files changed

+57
-64
lines changed

4 files changed

+57
-64
lines changed

lisp/c/eus_proto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ extern int thr_setprio(int /*tid*/, int /*prio*/);
500500
extern int thr_create(void */*base*/, size_t /*size*/, void (*/*func*/)(), void */*args*/, long /*flags*/, int */*tid*/);
501501
extern int thr_continue(int /*tid*/);
502502
extern int thr_suspend(int /*tid*/);
503+
extern int thr_unsuspend(int /*tid*/);
503504
extern int thr_kill(int /*tid*/, int /*sig*/);
504505
extern int thr_cancel(int /*tid*/);
505506
extern int thr_join(int /*tid*/, int */*depature*/, void **/*status*/);

lisp/c/eus_thr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ extern int thr_create(void *, size_t, void (*)(), void *, long, int *);
113113
extern int thr_setprio(int, int);
114114
extern int thr_continue(int);
115115
extern int thr_suspend(int);
116+
extern int thr_unsuspend(int);
116117
extern int thr_kill(int, int);
117118
extern int thr_cancel(int);
118119

lisp/c/memory.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,9 @@ void resume_all_threads()
762762
self=thr_self();
763763
for (i=0; i<MAXTHREAD; i++)
764764
if (i!=self && euscontexts[i]) {
765-
stat=thr_continue(i);
765+
// Use thr_unsuspend to avoid resuming threads which were
766+
// already suspended by the user before the gc
767+
stat=thr_unsuspend(i);
766768
if (stat) fprintf(stderr, "gc cannot resume thread %d\n",i); }
767769
}
768770

lisp/c/mthread_posix.c

Lines changed: 52 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ pthread_mutex_t susp_mut = PTHREAD_MUTEX_INITIALIZER;
122122
volatile int susp_sentinel = 0;
123123
pthread_once_t susp_once = PTHREAD_ONCE_INIT;
124124
pthread_t susp_null_pthread = {0};
125-
pthread_t susp_array[MAXTHREAD];
126-
int susp_bottom = MAXTHREAD;
125+
int susp_count[MAXTHREAD];
127126
int susp_inited = 0;
128127

129128
/*
@@ -134,14 +133,26 @@ void
134133
suspend_signal_handler (int sig)
135134
{
136135
sigset_t signal_set;
136+
susp_count[thr_self()] += 1;
137137

138138
/*
139-
* Block all signals except SIGUSR2 while suspended.
139+
* Skip if already suspended
140+
*/
141+
if (susp_count[thr_self()]>1) {
142+
susp_sentinel = 1;
143+
return;
144+
}
145+
146+
/*
147+
* Block all signals except SIGUSR1 and SIGUSR2 while suspended.
140148
*/
141149
sigfillset (&signal_set);
150+
sigdelset (&signal_set, SIGUSR1);
142151
sigdelset (&signal_set, SIGUSR2);
143152
susp_sentinel = 1;
144-
sigsuspend (&signal_set);
153+
while(susp_count[thr_self()]>0) {
154+
sigsuspend (&signal_set);
155+
}
145156

146157
/*
147158
* Once I'm here, I've been resumed, and the resume signal
@@ -158,6 +169,7 @@ suspend_signal_handler (int sig)
158169
void
159170
resume_signal_handler (int sig)
160171
{
172+
susp_count[thr_self()] -= 1;
161173
return;
162174
}
163175

@@ -168,15 +180,15 @@ resume_signal_handler (int sig)
168180
void
169181
suspend_init_routine (void)
170182
{
171-
int status;
183+
int i, status;
172184
struct sigaction sigusr1, sigusr2;
173185

174186
/*
175-
* Allocate the suspended threads array. This array is used
176-
* to guarentee idempotency
187+
* Initialize suspension counter
177188
*/
178-
//susp_bottom = 10;
179-
// susp_array = (pthread_t*) calloc (susp_bottom, sizeof (pthread_t));
189+
for (i=0; i<MAXTHREAD; i++) {
190+
susp_count[i] = 0;
191+
}
180192

181193
/*
182194
* Install the signal handlers for suspend/resume.
@@ -210,11 +222,10 @@ suspend_init_routine (void)
210222
* call will cause it to resume execution.
211223
*/
212224
int
213-
//thd_suspend (pthread_t target_thread)
225+
//thr_suspend (pthread_t target_thread)
214226
pthread_suspend (pthread_t target_thread)
215227
{
216228
int status;
217-
int i = 0;
218229

219230
/*
220231
* The first call to thd_suspend will initialize the
@@ -231,38 +242,6 @@ pthread_suspend (pthread_t target_thread)
231242
if (status != 0)
232243
return status;
233244

234-
/*
235-
* Threads that are suspended are added to the target_array;
236-
* a request to suspend a thread already listed in the array
237-
* is ignored. Sending a second SIGUSR1 would cause the
238-
* thread to re-suspend itself as soon as it is resumed.
239-
*/
240-
while (i < susp_bottom)
241-
if (susp_array[i++] == target_thread) {
242-
status = pthread_mutex_unlock (&susp_mut);
243-
return status;
244-
}
245-
246-
/*
247-
* Ok, we really need to suspend this thread. So, lets find
248-
* the location in the array that we'll use. If we run off
249-
* the end, realloc the array for more space.
250-
*/
251-
i = 0;
252-
while (susp_array[i] != 0)
253-
i++;
254-
255-
if (i == susp_bottom) {
256-
// susp_array = (pthread_t*) realloc (
257-
// susp_array, (++susp_bottom * sizeof (pthread_t)));
258-
// if (susp_array == NULL) {
259-
pthread_mutex_unlock (&susp_mut);
260-
return errno;
261-
// }
262-
263-
// susp_array[susp_bottom] = susp_null_pthread; /* Clear new entry */
264-
}
265-
266245
/*
267246
* Clear the sentinel and signal the thread to suspend.
268247
*/
@@ -279,23 +258,22 @@ pthread_suspend (pthread_t target_thread)
279258
while (susp_sentinel == 0)
280259
sched_yield ();
281260

282-
susp_array[i] = target_thread;
283-
284261
status = pthread_mutex_unlock (&susp_mut);
285262
return status;
286263
}
287264

288265
/*
289266
* Resume a suspended thread by sending it SIGUSR2 to break
290267
* it out of the sigsuspend() in which it's waiting. If the
291-
* target thread isn't suspended, return with success.
268+
* thread has received other suspension requests while waiting,
269+
* the thread will be re-suspended immediately after resuming.
270+
* If the target thread isn't suspended, return with success.
292271
*/
293272
int
294-
//thd_continue (pthread_t target_thread)
295-
pthread_continue (pthread_t target_thread)
273+
pthread_unsuspend (pthread_t target_thread)
296274
{
297275
int status;
298-
int i = 0;
276+
299277
/*
300278
* Serialize access to suspend, makes life easier
301279
*/
@@ -312,19 +290,6 @@ pthread_continue (pthread_t target_thread)
312290
return status;
313291
}
314292

315-
/*
316-
* Make sure the thread is in the suspend array. If not, it
317-
* hasn't been suspended (or it has already been resumed) and
318-
* we can just carry on.
319-
*/
320-
while (susp_array[i] != target_thread && i < susp_bottom)
321-
i++;
322-
323-
if (i >= susp_bottom) {
324-
pthread_mutex_unlock (&susp_mut);
325-
return 0;
326-
}
327-
328293
/*
329294
* Signal the thread to continue, and remove the thread from
330295
* the suspended array.
@@ -335,10 +300,34 @@ pthread_continue (pthread_t target_thread)
335300
return status;
336301
}
337302

338-
susp_array[i] = 0; /* Clear array element */
339303
status = pthread_mutex_unlock (&susp_mut);
340304
return status;
341305
}
306+
307+
/*
308+
* Ensures that a suspended thread is resumed, even if
309+
* multiple suspension requests have been received.
310+
*/
311+
int
312+
//thr_continue (pthread_t target_thread)
313+
pthread_continue (pthread_t target_thread)
314+
{
315+
int i;
316+
for(i = 0; i < MAXTHREAD && !pthread_equal(thread_table[i].tid,target_thread); i++);
317+
if (i == MAXTHREAD) return(-1);
318+
319+
susp_count[i] = 1;
320+
return pthread_unsuspend(target_thread);
321+
}
322+
323+
int thr_unsuspend( int tid ) {
324+
return pthread_unsuspend( thread_table[tid].tid );
325+
}
326+
#else
327+
int thr_unsuspend( int tid ) {
328+
// not supported, always continue
329+
return pthread_continue ( thread_table[tid].tid );
330+
}
342331
#endif
343332
int thr_suspend( int tid ) {
344333
return pthread_suspend ( thread_table[tid].tid );

0 commit comments

Comments
 (0)