DragonFly submit List (threaded) for 2007-04
[
Date Prev][Date Next]
[
Thread Prev][Thread Next]
[
Date Index][
Thread Index]
Re: cvs commit: src/lib Makefile src/lib/libpthread Makefile README dummy.c
On Tuesday 17 April 2007 15:42, Simon 'corecode' Schubert wrote:
[...]
> Known issues (of libthread_xu/system):
> Mozilla stuff doesn't work. they use sched_get_priority_min/max() and
> pthread_setsched_prio(). units disagree (former reporting -20/20, later
> expecting 0-32 or so). this has to be streamlined somehow.
>
> Unfortunately I won't have time to do this in the next month because I am
> on tour, so I'd be grateful if somebody else could jump in. It's not much
> work left!
The first attached patch (lwp_prio) adds a new syscall
int lwp_rtprio (int, pid_t, lwpid_t, struct rtprio *);
that monkeys rtprio(2) and works on lwps. The other patch brings in code from
freebsd (+ some small changes to /not/ silently accept any priority value for
SCHED_OTHER) in libthread_xu, so that now my test program can only set
priority values within sched_get_priority_{min,max} and smaller/larger values
fail. The values are passed on to the kernel using lwp_rtprio() but the
kernel side is not well tested.
Since, AFAICT lwpid can be zero lwp_rtprio() uses pid 0 for "current process"
but lwpid -1 for "current thread", which IMO is ugly. Perhaps we should also
reserve lwpid 0? Alternatively, I can change it to -1 for both. Then again,
very few programs are ever going to use this. Opinions are welcome.
Don't know if this fixes thunderbird; can someone who has it linked against
libpthread switch the symlink and test?
Aggelos
Index: kern/kern_resource.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/sys/kern/kern_resource.c,v
retrieving revision 1.31
diff -u -u -r1.31 kern_resource.c
--- kern/kern_resource.c 3 Feb 2007 17:05:58 -0000 1.31
+++ kern/kern_resource.c 28 Apr 2007 20:24:55 -0000
@@ -261,6 +261,98 @@
return (0);
}
+int
+sys_lwp_rtprio(struct lwp_rtprio_args *uap)
+{
+ struct proc *p = curproc;
+ struct lwp *lp;
+ struct rtprio rtp;
+ struct ucred *cr = p->p_ucred;
+ int error;
+
+ error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
+ if (error)
+ return error;
+
+ if (uap->pid < 0) {
+ return EINVAL;
+ } else if (uap->pid == 0) {
+ /* curproc already loaded on p */
+ } else {
+ p = pfind(uap->pid);
+ }
+
+ if (p == 0) {
+ return ESRCH;
+ }
+
+ if (uap->tid < -1) {
+ return EINVAL;
+ } else if (uap->tid == -1) {
+ /*
+ * sadly, tid can be 0 so we can't use 0 here
+ * like sys_rtprio()
+ */
+ lp = curthread->td_lwp;
+ } else {
+ FOREACH_LWP_IN_PROC(lp, p) {
+ if (lp->lwp_tid == uap->tid) {
+ break;
+ }
+ }
+ if (!lp) {
+ return ESRCH;
+ }
+ }
+
+ switch (uap->function) {
+ case RTP_LOOKUP:
+ return (copyout(&lp->lwp_rtprio, uap->rtp,
+ sizeof(struct rtprio)));
+ case RTP_SET:
+ if (cr->cr_uid && cr->cr_ruid &&
+ cr->cr_uid != p->p_ucred->cr_uid &&
+ cr->cr_ruid != p->p_ucred->cr_uid) {
+ return EPERM;
+ }
+ /* disallow setting rtprio in most cases if not superuser */
+ if (suser_cred(cr, 0)) {
+ /* can't set someone else's */
+ if (uap->pid) { /* XXX */
+ return EPERM;
+ }
+ /* can't set realtime priority */
+/*
+ * Realtime priority has to be restricted for reasons which should be
+ * obvious. However, for idle priority, there is a potential for
+ * system deadlock if an idleprio process gains a lock on a resource
+ * that other processes need (and the idleprio process can't run
+ * due to a CPU-bound normal process). Fix me! XXX
+ */
+ if (RTP_PRIO_IS_REALTIME(rtp.type)) {
+ return EPERM;
+ }
+ }
+ switch (rtp.type) {
+#ifdef RTP_PRIO_FIFO
+ case RTP_PRIO_FIFO:
+#endif
+ case RTP_PRIO_REALTIME:
+ case RTP_PRIO_NORMAL:
+ case RTP_PRIO_IDLE:
+ if (rtp.prio > RTP_PRIO_MAX)
+ return EINVAL;
+ lp->lwp_rtprio = rtp;
+ return 0;
+ default:
+ return EINVAL;
+ }
+ default:
+ return EINVAL;
+ }
+ panic("can't get here");
+}
+
/*
* Set realtime priority
*/
Index: kern/syscalls.master
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/sys/kern/syscalls.master,v
retrieving revision 1.54
diff -u -u -r1.54 syscalls.master
--- kern/syscalls.master 22 Apr 2007 00:59:25 -0000 1.54
+++ kern/syscalls.master 28 Apr 2007 12:01:48 -0000
@@ -680,3 +680,4 @@
495 STD BSD { int lwp_create(struct lwp_params *params); }
496 STD BSD { lwpid_t lwp_gettid(void); }
497 STD BSD { int lwp_kill(pid_t pid, lwpid_t tid, int signum); }
+498 STD BSD { int lwp_rtprio(int function, pid_t pid, lwpid_t tid, struct rtprio *rtp); }
Index: sys/rtprio.h
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/sys/sys/rtprio.h,v
retrieving revision 1.5
diff -u -u -r1.5 rtprio.h
--- sys/rtprio.h 20 May 2006 02:42:13 -0000 1.5
+++ sys/rtprio.h 28 Apr 2007 17:38:22 -0000
@@ -81,6 +81,7 @@
__BEGIN_DECLS
int rtprio (int, pid_t, struct rtprio *);
+int lwp_rtprio (int, pid_t, lwpid_t, struct rtprio *);
__END_DECLS
#endif /* !_KERNEL */
#endif /* !_SYS_RTPRIO_H_ */
Index: thread/thr_attr.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_attr.c,v
retrieving revision 1.7
diff -u -u -r1.7 thr_attr.c
--- thread/thr_attr.c 6 Apr 2006 13:03:09 -0000 1.7
+++ thread/thr_attr.c 27 Apr 2007 21:37:04 -0000
@@ -49,7 +49,6 @@
struct pthread_attr _pthread_attr_default = {
.sched_policy = SCHED_OTHER,
.sched_inherit = 0,
- .sched_interval = TIMESLICE_USEC,
.prio = THR_DEFAULT_PRIORITY,
.suspend = THR_CREATE_RUNNING,
.flags = 0,
Index: thread/thr_getschedparam.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_getschedparam.c,v
retrieving revision 1.4
diff -u -u -r1.4 thr_getschedparam.c
--- thread/thr_getschedparam.c 6 Apr 2006 13:03:09 -0000 1.4
+++ thread/thr_getschedparam.c 28 Apr 2007 09:46:01 -0000
@@ -46,34 +46,30 @@
struct sched_param *param)
{
struct pthread *curthread = tls_get_curthread();
- int ret, tmp;
+ int ret;
- if ((param == NULL) || (policy == NULL))
- /* Return an invalid argument error: */
- ret = EINVAL;
- else if (pthread == curthread) {
+ if (policy == NULL || param == NULL)
+ return (EINVAL);
+
+ if (pthread == curthread) {
/*
* Avoid searching the thread list when it is the current
* thread.
*/
- THR_THREAD_LOCK(curthread, curthread);
- param->sched_priority =
- THR_BASE_PRIORITY(pthread->base_priority);
- tmp = pthread->attr.sched_policy;
- THR_THREAD_UNLOCK(curthread, curthread);
- *policy = tmp;
+ THR_LOCK(curthread);
+ *policy = curthread->attr.sched_policy;
+ param->sched_priority = curthread->attr.prio;
+ THR_UNLOCK(curthread);
ret = 0;
}
/* Find the thread in the list of active threads. */
else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
== 0) {
THR_THREAD_LOCK(curthread, pthread);
- param->sched_priority =
- THR_BASE_PRIORITY(pthread->base_priority);
- tmp = pthread->attr.sched_policy;
+ *policy = pthread->attr.sched_policy;
+ param->sched_priority = pthread->attr.prio;
THR_THREAD_UNLOCK(curthread, pthread);
_thr_ref_delete(curthread, pthread);
- *policy = tmp;
}
return (ret);
}
Index: thread/thr_kern.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_kern.c,v
retrieving revision 1.2
diff -u -u -r1.2 thr_kern.c
--- thread/thr_kern.c 13 Mar 2007 00:19:29 -0000 1.2
+++ thread/thr_kern.c 30 Apr 2007 11:17:45 -0000
@@ -29,6 +29,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/signalvar.h>
+#include <sys/rtprio.h>
#include <pthread.h>
#include "thr_private.h"
@@ -103,3 +104,114 @@
{
return (lwp_gettid());
}
+
+/*
+ * We don't use the priority for SCHED_OTHER, but
+ * some programs may depend on getting an error when
+ * setting a priority that is out of the range returned
+ * by sched_get_priority_{min,max}. Not sure if this
+ * falls into implementation defined behavior or not.
+ */
+int
+_thr_set_sched_other_prio(struct pthread *pth, int prio)
+{
+ static int max, min, init_status;
+
+ /*
+ * switch (init_status) {
+ * case 0: need initialization
+ * case 1: initialization successful
+ * case 2: initialization failed. can't happen, but if
+ * it does, accept all and hope for the best.
+ * It's not like we use it anyway.
+ */
+ if (!init_status) {
+ int tmp = errno;
+
+ errno = 0;
+ init_status = 1;
+ if (((min = sched_get_priority_min(SCHED_OTHER)) == -1) &&
+ (errno != 0))
+ init_status = 2;
+ if (((max = sched_get_priority_max(SCHED_OTHER)) == -1) &&
+ (errno != 0))
+ init_status = 2;
+ errno = tmp;
+ }
+ if ((init_status == 2) || ((prio >= min) && (prio <= max))) {
+ return 0;
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+int
+_rtp_to_schedparam(const struct rtprio *rtp, int *policy,
+ struct sched_param *param)
+{
+ switch(rtp->type) {
+ case RTP_PRIO_REALTIME:
+ *policy = SCHED_RR;
+ param->sched_priority = RTP_PRIO_MAX - rtp->prio;
+ break;
+ case RTP_PRIO_FIFO:
+ *policy = SCHED_FIFO;
+ param->sched_priority = RTP_PRIO_MAX - rtp->prio;
+ break;
+ default:
+ *policy = SCHED_OTHER;
+ param->sched_priority = 0;
+ break;
+ }
+ return (0);
+}
+
+int
+_schedparam_to_rtp(int policy, const struct sched_param *param,
+ struct rtprio *rtp)
+{
+ switch(policy) {
+ case SCHED_RR:
+ rtp->type = RTP_PRIO_REALTIME;
+ rtp->prio = RTP_PRIO_MAX - param->sched_priority;
+ break;
+ case SCHED_FIFO:
+ rtp->type = RTP_PRIO_FIFO;
+ rtp->prio = RTP_PRIO_MAX - param->sched_priority;
+ break;
+ case SCHED_OTHER:
+ default:
+ rtp->type = RTP_PRIO_NORMAL;
+ rtp->prio = 0;
+ break;
+ }
+ return (0);
+}
+
+int
+_thr_getscheduler(lwpid_t lwpid, int *policy, struct sched_param *param)
+{
+ struct pthread *curthread = tls_get_curthread();
+ struct rtprio rtp;
+ int ret;
+
+ if (lwpid == curthread->tid)
+ lwpid = -1;
+ ret = lwp_rtprio(RTP_LOOKUP, 0, lwpid, &rtp);
+ if (ret == -1)
+ return (ret);
+ _rtp_to_schedparam(&rtp, policy, param);
+ return (0);
+}
+
+int
+_thr_setscheduler(lwpid_t lwpid, int policy, const struct sched_param *param)
+{
+ struct pthread *curthread = tls_get_curthread();
+ struct rtprio rtp;
+
+ if (lwpid == curthread->tid)
+ lwpid = -1;
+ _schedparam_to_rtp(policy, param, &rtp);
+ return (lwp_rtprio(RTP_SET, 0, lwpid, &rtp));
+}
Index: thread/thr_private.h
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_private.h,v
retrieving revision 1.15
diff -u -u -r1.15 thr_private.h
--- thread/thr_private.h 13 Apr 2006 11:48:01 -0000 1.15
+++ thread/thr_private.h 30 Apr 2007 10:38:54 -0000
@@ -236,7 +236,6 @@
struct pthread_attr {
int sched_policy;
int sched_inherit;
- int sched_interval;
int prio;
int suspend;
#define THR_STACK_USER 0x100 /* 0xFF reserved for <pthread.h> */
@@ -691,6 +690,9 @@
void _thr_report_death(struct pthread *curthread);
void _thread_bp_create(void);
void _thread_bp_death(void);
+int _thr_getscheduler(lwpid_t, int *, struct sched_param *);
+int _thr_setscheduler(lwpid_t, int, const struct sched_param *);
+int _thr_set_sched_other_prio(struct pthread *, int);
/* #include <sys/aio.h> */
#ifdef _SYS_AIO_H_
Index: thread/thr_setschedparam.c
===================================================================
RCS file: /home/aggelos/imports/vcs/dcvs/src/lib/libthread_xu/thread/thr_setschedparam.c,v
retrieving revision 1.5
diff -u -u -r1.5 thr_setschedparam.c
--- thread/thr_setschedparam.c 6 Apr 2006 13:03:09 -0000 1.5
+++ thread/thr_setschedparam.c 30 Apr 2007 10:40:46 -0000
@@ -49,49 +49,47 @@
struct pthread *curthread = tls_get_curthread();
int ret = 0;
- if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) {
- /* Return an invalid argument error: */
- ret = EINVAL;
- } else if ((param->sched_priority < THR_MIN_PRIORITY) ||
- (param->sched_priority > THR_MAX_PRIORITY)) {
- /* Return an unsupported value error. */
- ret = ENOTSUP;
-
- /* Find the thread in the list of active threads: */
+ if (pthread == curthread) {
+ THR_LOCK(curthread);
+ if (curthread->attr.sched_policy == policy &&
+ curthread->attr.prio == param->sched_priority) {
+ THR_UNLOCK(curthread);
+ return (0);
+ }
+ if (policy == SCHED_OTHER) {
+ ret = _thr_set_sched_other_prio(curthread,
+ param->sched_priority);
+ } else {
+ ret = _thr_setscheduler(curthread->tid, policy, param);
+ }
+ if (ret == -1)
+ ret = errno;
+ else {
+ curthread->attr.sched_policy = policy;
+ curthread->attr.prio = param->sched_priority;
+ }
+ THR_UNLOCK(curthread);
} else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
- == 0) {
- /*
- * Lock the threads scheduling queue while we change
- * its priority:
- */
+ == 0) {
THR_THREAD_LOCK(curthread, pthread);
- if (pthread->state == PS_DEAD) {
+ if (pthread->attr.sched_policy == policy &&
+ pthread->attr.prio == param->sched_priority) {
THR_THREAD_UNLOCK(curthread, pthread);
- _thr_ref_delete(curthread, pthread);
- return (ESRCH);
+ return (0);
}
-
- /* Set the scheduling policy: */
- pthread->attr.sched_policy = policy;
-
- if (param->sched_priority ==
- THR_BASE_PRIORITY(pthread->base_priority))
- /*
- * There is nothing to do; unlock the threads
- * scheduling queue.
- */
- THR_THREAD_UNLOCK(curthread, pthread);
+ if (policy == SCHED_OTHER) {
+ ret = _thr_set_sched_other_prio(curthread,
+ param->sched_priority);
+ } else {
+ ret = _thr_setscheduler(curthread->tid, policy, param);
+ }
+ if (ret == -1)
+ ret = errno;
else {
- /* Set the thread base priority: */
- pthread->base_priority = param->sched_priority;
-
- /* Recalculate the active priority: */
- pthread->active_priority = MAX(pthread->base_priority,
- pthread->inherited_priority);
-
- /* Unlock the threads scheduling queue: */
- THR_THREAD_UNLOCK(curthread, pthread);
+ pthread->attr.sched_policy = policy;
+ pthread->attr.prio = param->sched_priority;
}
+ THR_THREAD_UNLOCK(curthread, pthread);
_thr_ref_delete(curthread, pthread);
}
return (ret);
[
Date Prev][Date Next]
[
Thread Prev][Thread Next]
[
Date Index][
Thread Index]