* [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user @ 2014-11-25 19:42 Jan Kiszka 2014-11-25 20:37 ` Philippe Gerum 0 siblings, 1 reply; 4+ messages in thread From: Jan Kiszka @ 2014-11-25 19:42 UTC (permalink / raw) To: Xenomai Hi, I ran into an oops (bt below) when (for yet unknown reasons) cobalt_map_user fails. The reason is that we then call xnthread_cancel, but on a thread that has no user space task assigned yet. Which functions rolls only pthread_create back? The issue should apply to cobalt_thread_shadow as well. Jan (gdb) bt #0 dump_stack () at /data/linux-ipipe/lib/dump_stack.c:27 #1 0xffffffff810e75ad in ipipe_root_only () at /data/linux-ipipe/kernel/ipipe/core.c:1685 #2 0xffffffff810e86b1 in ipipe_unstall_root () at /data/linux-ipipe/kernel/ipipe/core.c:419 #3 0xffffffff8168a51a in arch_local_irq_enable () at /data/linux-ipipe/arch/x86/include/asm/irqflags.h:114 #4 __do_page_fault (regs=0xffff88003a4a7cc8, error_code=0, address=732) at /data/linux-ipipe/arch/x86/mm/fault.c:1134 #5 0xffffffff8168a7b2 in do_page_fault (regs=<optimized out>, error_code=<optimized out>) at /data/linux-ipipe/arch/x86/mm/fault.c:1277 #6 0xffffffff8102ea1a in __ipipe_handle_exception (regs=0xffff88003a4a7cc8, error_code=-131940329925848, vector=14) at /data/linux-ipipe/arch/x86/kernel/ipipe.c:438 #7 <signal handler called> #8 0xffffffff81133902 in xnthread_host_pid (thread=<optimized out>) at /data/linux-ipipe/include/xenomai/cobalt/kernel/thread.h:249 #9 xnthread_resume (thread=0xffff88003c204040, mask=<optimized out>) at /data/linux-ipipe/kernel/xenomai/thread.c:1038 #10 0xffffffff81137a5f in xnthread_cancel (thread=0xffff88003c204040) at /data/linux-ipipe/kernel/xenomai/thread.c:1463 #11 0xffffffff81179f45 in __cobalt_thread_create (pth=140597174187776, policy=<optimized out>, param_ex=0xffff88003a4a7e80, xid=<optimized out>, u_winoff=<optimized out>) at /data/linux-ipipe/kernel/xenomai/posix/thread.c:586 #12 0xffffffff8117a164 in cobalt_thread_create (pth=140597174187776, policy=0, u_param=<optimized out>, xid=0, u_winoff=0x7fdf549fae94) at /data/linux-ipipe/kernel/xenomai/posix/thread.c:604 #13 0xffffffff8117031a in handle_root_syscall (ipd=<optimized out>, regs=<optimized out>) at /data/linux-ipipe/kernel/xenomai/posix/syscall.c:950 #14 ipipe_syscall_hook (ipd=<optimized out>, regs=0xffff88003a4a7f58) at /data/linux-ipipe/kernel/xenomai/posix/syscall.c:999 #15 0xffffffff810e97a7 in __ipipe_notify_syscall (regs=<optimized out>) at /data/linux-ipipe/kernel/ipipe/core.c:1045 #16 <signal handler called> #17 0x00007fdf5591caff in ?? () #18 0xffff88003b9ef220 in ?? () #19 0xffffffff819a75a0 in ?? () #20 0x0000000000000000 in ?? () -- Siemens AG, Corporate Technology, CT RTC ITP SES-DE Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user 2014-11-25 19:42 [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user Jan Kiszka @ 2014-11-25 20:37 ` Philippe Gerum 2014-11-25 20:36 ` Jan Kiszka 2014-11-26 12:53 ` Jan Kiszka 0 siblings, 2 replies; 4+ messages in thread From: Philippe Gerum @ 2014-11-25 20:37 UTC (permalink / raw) To: Jan Kiszka, Xenomai On 11/25/2014 08:42 PM, Jan Kiszka wrote: > Hi, > > I ran into an oops (bt below) when (for yet unknown reasons) > cobalt_map_user fails. The reason is that we then call xnthread_cancel, > but on a thread that has no user space task assigned yet. > Ack, it's terminally broken. > Which functions rolls only pthread_create back? > None, we need one which specifically applies to a dormant, unmapped thread. The existing code assumes a mapped thread. > The issue should apply to cobalt_thread_shadow as well. > Correct. In theory, this patch should fix it. In practice, it's untested code in all its glory: diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h index 72168f4..535489b 100644 --- a/include/cobalt/kernel/thread.h +++ b/include/cobalt/kernel/thread.h @@ -332,6 +332,8 @@ void __xnthread_test_cancel(struct xnthread *curr); void __xnthread_cleanup(struct xnthread *curr); +void __xnthread_discard(struct xnthread *thread); + /** * @fn struct xnthread *xnthread_current(void) * @brief Retrieve the current Cobalt core TCB. diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c index 3ab20f6..7c78405 100644 --- a/kernel/cobalt/posix/thread.c +++ b/kernel/cobalt/posix/thread.c @@ -345,10 +345,10 @@ unlock_and_exit: return 0; } -static inline int pthread_create(struct cobalt_thread **thread_p, - int policy, - const struct sched_param_ex *param_ex, - struct task_struct *task) +static int pthread_create(struct cobalt_thread **thread_p, + int policy, + const struct sched_param_ex *param_ex, + struct task_struct *task) { struct xnsched_class *sched_class; union xnsched_policy_param param; @@ -416,6 +416,20 @@ static inline int pthread_create(struct cobalt_thread **thread_p, return 0; } +static void pthread_discard(struct cobalt_thread *thread) +{ + spl_t s; + + xnsynch_destroy(&thread->monitor_synch); + xnsynch_destroy(&thread->sigwait); + + xnlock_get_irqsave(&nklock, s); + list_del(&thread->link); + xnlock_put_irqrestore(&nklock, s); + __xnthread_discard(&thread->threadbase); + xnfree(thread); +} + static inline int pthread_setmode_np(int clrmask, int setmask, int *mode_r) { const int valid_flags = XNLOCK|XNWARN|XNTRAPLB; @@ -566,8 +580,10 @@ int __cobalt_thread_create(unsigned long pth, int policy, return ret; ret = cobalt_map_user(&thread->threadbase, u_winoff); - if (ret) - goto fail; + if (ret) { + pthread_discard(thread); + return ret; + } if (!thread_hash(&hkey, thread, task_pid_vnr(p))) { ret = -EAGAIN; @@ -617,11 +633,13 @@ cobalt_thread_shadow(struct task_struct *p, trace_cobalt_pthread_create(hkey->u_pth, SCHED_NORMAL, ¶m_ex); ret = pthread_create(&thread, SCHED_NORMAL, ¶m_ex, p); if (ret) - return ERR_PTR(-ret); + return ERR_PTR(ret); ret = cobalt_map_user(&thread->threadbase, u_winoff); - if (ret) - goto fail; + if (ret) { + pthread_discard(thread); + return ERR_PTR(ret); + } if (!thread_hash(hkey, thread, task_pid_vnr(p))) { ret = -EAGAIN; diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c index f5444d3..e7726dd 100644 --- a/kernel/cobalt/thread.c +++ b/kernel/cobalt/thread.c @@ -492,6 +492,25 @@ void __xnthread_cleanup(struct xnthread *curr) wake_up(&nkjoinq); } +/* + * Unwinds xnthread_init() ops for an unmapped thread. Since the + * latter must be dormant, it can't be part of any runqueue. + */ +void __xnthread_discard(struct xnthread *thread) +{ + spl_t s; + + xntimer_destroy(&thread->rtimer); + xntimer_destroy(&thread->ptimer); + + xnlock_get_irqsave(&nklock, s); + list_del(&thread->glink); + nknrthreads--; + xnvfile_touch_tag(&nkthreadlist_tag); + xnthread_deregister(thread); + xnlock_put_irqrestore(&nklock, s); +} + /** * @fn void xnthread_init(struct xnthread *thread,const struct xnthread_init_attr *attr,struct xnsched_class *sched_class,const union xnsched_policy_param *sched_param) * @brief Initialize a new thread. -- Philippe. ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user 2014-11-25 20:37 ` Philippe Gerum @ 2014-11-25 20:36 ` Jan Kiszka 2014-11-26 12:53 ` Jan Kiszka 1 sibling, 0 replies; 4+ messages in thread From: Jan Kiszka @ 2014-11-25 20:36 UTC (permalink / raw) To: Philippe Gerum, Xenomai On 2014-11-25 21:37, Philippe Gerum wrote: > On 11/25/2014 08:42 PM, Jan Kiszka wrote: >> Hi, >> >> I ran into an oops (bt below) when (for yet unknown reasons) >> cobalt_map_user fails. The reason is that we then call xnthread_cancel, >> but on a thread that has no user space task assigned yet. >> > > Ack, it's terminally broken. > >> Which functions rolls only pthread_create back? >> > > None, we need one which specifically applies to a dormant, unmapped thread. The existing code assumes a mapped thread. > >> The issue should apply to cobalt_thread_shadow as well. >> > > Correct. In theory, this patch should fix it. In practice, it's untested code in all its glory: Wish I could still test, but I happened to have found the trigger of that issue - an inconsistent kernel build - and destroyed it along the way. Will check tomorrow via an artificial failure of cobalt_map_user. Jan -- Siemens AG, Corporate Technology, CT RTC ITP SES-DE Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user 2014-11-25 20:37 ` Philippe Gerum 2014-11-25 20:36 ` Jan Kiszka @ 2014-11-26 12:53 ` Jan Kiszka 1 sibling, 0 replies; 4+ messages in thread From: Jan Kiszka @ 2014-11-26 12:53 UTC (permalink / raw) To: Philippe Gerum, Xenomai On 2014-11-25 21:37, Philippe Gerum wrote: > On 11/25/2014 08:42 PM, Jan Kiszka wrote: >> Hi, >> >> I ran into an oops (bt below) when (for yet unknown reasons) >> cobalt_map_user fails. The reason is that we then call xnthread_cancel, >> but on a thread that has no user space task assigned yet. >> > > Ack, it's terminally broken. > >> Which functions rolls only pthread_create back? >> > > None, we need one which specifically applies to a dormant, unmapped thread. The existing code assumes a mapped thread. > >> The issue should apply to cobalt_thread_shadow as well. >> > > Correct. In theory, this patch should fix it. In practice, it's untested code in all its glory: Looks good, test passed here. > > diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h > index 72168f4..535489b 100644 > --- a/include/cobalt/kernel/thread.h > +++ b/include/cobalt/kernel/thread.h > @@ -332,6 +332,8 @@ void __xnthread_test_cancel(struct xnthread *curr); > > void __xnthread_cleanup(struct xnthread *curr); > > +void __xnthread_discard(struct xnthread *thread); > + > /** > * @fn struct xnthread *xnthread_current(void) > * @brief Retrieve the current Cobalt core TCB. > diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c > index 3ab20f6..7c78405 100644 > --- a/kernel/cobalt/posix/thread.c > +++ b/kernel/cobalt/posix/thread.c > @@ -345,10 +345,10 @@ unlock_and_exit: > return 0; > } > > -static inline int pthread_create(struct cobalt_thread **thread_p, > - int policy, > - const struct sched_param_ex *param_ex, > - struct task_struct *task) > +static int pthread_create(struct cobalt_thread **thread_p, > + int policy, > + const struct sched_param_ex *param_ex, > + struct task_struct *task) > { > struct xnsched_class *sched_class; > union xnsched_policy_param param; > @@ -416,6 +416,20 @@ static inline int pthread_create(struct cobalt_thread **thread_p, > return 0; > } > > +static void pthread_discard(struct cobalt_thread *thread) > +{ > + spl_t s; > + > + xnsynch_destroy(&thread->monitor_synch); > + xnsynch_destroy(&thread->sigwait); > + > + xnlock_get_irqsave(&nklock, s); > + list_del(&thread->link); > + xnlock_put_irqrestore(&nklock, s); > + __xnthread_discard(&thread->threadbase); > + xnfree(thread); > +} > + > static inline int pthread_setmode_np(int clrmask, int setmask, int *mode_r) > { > const int valid_flags = XNLOCK|XNWARN|XNTRAPLB; > @@ -566,8 +580,10 @@ int __cobalt_thread_create(unsigned long pth, int policy, > return ret; > > ret = cobalt_map_user(&thread->threadbase, u_winoff); > - if (ret) > - goto fail; > + if (ret) { > + pthread_discard(thread); > + return ret; > + } > > if (!thread_hash(&hkey, thread, task_pid_vnr(p))) { > ret = -EAGAIN; > @@ -617,11 +633,13 @@ cobalt_thread_shadow(struct task_struct *p, > trace_cobalt_pthread_create(hkey->u_pth, SCHED_NORMAL, ¶m_ex); > ret = pthread_create(&thread, SCHED_NORMAL, ¶m_ex, p); > if (ret) > - return ERR_PTR(-ret); > + return ERR_PTR(ret); > > ret = cobalt_map_user(&thread->threadbase, u_winoff); > - if (ret) > - goto fail; > + if (ret) { > + pthread_discard(thread); > + return ERR_PTR(ret); > + } After removing this jump source of the fail label, you could fold the latter into its last user. Jan > > if (!thread_hash(hkey, thread, task_pid_vnr(p))) { > ret = -EAGAIN; > diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c > index f5444d3..e7726dd 100644 > --- a/kernel/cobalt/thread.c > +++ b/kernel/cobalt/thread.c > @@ -492,6 +492,25 @@ void __xnthread_cleanup(struct xnthread *curr) > wake_up(&nkjoinq); > } > > +/* > + * Unwinds xnthread_init() ops for an unmapped thread. Since the > + * latter must be dormant, it can't be part of any runqueue. > + */ > +void __xnthread_discard(struct xnthread *thread) > +{ > + spl_t s; > + > + xntimer_destroy(&thread->rtimer); > + xntimer_destroy(&thread->ptimer); > + > + xnlock_get_irqsave(&nklock, s); > + list_del(&thread->glink); > + nknrthreads--; > + xnvfile_touch_tag(&nkthreadlist_tag); > + xnthread_deregister(thread); > + xnlock_put_irqrestore(&nklock, s); > +} > + > /** > * @fn void xnthread_init(struct xnthread *thread,const struct xnthread_init_attr *attr,struct xnsched_class *sched_class,const union xnsched_policy_param *sched_param) > * @brief Initialize a new thread. > -- Siemens AG, Corporate Technology, CT RTC ITP SES-DE Corporate Competence Center Embedded Linux ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-11-26 12:53 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-11-25 19:42 [Xenomai] __cobalt_thread_create: cleanup after failing cobalt_map_user Jan Kiszka 2014-11-25 20:37 ` Philippe Gerum 2014-11-25 20:36 ` Jan Kiszka 2014-11-26 12:53 ` Jan Kiszka
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.