Skip to content

Commit

Permalink
Don't resume previously suspended threads on gc
Browse files Browse the repository at this point in the history
  • Loading branch information
Affonso-Gui committed Nov 10, 2022
1 parent 03ff817 commit 938131f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 64 deletions.
1 change: 1 addition & 0 deletions lisp/c/eus_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ extern int thr_setprio(int /*tid*/, int /*prio*/);
extern int thr_create(void */*base*/, size_t /*size*/, void (*/*func*/)(), void */*args*/, long /*flags*/, int */*tid*/);
extern int thr_continue(int /*tid*/);
extern int thr_suspend(int /*tid*/);
extern int thr_unsuspend(int /*tid*/);
extern int thr_kill(int /*tid*/, int /*sig*/);
extern int thr_cancel(int /*tid*/);
extern int thr_join(int /*tid*/, int */*depature*/, void **/*status*/);
Expand Down
1 change: 1 addition & 0 deletions lisp/c/eus_thr.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ extern int thr_create(void *, size_t, void (*)(), void *, long, int *);
extern int thr_setprio(int, int);
extern int thr_continue(int);
extern int thr_suspend(int);
extern int thr_unsuspend(int);
extern int thr_kill(int, int);
extern int thr_cancel(int);

Expand Down
4 changes: 3 additions & 1 deletion lisp/c/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,9 @@ void resume_all_threads()
self=thr_self();
for (i=0; i<MAXTHREAD; i++)
if (i!=self && euscontexts[i]) {
stat=thr_continue(i);
// Use thr_unsuspend to avoid resuming threads which were
// already suspended by the user before the gc
stat=thr_unsuspend(i);
if (stat) fprintf(stderr, "gc cannot resume thread %d\n",i); }
}

Expand Down
115 changes: 52 additions & 63 deletions lisp/c/mthread_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ pthread_mutex_t susp_mut = PTHREAD_MUTEX_INITIALIZER;
volatile int susp_sentinel = 0;
pthread_once_t susp_once = PTHREAD_ONCE_INIT;
pthread_t susp_null_pthread = {0};
pthread_t susp_array[MAXTHREAD];
int susp_bottom = MAXTHREAD;
int susp_count[MAXTHREAD];
int susp_inited = 0;

/*
Expand All @@ -134,14 +133,26 @@ void
suspend_signal_handler (int sig)
{
sigset_t signal_set;
susp_count[thr_self()] += 1;

/*
* Block all signals except SIGUSR2 while suspended.
* Skip if already suspended
*/
if (susp_count[thr_self()]>1) {
susp_sentinel = 1;
return;
}

/*
* Block all signals except SIGUSR1 and SIGUSR2 while suspended.
*/
sigfillset (&signal_set);
sigdelset (&signal_set, SIGUSR1);
sigdelset (&signal_set, SIGUSR2);
susp_sentinel = 1;
sigsuspend (&signal_set);
while(susp_count[thr_self()]>0) {
sigsuspend (&signal_set);
}

/*
* Once I'm here, I've been resumed, and the resume signal
Expand All @@ -158,6 +169,7 @@ suspend_signal_handler (int sig)
void
resume_signal_handler (int sig)
{
susp_count[thr_self()] -= 1;
return;
}

Expand All @@ -168,15 +180,15 @@ resume_signal_handler (int sig)
void
suspend_init_routine (void)
{
int status;
int i, status;
struct sigaction sigusr1, sigusr2;

/*
* Allocate the suspended threads array. This array is used
* to guarentee idempotency
* Initialize suspension counter
*/
//susp_bottom = 10;
// susp_array = (pthread_t*) calloc (susp_bottom, sizeof (pthread_t));
for (i=0; i<MAXTHREAD; i++) {
susp_count[i] = 0;
}

/*
* Install the signal handlers for suspend/resume.
Expand Down Expand Up @@ -210,11 +222,10 @@ suspend_init_routine (void)
* call will cause it to resume execution.
*/
int
//thd_suspend (pthread_t target_thread)
//thr_suspend (pthread_t target_thread)
pthread_suspend (pthread_t target_thread)
{
int status;
int i = 0;

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

/*
* Threads that are suspended are added to the target_array;
* a request to suspend a thread already listed in the array
* is ignored. Sending a second SIGUSR1 would cause the
* thread to re-suspend itself as soon as it is resumed.
*/
while (i < susp_bottom)
if (susp_array[i++] == target_thread) {
status = pthread_mutex_unlock (&susp_mut);
return status;
}

/*
* Ok, we really need to suspend this thread. So, lets find
* the location in the array that we'll use. If we run off
* the end, realloc the array for more space.
*/
i = 0;
while (susp_array[i] != 0)
i++;

if (i == susp_bottom) {
// susp_array = (pthread_t*) realloc (
// susp_array, (++susp_bottom * sizeof (pthread_t)));
// if (susp_array == NULL) {
pthread_mutex_unlock (&susp_mut);
return errno;
// }

// susp_array[susp_bottom] = susp_null_pthread; /* Clear new entry */
}

/*
* Clear the sentinel and signal the thread to suspend.
*/
Expand All @@ -279,23 +258,22 @@ pthread_suspend (pthread_t target_thread)
while (susp_sentinel == 0)
sched_yield ();

susp_array[i] = target_thread;

status = pthread_mutex_unlock (&susp_mut);
return status;
}

/*
* Resume a suspended thread by sending it SIGUSR2 to break
* it out of the sigsuspend() in which it's waiting. If the
* target thread isn't suspended, return with success.
* thread has received other suspension requests while waiting,
* the thread will be re-suspended immediately after resuming.
* If the target thread isn't suspended, return with success.
*/
int
//thd_continue (pthread_t target_thread)
pthread_continue (pthread_t target_thread)
pthread_unsuspend (pthread_t target_thread)
{
int status;
int i = 0;

/*
* Serialize access to suspend, makes life easier
*/
Expand All @@ -312,19 +290,6 @@ pthread_continue (pthread_t target_thread)
return status;
}

/*
* Make sure the thread is in the suspend array. If not, it
* hasn't been suspended (or it has already been resumed) and
* we can just carry on.
*/
while (susp_array[i] != target_thread && i < susp_bottom)
i++;

if (i >= susp_bottom) {
pthread_mutex_unlock (&susp_mut);
return 0;
}

/*
* Signal the thread to continue, and remove the thread from
* the suspended array.
Expand All @@ -335,10 +300,34 @@ pthread_continue (pthread_t target_thread)
return status;
}

susp_array[i] = 0; /* Clear array element */
status = pthread_mutex_unlock (&susp_mut);
return status;
}

/*
* Ensures that a suspended thread is resumed, even if
* multiple suspension requests have been received.
*/
int
//thr_continue (pthread_t target_thread)
pthread_continue (pthread_t target_thread)
{
int i;
for(i = 0; i < MAXTHREAD && !pthread_equal(thread_table[i].tid,target_thread); i++);
if (i == MAXTHREAD) return(-1);

susp_count[i] = 1;
return pthread_unsuspend(target_thread);
}

int thr_unsuspend( int tid ) {
return pthread_unsuspend( thread_table[tid].tid );
}
#else
int thr_unsuspend( int tid ) {
// not supported, always continue
return pthread_continue ( thread_table[tid].tid );
}
#endif
int thr_suspend( int tid ) {
return pthread_suspend ( thread_table[tid].tid );
Expand Down

0 comments on commit 938131f

Please sign in to comment.