summaryrefslogtreecommitdiff
path: root/src/thread
diff options
context:
space:
mode:
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;
+}