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.
This commit is contained in:
parent
e9b885ee55
commit
1e21e78bf7
23 changed files with 159 additions and 13 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue