[Xenomai-git] Philippe Gerum : copperplate/threadobj: prevent priority inversion in threadobj_cancel()

2015-05-02 Thread git repository hosting
Module: xenomai-3
Branch: master
Commit: d3a61fef180f14f7de88f319d8e4a8e981013355
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d3a61fef180f14f7de88f319d8e4a8e981013355

Author: Philippe Gerum 
Date:   Fri May  1 18:41:49 2015 +0200

copperplate/threadobj: prevent priority inversion in threadobj_cancel()

We provide a guarantee to threadobj_cancel() callers that the killed
thread has actually exited when the call returns.

This change fixes an issue with L < M < H priority threads, with H
calling threadobj_cancel() on L, while M is spinning. To address this,
we boost L to H's priority before waiting for the "deletion confirmed"
event, which is sent from L's finalizer.

---

 lib/copperplate/threadobj.c |   27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index 1dcf9bd..5a528fa 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -88,6 +88,8 @@ static pid_t agent_pid;
 
 struct remote_cancel {
pthread_t ptid;
+   int policy;
+   struct sched_param_ex param_ex;
 };
 
 struct remote_setsched {
@@ -139,6 +141,10 @@ static void *agent_loop(void *arg)
  
&rq->u.setsched.param_ex);
break;
case RMT_CANCEL:
+   if (rq->u.cancel.policy != -1)
+   
copperplate_renice_local_thread(rq->u.cancel.ptid,
+   
rq->u.cancel.policy,
+   
&rq->u.cancel.param_ex);
ret = pthread_cancel(rq->u.cancel.ptid);
break;
default:
@@ -995,6 +1001,8 @@ static int request_setschedparam(struct threadobj *thobj, 
int policy,
 
 static int request_cancel(struct threadobj *thobj) /* thobj->lock held, 
dropped. */
 {
+   struct threadobj *current = threadobj_current();
+   int thprio = thobj->global_priority;
pthread_t ptid = thobj->ptid;
 #ifdef CONFIG_XENO_PSHARED
struct remote_request *rq;
@@ -1008,7 +1016,11 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 
rq->req = RMT_CANCEL;
rq->u.cancel.ptid = ptid;
-
+   rq->u.cancel.policy = -1;
+   if (current) {
+   rq->u.cancel.policy = current->policy;
+   rq->u.cancel.param_ex = current->schedparam;
+   }
ret = __bt(send_agent(thobj, rq));
if (ret)
xnfree(rq);
@@ -1017,8 +1029,19 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 #endif
threadobj_unlock(thobj);
 
-   /* We might race, glibc will check. */
+   /*
+* The caller will have to wait for the killed thread to enter
+* its finalizer, so we boost the latter thread to prevent a
+* priority inversion if need be.
+*
+* NOTE: Since we dropped the lock, we might race if ptid
+* disappears while we are busy killing it, glibc will check
+* and dismiss if so.
+*/
 
+   if (current && thprio < current->global_priority)
+   copperplate_renice_local_thread(ptid, current->policy,
+   ¤t->schedparam);
pthread_cancel(ptid);
 
return 0;


___
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git


[Xenomai-git] Philippe Gerum : copperplate/threadobj: prevent priority inversion in threadobj_cancel()

2015-05-02 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: d3a61fef180f14f7de88f319d8e4a8e981013355
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=d3a61fef180f14f7de88f319d8e4a8e981013355

Author: Philippe Gerum 
Date:   Fri May  1 18:41:49 2015 +0200

copperplate/threadobj: prevent priority inversion in threadobj_cancel()

We provide a guarantee to threadobj_cancel() callers that the killed
thread has actually exited when the call returns.

This change fixes an issue with L < M < H priority threads, with H
calling threadobj_cancel() on L, while M is spinning. To address this,
we boost L to H's priority before waiting for the "deletion confirmed"
event, which is sent from L's finalizer.

---

 lib/copperplate/threadobj.c |   27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index 1dcf9bd..5a528fa 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -88,6 +88,8 @@ static pid_t agent_pid;
 
 struct remote_cancel {
pthread_t ptid;
+   int policy;
+   struct sched_param_ex param_ex;
 };
 
 struct remote_setsched {
@@ -139,6 +141,10 @@ static void *agent_loop(void *arg)
  
&rq->u.setsched.param_ex);
break;
case RMT_CANCEL:
+   if (rq->u.cancel.policy != -1)
+   
copperplate_renice_local_thread(rq->u.cancel.ptid,
+   
rq->u.cancel.policy,
+   
&rq->u.cancel.param_ex);
ret = pthread_cancel(rq->u.cancel.ptid);
break;
default:
@@ -995,6 +1001,8 @@ static int request_setschedparam(struct threadobj *thobj, 
int policy,
 
 static int request_cancel(struct threadobj *thobj) /* thobj->lock held, 
dropped. */
 {
+   struct threadobj *current = threadobj_current();
+   int thprio = thobj->global_priority;
pthread_t ptid = thobj->ptid;
 #ifdef CONFIG_XENO_PSHARED
struct remote_request *rq;
@@ -1008,7 +1016,11 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 
rq->req = RMT_CANCEL;
rq->u.cancel.ptid = ptid;
-
+   rq->u.cancel.policy = -1;
+   if (current) {
+   rq->u.cancel.policy = current->policy;
+   rq->u.cancel.param_ex = current->schedparam;
+   }
ret = __bt(send_agent(thobj, rq));
if (ret)
xnfree(rq);
@@ -1017,8 +1029,19 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 #endif
threadobj_unlock(thobj);
 
-   /* We might race, glibc will check. */
+   /*
+* The caller will have to wait for the killed thread to enter
+* its finalizer, so we boost the latter thread to prevent a
+* priority inversion if need be.
+*
+* NOTE: Since we dropped the lock, we might race if ptid
+* disappears while we are busy killing it, glibc will check
+* and dismiss if so.
+*/
 
+   if (current && thprio < current->global_priority)
+   copperplate_renice_local_thread(ptid, current->policy,
+   ¤t->schedparam);
pthread_cancel(ptid);
 
return 0;


___
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git


[Xenomai-git] Philippe Gerum : copperplate/threadobj: prevent priority inversion in threadobj_cancel()

2015-05-01 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: 8431d7149405235fb0aebb53ed32a537ad968c7e
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=8431d7149405235fb0aebb53ed32a537ad968c7e

Author: Philippe Gerum 
Date:   Fri May  1 18:41:49 2015 +0200

copperplate/threadobj: prevent priority inversion in threadobj_cancel()

We provide a guarantee to threadobj_cancel() callers that the killed
thread has actually exited when the call returns.

This change fixes an issue with L < M < H priority threads, with H
calling threadobj_cancel() on L, while M is spinning. To address this,
we boost L to H's priority before waiting for the "deletion confirmed"
event, which is sent from L's finalizer.

---

 lib/copperplate/threadobj.c |   26 --
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index 1dcf9bd..395c403 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -88,6 +88,8 @@ static pid_t agent_pid;
 
 struct remote_cancel {
pthread_t ptid;
+   int policy;
+   struct sched_param_ex param_ex;
 };
 
 struct remote_setsched {
@@ -139,6 +141,10 @@ static void *agent_loop(void *arg)
  
&rq->u.setsched.param_ex);
break;
case RMT_CANCEL:
+   if (rq->u.cancel.policy != -1)
+   
copperplate_renice_local_thread(rq->u.cancel.ptid,
+   
rq->u.cancel.policy,
+   
&rq->u.cancel.param_ex);
ret = pthread_cancel(rq->u.cancel.ptid);
break;
default:
@@ -995,6 +1001,7 @@ static int request_setschedparam(struct threadobj *thobj, 
int policy,
 
 static int request_cancel(struct threadobj *thobj) /* thobj->lock held, 
dropped. */
 {
+   struct threadobj *current = threadobj_current();
pthread_t ptid = thobj->ptid;
 #ifdef CONFIG_XENO_PSHARED
struct remote_request *rq;
@@ -1008,7 +1015,11 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 
rq->req = RMT_CANCEL;
rq->u.cancel.ptid = ptid;
-
+   rq->u.cancel.policy = -1;
+   if (current) {
+   rq->u.cancel.policy = current->policy;
+   rq->u.cancel.param_ex = current->schedparam;
+   }
ret = __bt(send_agent(thobj, rq));
if (ret)
xnfree(rq);
@@ -1017,8 +1028,19 @@ static int request_cancel(struct threadobj *thobj) /* 
thobj->lock held, dropped.
 #endif
threadobj_unlock(thobj);
 
-   /* We might race, glibc will check. */
+   /*
+* The caller will have to wait for the killed thread to enter
+* its finalizer, so we boost the latter thread to prevent a
+* priority inversion if need be.
+*
+* NOTE: Since we dropped the lock, we might race if ptid
+* disappears while we are busy killing it, glibc will check
+* and dismiss if so.
+*/
 
+   if (current && thobj->global_priority < current->global_priority)
+   copperplate_renice_local_thread(ptid, current->policy,
+   ¤t->schedparam);
pthread_cancel(ptid);
 
return 0;


___
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git