提交 1e21e78b 编写于 作者: R Rich Felker

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.
上级 e9b885ee
......@@ -91,6 +91,10 @@ int pthread_setcanceltype(int, int *);
void pthread_testcancel(void);
int pthread_cancel(pthread_t);
int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict);
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
int pthread_setschedprio(pthread_t, int);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_mutex_init(pthread_mutex_t *__restrict, const pthread_mutexattr_t *__restrict);
......
......@@ -32,6 +32,9 @@ int sched_yield(void);
#define SCHED_OTHER 0
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
#define SCHED_IDLE 5
#define SCHED_RESET_ON_FORK 0x40000000
#ifdef _GNU_SOURCE
#define CSIGNAL 0x000000ff
......
......@@ -55,6 +55,11 @@ int posix_spawnattr_getsigmask(const posix_spawnattr_t *__restrict, sigset_t *__
int posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict, const sigset_t *__restrict);
int posix_spawnattr_getsigdefault(const posix_spawnattr_t *__restrict, sigset_t *__restrict);
int posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict, const struct sched_param *__restrict);
int posix_spawnattr_getschedparam(const posix_spawnattr_t *__restrict, struct sched_param *__restrict);
int posix_spawnattr_setschedpolicy(posix_spawnattr_t *__restrict, int);
int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *__restrict, int *);
int posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
......
......@@ -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]
......
#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;
}
#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);
}
#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);
}
#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);
}
......@@ -5,4 +5,3 @@ int sched_rr_get_interval(pid_t pid, struct timespec *ts)
{
return syscall(SYS_sched_rr_get_interval, pid, ts);
}
#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);
}
#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);
}
#include "pthread_impl.h"
int pthread_attr_getinheritsched(const pthread_attr_t *a, int *inherit)
{
*inherit = a->_a_sched;
return 0;
}
......@@ -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;
}
#include "pthread_impl.h"
int pthread_attr_getschedpolicy(const pthread_attr_t *a, int *policy)
{
*policy = a->_a_policy;
return 0;
}
......@@ -2,5 +2,6 @@
int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope)
{
*scope = PTHREAD_SCOPE_SYSTEM;
return 0;
}
#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;
}
......@@ -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;
}
#include "pthread_impl.h"
int pthread_attr_setschedpolicy(pthread_attr_t *a, int policy)
{
a->_a_policy = policy;
return 0;
}
......@@ -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;
}
}
......@@ -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;
}
#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;
}
#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;
}
#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;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册