Module: xenomai-3 Branch: next Commit: 7a81ea81d92e33ff4d78b01646ebb8af070d7e4a URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=7a81ea81d92e33ff4d78b01646ebb8af070d7e4a
Author: Philippe Gerum <r...@xenomai.org> Date: Thu Nov 27 22:02:32 2014 +0100 cobalt/posix/thread: fix error handling upon failure to map shadow --- include/cobalt/kernel/thread.h | 2 ++ kernel/cobalt/posix/thread.c | 36 +++++++++++++++++++++++++++--------- kernel/cobalt/thread.c | 19 +++++++++++++++++++ 3 files changed, 48 insertions(+), 9 deletions(-) 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. _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git