aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-11-11 15:38:04 -0500
committerRich Felker <dalias@aerifal.cx>2012-11-11 15:38:04 -0500
commit1e21e78bf7a5c24c217446d8760be7b7188711c2 (patch)
tree83920f2f5aad8bc090ddb55e57f74e062743e592 /src
parente9b885ee550e8a3eabc9d11c469baf1cfaf64f55 (diff)
downloadmusl-1e21e78bf7a5c24c217446d8760be7b7188711c2.zip
musl-1e21e78bf7a5c24c217446d8760be7b7188711c2.tar.gz
musl-1e21e78bf7a5c24c217446d8760be7b7188711c2.tar.bz2
add support for thread scheduling (POSIX TPS option)
linux's sched_* syscalls actually implement the TPS (thread scheduling) functionality, not the PS (process scheduling) functionality which the sched_* functions are supposed to have. omitting support for the PS option (and having the sched_* interfaces fail with ENOSYS rather than omitting them, since some broken software assumes they exist) seems to be the only conforming way to do this on linux.
Diffstat (limited to 'src')
-rw-r--r--src/internal/pthread_impl.h5
-rw-r--r--src/process/posix_spawnattr_sched.c25
-rw-r--r--src/sched/sched_get_priority_max.c5
-rw-r--r--src/sched/sched_getparam.c3
-rw-r--r--src/sched/sched_getscheduler.c3
-rw-r--r--src/sched/sched_rr_get_interval.c1
-rw-r--r--src/sched/sched_setparam.c4
-rw-r--r--src/sched/sched_setscheduler.c4
-rw-r--r--src/thread/pthread_attr_getinheritsched.c7
-rw-r--r--src/thread/pthread_attr_getschedparam.c2
-rw-r--r--src/thread/pthread_attr_getschedpolicy.c7
-rw-r--r--src/thread/pthread_attr_getscope.c1
-rw-r--r--src/thread/pthread_attr_setinheritsched.c8
-rw-r--r--src/thread/pthread_attr_setschedparam.c2
-rw-r--r--src/thread/pthread_attr_setschedpolicy.c7
-rw-r--r--src/thread/pthread_attr_setscope.c10
-rw-r--r--src/thread/pthread_create.c29
-rw-r--r--src/thread/pthread_getschedparam.c17
-rw-r--r--src/thread/pthread_setschedparam.c10
-rw-r--r--src/thread/pthread_setschedprio.c10
20 files changed, 147 insertions, 13 deletions
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 9424a5b..4215e67 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -40,6 +40,8 @@ struct pthread {
locale_t locale;
int killlock[2];
int exitlock[2];
+ int startlock[2];
+ unsigned long sigmask[__SYSCALL_SSLEN/sizeof(long)];
};
struct __timer {
@@ -53,6 +55,9 @@ struct __timer {
#define _a_guardsize __u.__s[1]
#define _a_stackaddr __u.__s[2]
#define _a_detach __u.__i[3*__SU+0]
+#define _a_sched __u.__i[3*__SU+1]
+#define _a_policy __u.__i[3*__SU+2]
+#define _a_prio __u.__i[3*__SU+3]
#define _m_type __u.__i[0]
#define _m_lock __u.__i[1]
#define _m_waiters __u.__i[2]
diff --git a/src/process/posix_spawnattr_sched.c b/src/process/posix_spawnattr_sched.c
new file mode 100644
index 0000000..e2ba0d1
--- /dev/null
+++ b/src/process/posix_spawnattr_sched.c
@@ -0,0 +1,25 @@
+#include <spawn.h>
+#include <sched.h>
+#include <errno.h>
+
+int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict attr,
+ struct sched_param *restrict schedparam)
+{
+ return ENOSYS;
+}
+
+int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict attr,
+ const struct sched_param *restrict schedparam)
+{
+ return ENOSYS;
+}
+
+int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict attr, int *policy)
+{
+ return ENOSYS;
+}
+
+int posix_spawnattr_setschedpolicy(posix_spawnattr_t *restrict attr, int policy)
+{
+ return ENOSYS;
+}
diff --git a/src/sched/sched_get_priority_max.c b/src/sched/sched_get_priority_max.c
index 64cbca9..30ae510 100644
--- a/src/sched/sched_get_priority_max.c
+++ b/src/sched/sched_get_priority_max.c
@@ -1,11 +1,12 @@
#include <sched.h>
+#include "syscall.h"
int sched_get_priority_max(int policy)
{
- return 0;
+ return syscall(SYS_sched_get_priority_max, policy);
}
int sched_get_priority_min(int policy)
{
- return 0;
+ return syscall(SYS_sched_get_priority_min, policy);
}
diff --git a/src/sched/sched_getparam.c b/src/sched/sched_getparam.c
index 65be107..76f10e4 100644
--- a/src/sched/sched_getparam.c
+++ b/src/sched/sched_getparam.c
@@ -1,7 +1,8 @@
#include <sched.h>
+#include <errno.h>
#include "syscall.h"
int sched_getparam(pid_t pid, struct sched_param *param)
{
- return syscall(SYS_sched_getparam, pid, param);
+ return __syscall_ret(-ENOSYS);
}
diff --git a/src/sched/sched_getscheduler.c b/src/sched/sched_getscheduler.c
index 4c922f6..394e508 100644
--- a/src/sched/sched_getscheduler.c
+++ b/src/sched/sched_getscheduler.c
@@ -1,7 +1,8 @@
#include <sched.h>
+#include <errno.h>
#include "syscall.h"
int sched_getscheduler(pid_t pid)
{
- return syscall(SYS_sched_getscheduler, pid);
+ return __syscall_ret(-ENOSYS);
}
diff --git a/src/sched/sched_rr_get_interval.c b/src/sched/sched_rr_get_interval.c
index 43bc490..4b01028 100644
--- a/src/sched/sched_rr_get_interval.c
+++ b/src/sched/sched_rr_get_interval.c
@@ -5,4 +5,3 @@ int sched_rr_get_interval(pid_t pid, struct timespec *ts)
{
return syscall(SYS_sched_rr_get_interval, pid, ts);
}
-
diff --git a/src/sched/sched_setparam.c b/src/sched/sched_setparam.c
index 07d61ae..18623ee 100644
--- a/src/sched/sched_setparam.c
+++ b/src/sched/sched_setparam.c
@@ -1,8 +1,8 @@
#include <sched.h>
+#include <errno.h>
#include "syscall.h"
int sched_setparam(pid_t pid, const struct sched_param *param)
{
- static const struct sched_param def;
- return syscall(SYS_sched_setparam, pid, &def);
+ return __syscall_ret(-ENOSYS);
}
diff --git a/src/sched/sched_setscheduler.c b/src/sched/sched_setscheduler.c
index 1958066..4435f21 100644
--- a/src/sched/sched_setscheduler.c
+++ b/src/sched/sched_setscheduler.c
@@ -1,8 +1,8 @@
#include <sched.h>
+#include <errno.h>
#include "syscall.h"
int sched_setscheduler(pid_t pid, int sched, const struct sched_param *param)
{
- static const struct sched_param def;
- return syscall(SYS_sched_setscheduler, pid, 0, &def);
+ return __syscall_ret(-ENOSYS);
}
diff --git a/src/thread/pthread_attr_getinheritsched.c b/src/thread/pthread_attr_getinheritsched.c
new file mode 100644
index 0000000..392a5df
--- /dev/null
+++ b/src/thread/pthread_attr_getinheritsched.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getinheritsched(const pthread_attr_t *a, int *inherit)
+{
+ *inherit = a->_a_sched;
+ return 0;
+}
diff --git a/src/thread/pthread_attr_getschedparam.c b/src/thread/pthread_attr_getschedparam.c
index 5806bdf..de5fbfe 100644
--- a/src/thread/pthread_attr_getschedparam.c
+++ b/src/thread/pthread_attr_getschedparam.c
@@ -2,6 +2,6 @@
int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param)
{
- param->sched_priority = 0;
+ param->sched_priority = a->_a_prio;
return 0;
}
diff --git a/src/thread/pthread_attr_getschedpolicy.c b/src/thread/pthread_attr_getschedpolicy.c
new file mode 100644
index 0000000..09e893a
--- /dev/null
+++ b/src/thread/pthread_attr_getschedpolicy.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_getschedpolicy(const pthread_attr_t *a, int *policy)
+{
+ *policy = a->_a_policy;
+ return 0;
+}
diff --git a/src/thread/pthread_attr_getscope.c b/src/thread/pthread_attr_getscope.c
index c0167b6..b8dfd12 100644
--- a/src/thread/pthread_attr_getscope.c
+++ b/src/thread/pthread_attr_getscope.c
@@ -2,5 +2,6 @@
int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope)
{
+ *scope = PTHREAD_SCOPE_SYSTEM;
return 0;
}
diff --git a/src/thread/pthread_attr_setinheritsched.c b/src/thread/pthread_attr_setinheritsched.c
new file mode 100644
index 0000000..c91d8f8
--- /dev/null
+++ b/src/thread/pthread_attr_setinheritsched.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setinheritsched(pthread_attr_t *a, int inherit)
+{
+ if (inherit > 1U) return EINVAL;
+ a->_a_sched = inherit;
+ return 0;
+}
diff --git a/src/thread/pthread_attr_setschedparam.c b/src/thread/pthread_attr_setschedparam.c
index 77ce9c9..d4c1204 100644
--- a/src/thread/pthread_attr_setschedparam.c
+++ b/src/thread/pthread_attr_setschedparam.c
@@ -2,6 +2,6 @@
int pthread_attr_setschedparam(pthread_attr_t *restrict a, const struct sched_param *restrict param)
{
- if (param->sched_priority) return ENOTSUP;
+ a->_a_prio = param->sched_priority;
return 0;
}
diff --git a/src/thread/pthread_attr_setschedpolicy.c b/src/thread/pthread_attr_setschedpolicy.c
new file mode 100644
index 0000000..bb71f39
--- /dev/null
+++ b/src/thread/pthread_attr_setschedpolicy.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setschedpolicy(pthread_attr_t *a, int policy)
+{
+ a->_a_policy = policy;
+ return 0;
+}
diff --git a/src/thread/pthread_attr_setscope.c b/src/thread/pthread_attr_setscope.c
index d56ee39..46b520c 100644
--- a/src/thread/pthread_attr_setscope.c
+++ b/src/thread/pthread_attr_setscope.c
@@ -2,6 +2,12 @@
int pthread_attr_setscope(pthread_attr_t *a, int scope)
{
- if (scope > 1U) return EINVAL;
- return 0;
+ switch (scope) {
+ case PTHREAD_SCOPE_SYSTEM:
+ return 0;
+ case PTHREAD_SCOPE_PROCESS:
+ return ENOTSUP;
+ default:
+ return EINVAL;
+ }
}
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index a7aadb5..a65e88e 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -62,6 +62,15 @@ void __do_cleanup_pop(struct __ptcb *cb)
static int start(void *p)
{
pthread_t self = p;
+ if (self->startlock[0]) {
+ __wait(self->startlock, 0, 1, 1);
+ if (self->startlock[0]) {
+ self->detached = 2;
+ pthread_exit(0);
+ }
+ __syscall(SYS_rt_sigprocmask, SIG_SETMASK,
+ self->sigmask, 0, __SYSCALL_SSLEN);
+ }
if (self->unblock_cancel)
__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
SIGPT_SET, 0, __SYSCALL_SSLEN);
@@ -95,6 +104,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr,
struct pthread *self = pthread_self(), *new;
unsigned char *map, *stack, *tsd;
unsigned flags = 0x7d8f00;
+ int do_sched = 0;
if (!self) return ENOSYS;
if (!libc.threaded) {
@@ -144,6 +154,11 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr,
new->detached = 1;
flags -= 0x200000;
}
+ if (attr && attr->_a_sched) {
+ do_sched = new->startlock[0] = 1;
+ __syscall(SYS_rt_sigprocmask, SIG_BLOCK,
+ SIGALL_SET, self->sigmask, __SYSCALL_SSLEN);
+ }
new->unblock_cancel = self->cancel;
new->canary = self->canary;
@@ -152,11 +167,25 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attr,
__release_ptc();
+ if (do_sched) {
+ __syscall(SYS_rt_sigprocmask, SIG_SETMASK,
+ new->sigmask, 0, __SYSCALL_SSLEN);
+ }
+
if (ret < 0) {
a_dec(&libc.threads_minus_1);
munmap(map, size);
return EAGAIN;
}
+
+ if (do_sched) {
+ ret = __syscall(SYS_sched_setscheduler, new->tid,
+ attr->_a_policy, &attr->_a_prio);
+ a_store(new->startlock, ret<0 ? 2 : 0);
+ __wake(new->startlock, 1, 1);
+ if (ret < 0) return -ret;
+ }
+
*res = new;
return 0;
}
diff --git a/src/thread/pthread_getschedparam.c b/src/thread/pthread_getschedparam.c
new file mode 100644
index 0000000..7b6a95f
--- /dev/null
+++ b/src/thread/pthread_getschedparam.c
@@ -0,0 +1,17 @@
+#include "pthread_impl.h"
+
+int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param)
+{
+ int r;
+ __lock(t->killlock);
+ if (t->dead) {
+ r = ESRCH;
+ } else {
+ r = -__syscall(SYS_sched_getparam, t->tid, &param);
+ if (!r) {
+ *policy = __syscall(SYS_sched_getscheduler, t->tid);
+ }
+ }
+ __unlock(t->killlock);
+ return r;
+}
diff --git a/src/thread/pthread_setschedparam.c b/src/thread/pthread_setschedparam.c
new file mode 100644
index 0000000..8e8b5a1
--- /dev/null
+++ b/src/thread/pthread_setschedparam.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *param)
+{
+ int r;
+ __lock(t->killlock);
+ r = t->dead ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, &param);
+ __unlock(t->killlock);
+ return r;
+}
diff --git a/src/thread/pthread_setschedprio.c b/src/thread/pthread_setschedprio.c
new file mode 100644
index 0000000..e0bdc03
--- /dev/null
+++ b/src/thread/pthread_setschedprio.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int pthread_setschedprio(pthread_t t, int prio)
+{
+ int r;
+ __lock(t->killlock);
+ r = t->dead ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);
+ __unlock(t->killlock);
+ return r;
+}