summaryrefslogtreecommitdiff
path: root/src/thread
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/thread
parente9b885ee550e8a3eabc9d11c469baf1cfaf64f55 (diff)
downloadmusl-1e21e78bf7a5.tar.gz
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/thread')
-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
12 files changed, 106 insertions, 4 deletions
diff --git a/src/thread/pthread_attr_getinheritsched.c b/src/thread/pthread_attr_getinheritsched.c
new file mode 100644
index 00000000..392a5df8
--- /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 5806bdf1..de5fbfe2 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 00000000..09e893a3
--- /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 c0167b6a..b8dfd123 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 00000000..c91d8f83
--- /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 77ce9c98..d4c1204f 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 00000000..bb71f393
--- /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 d56ee391..46b520c0 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 a7aadb51..a65e88e1 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 00000000..7b6a95f1
--- /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 00000000..8e8b5a19
--- /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 00000000..e0bdc03b
--- /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;
+}