[Devel] Re: [PATCH] RFC: s390: Move get_signal_to_deliver() up in do_signal

Oren Laadan orenl at cs.columbia.edu
Mon Feb 15 05:26:23 PST 2010


Ok, I think I'm convinced ;)
Applied...

Serge E. Hallyn wrote:
> Quoting Serge E. Hallyn (serue at us.ibm.com):
>> Well, perhaps I've been making this more complicated than it
>> needs to be.
>>
>> If we get frozen+checkpointed, then no matter whether we were
>> frozen with a real pending signal or not, we won't handle the
>> signal during restart, so we can treat it as though signr==0.
>>
>> So, in that case, the only thing we need to change at end of
>> sys_restart is to handle the case:
>>
>> 	/* Restart a different system call. */
>> 	if (retval == -ERESTART_RESTARTBLOCK
>> 			&& regs->psw.addr == continue_addr) {
>> 		regs->gprs[2] = __NR_restart_syscall;
>> 		set_thread_flag(TIF_RESTART_SVC);
>> 	}
>>
>> Now that's of course a problem bc we don't know continue_addr
>> when we're in sys_restart().  So before we go into get_signal_to_deliver(),
>> we should set a new TIF flag which represents the fact that we are
>> inside do_signal with those conditions.
>>
>> Then at end of restore_thread(), if that flag is set, we do the
>>
>> 	regs->gprs[2] = __NR_restart_syscall;
>> 	set_thread_flag(TIF_RESTART_SVC);
>>
>> (which presumably goes into a helper)
>>
>> If there was a pending signal which we were intending to handle
>> when checkpointed, then that will simply be delivered after we
>> exit sys_restart.  That is no different from the case where we
>> got another signal delivered while a slow sighandler was executing.
>>
>> I'll try implementing that idea.
>>
>> -serge
> 
> Like so:
> 
> From b50eb90da03e82ae6e7a2f1a8362e93c18d52074 Mon Sep 17 00:00:00 2001
> From: Serge E. Hallyn <serue at us.ibm.com>
> Date: Thu, 11 Feb 2010 14:05:16 -0500
> Subject: [PATCH 1/1] set TIF_RESTART_SVC when needed after sys_restart
> 
> Signed-off-by: Serge E. Hallyn <serue at us.ibm.com>
> ---
>  arch/s390/include/asm/checkpoint_hdr.h |    5 +++
>  arch/s390/include/asm/thread_info.h    |    2 +
>  arch/s390/kernel/checkpoint.c          |   52 +++++++++++++++++++++++++++++++-
>  arch/s390/kernel/signal.c              |   16 ++++++++++
>  4 files changed, 74 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/s390/include/asm/checkpoint_hdr.h b/arch/s390/include/asm/checkpoint_hdr.h
> index a8c2a3d..fd8be2a 100644
> --- a/arch/s390/include/asm/checkpoint_hdr.h
> +++ b/arch/s390/include/asm/checkpoint_hdr.h
> @@ -76,6 +76,11 @@ struct ckpt_hdr_cpu {
>  	__u8 instruction_fetch;
>  };
>  
> +struct ckpt_hdr_thread {
> +	struct ckpt_hdr h;
> +	__u64 thread_info_flags;
> +};
> +
>  struct ckpt_hdr_mm_context {
>  	struct ckpt_hdr h;
>  	unsigned long vdso_base;
> diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
> index 66069e7..61e84e5 100644
> --- a/arch/s390/include/asm/thread_info.h
> +++ b/arch/s390/include/asm/thread_info.h
> @@ -99,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
>  #define TIF_MEMDIE		18
>  #define TIF_RESTORE_SIGMASK	19	/* restore signal mask in do_signal() */
>  #define TIF_FREEZE		20	/* thread is freezing for suspend */
> +#define TIF_SIG_RESTARTBLOCK	23	/* restart must set TIF_RESTART_SVC */
>  
>  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
>  #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
> @@ -114,6 +115,7 @@ static inline struct thread_info *current_thread_info(void)
>  #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
>  #define _TIF_31BIT		(1<<TIF_31BIT)
>  #define _TIF_FREEZE		(1<<TIF_FREEZE)
> +#define _TIF_SIG_RESTARTBLOCK	(1<<TIF_SIG_RESTARTBLOCK)
>  
>  #endif /* __KERNEL__ */
>  
> diff --git a/arch/s390/kernel/checkpoint.c b/arch/s390/kernel/checkpoint.c
> index 60ba04d..cc7f341 100644
> --- a/arch/s390/kernel/checkpoint.c
> +++ b/arch/s390/kernel/checkpoint.c
> @@ -12,6 +12,7 @@
>  #include <asm/system.h>
>  #include <asm/pgtable.h>
>  #include <asm/elf.h>
> +#include <asm/unistd.h>
>  
>  #include <linux/checkpoint.h>
>  #include <linux/checkpoint_hdr.h>
> @@ -65,6 +66,18 @@ static void s390_copy_regs(int op, struct ckpt_hdr_cpu *h,
>  		BUG_ON(h->gprs[2] < 0);
>  		h->gprs[2] = 0;
>  	}
> +
> +	/*
> +	 * if a checkpoint was taken while interrupted from a restartable
> +	 * syscall, then treat this as though signr==0 (since we did not
> +	 * handle the signal) and finish the last part of do_signal
> +	 */
> +	if (op == CKPT_RST && test_thread_flag(TIF_SIG_RESTARTBLOCK)) {
> +		regs->gprs[2] = __NR_restart_syscall;
> +		set_thread_flag(TIF_RESTART_SVC);
> +		clear_thread_flag(TIF_SIG_RESTARTBLOCK);
> +	}
> +
>  	CKPT_COPY_ARRAY(op, h->fprs, thr->fp_regs.fprs, NUM_FPRS);
>  	CKPT_COPY_ARRAY(op, h->acrs, thr->acrs, NUM_ACRS);
>  	CKPT_COPY_ARRAY(op, h->per_control_regs,
> @@ -83,12 +96,24 @@ static void s390_mm(int op, struct ckpt_hdr_mm_context *h,
>  
>  int checkpoint_thread(struct ckpt_ctx *ctx, struct task_struct *t)
>  {
> +	struct ckpt_hdr_thread *h;
> +	int ret;
> +
>  	/* we will eventually support this, as we do on x86-64 */
>  	if (test_tsk_thread_flag(t, TIF_31BIT)) {
>  		ckpt_err(ctx, -EINVAL, "checkpoint of 31-bit task\n");
>  		return -EINVAL;
>  	}
> -	return 0;
> +
> +	h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_THREAD);
> +	if (!h)
> +		return -ENOMEM;
> +
> +	h->thread_info_flags = task_thread_info(t)->flags;
> +	ret = ckpt_write_obj(ctx, &h->h);
> +	ckpt_hdr_put(ctx, h);
> +
> +	return ret;
>  }
>  
>  /* dump the cpu state and registers of a given task */
> @@ -148,11 +173,36 @@ int checkpoint_mm_context(struct ckpt_ctx *ctx, struct mm_struct *mm)
>  
>  int restore_thread(struct ckpt_ctx *ctx)
>  {
> +	struct ckpt_hdr_thread *h;
> +
>  	/* a 31-bit task cannot call sys_restart right now */
>  	if (test_thread_flag(TIF_31BIT)) {
>  		ckpt_err(ctx, -EINVAL, "restart from 31-bit task\n");
>  		return -EINVAL;
>  	}
> +
> +	h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_THREAD);
> +	if (IS_ERR(h))
> +		return PTR_ERR(h);
> +
> +	/*
> +	 * If we were checkpointed while do_signal() interrupted a
> +	 * syscall with restart blocks, then we have some cleanup to
> +	 * do at end of restart, in order to finish our pretense of
> +	 * having handled signr==0.  (See last part of do_signal).
> +	 *
> +	 * We can't set gprs[2] here bc we haven't copied registers
> +	 * yet, that happens later in restore_cpu().  So re-set the
> +	 * TIF_SIG_RESTARTBLOCK thread flag so we can detect it
> +	 * at restore_cpu()->s390_copy_regs() and do the right thing.
> +	 */
> +	if (h->thread_info_flags & _TIF_SIG_RESTARTBLOCK)
> +		set_thread_flag(TIF_SIG_RESTARTBLOCK);
> +
> +	/* will have to handle TIF_RESTORE_SIGMASK as well */
> +
> +	ckpt_hdr_put(ctx, h);
> +
>  	return 0;
>  }
>  
> diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
> index 1675c48..9b6ca21 100644
> --- a/arch/s390/kernel/signal.c
> +++ b/arch/s390/kernel/signal.c
> @@ -459,6 +459,16 @@ void do_signal(struct pt_regs *regs)
>  			break;
>  		case -ERESTART_RESTARTBLOCK:
>  			regs->gprs[2] = -EINTR;
> +			/*
> +			 * This condition is the only one which requires
> +			 * special care after handling a signr==0.  So if
> +			 * we get frozen and checkpointed at the
> +			 * get_signal_to_deliver() below, then we need
> +			 * to convey this condition to sys_restart() so it
> +			 * can set the restored thread up to run the restart
> +			 * block.
> +			 */
> +			set_thread_flag(TIF_SIG_RESTARTBLOCK);
>  		}
>  		regs->svcnr = 0;	/* Don't deal with this again. */
>  	}
> @@ -467,6 +477,12 @@ void do_signal(struct pt_regs *regs)
>  	   the debugger may change all our registers ... */
>  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
>  
> +	/*
> +	 * we won't get frozen past this so clear the thread flag hinting
> +	 * to sys_restart that TIF_RESTART_SVC must be set.
> +	 */
> +	clear_thread_flag(TIF_SIG_RESTARTBLOCK);
> +
>  	/* Depending on the signal settings we may need to revert the
>  	   decision to restart the system call. */
>  	if (signr > 0 && regs->psw.addr == restart_addr) {
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list