diff options
author | rpj <rpj> | 2001-07-01 13:23:10 +0000 |
---|---|---|
committer | rpj <rpj> | 2001-07-01 13:23:10 +0000 |
commit | a311086d622d3c778e1da57cfae167c0ab1c0fb4 (patch) | |
tree | 760a76a351c18331ff92239366804bd4b866dea6 /sched.c | |
parent | 528fccade9ca5f90db376e08b2cb85b3fc822a45 (diff) |
2001-06-25 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
* create.c (pthread_create): Add priority inheritance
attributes.
* mutex.c (pthread_mutex_lock): Remove some overhead for
PTHREAD_MUTEX_NORMAL mutex types. Specifically, avoid
calling pthread_self() and pthread_equal() to check/set
the mutex owner. Introduce a new pseudo owner for this
type. Test results suggest increases in speed of up to
90% for non-blocking locks.
This is the default type of mutex used internally by other
synchronising objects, ie. condition variables and
read-write locks. The test rwlock7.c shows about a
30-35% speed increase over snapshot 2001-06-06. The
price of this is that the application developer
must ensure correct behaviour, or explicitly set the
mutex to a safer type such as PTHREAD_MUTEX_ERRORCHECK.
For example, PTHREAD_MUTEX_NORMAL (or PTHREAD_MUTEX_DEFAULT)
type mutexes will not return an error if a thread which is not
the owner calls pthread_mutex_unlock. The call will succeed
in unlocking the mutex if it is currently locked, but a
subsequent unlock by the true owner will then fail with EPERM.
This is however consistent with some other implementations.
(pthread_mutex_unlock): Likewise.
(pthread_mutex_trylock): Likewise.
(pthread_mutex_destroy): Likewise.
* attr.c (pthread_attr_init): PTHREAD_EXPLICIT_SCHED is the
default inheritance attribute; THREAD_PRIORITY_NORMAL is
the default priority for new threads.
* sched.c (pthread_attr_setschedpolicy): Added routine.
(pthread_attr_getschedpolicy): Added routine.
(pthread_attr_setinheritsched): Added routine.
(pthread_attr_getinheritsched): Added routine.
* pthread.h (sched_rr_set_interval): Added as a macro;
returns -1 with errno set to ENOSYS.
2001-06-23 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
*sched.c (pthread_attr_setschedparam): Add priority range
check.
(sched_setscheduler): New function; checks for a valid
pid and policy; checks for permission to set information
in the target process; expects pid to be a Win32 process ID,
not a process handle; the only scheduler policy allowed is
SCHED_OTHER.
(sched_getscheduler): Likewise, but checks for permission
to query.
* pthread.h (SCHED_*): Moved to sched.h as defined in the
POSIX standard.
* sched.h (SCHED_*): Moved from pthread.h.
(pid_t): Defined if necessary.
(sched_setscheduler): Defined.
(sched_getscheduler): Defined.
* pthread.def (sched_setscheduler): Exported.
(sched_getscheduler): Likewise.
2001-06-23 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
Contributed by - Ralf Brese <Ralf.Brese@pdb4.siemens.de>
* create.c (pthread_create): Set thread priority from
thread attributes.
Diffstat (limited to 'sched.c')
-rw-r--r-- | sched.c | 410 |
1 files changed, 391 insertions, 19 deletions
@@ -23,8 +23,6 @@ * MA 02111-1307, USA */ -#define ENOSUP 0 - #include "pthread.h" #include "implement.h" #include "sched.h" @@ -37,19 +35,78 @@ is_attr(const pthread_attr_t *attr) (*attr)->valid != PTW32_ATTR_VALID) ? 1 : 0; } + +int +pthread_attr_setschedpolicy(pthread_attr_t *attr, + int policy) +{ + if (is_attr(attr) != 0) + { + return EINVAL; + } + + if (policy != SCHED_OTHER) + { + return ENOTSUP; + } + + return 0; +} + + +int +pthread_attr_getschedpolicy(pthread_attr_t *attr, + int * policy) +{ + if (is_attr(attr) != 0 || policy == NULL) + { + return EINVAL; + } + + /* + * Validate the policy arg. + * Check that a policy constant wasn't passed rather than &policy. + */ + if (policy <= (int *) SCHED_MAX) + { + return EINVAL; + } + + *policy = SCHED_OTHER; + + return 0; +} + + int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) { + int priority; + if (is_attr(attr) != 0 || param == NULL) { return EINVAL; } - (*attr)->priority = param->sched_priority; + priority = param->sched_priority; + + /* + * Validate priority level. Don't check the + * return values of the function calls because + * we're sure they will succeed. + */ + if (priority < sched_get_priority_min(SCHED_OTHER) || + priority > sched_get_priority_max(SCHED_OTHER)) + { + return EINVAL; + } + + memcpy(&(*attr)->param, param, sizeof(*param)); return 0; } + int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) @@ -59,11 +116,47 @@ pthread_attr_getschedparam(const pthread_attr_t *attr, return EINVAL; } - param->sched_priority = (*attr)->priority; + memcpy(param, &(*attr)->param, sizeof(*param)); return 0; } -int pthread_setschedparam(pthread_t thread, int policy, + +int +pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched) +{ + if (is_attr(attr) != 0) + { + return EINVAL; + } + + if (PTHREAD_INHERIT_SCHED != inheritsched + && PTHREAD_EXPLICIT_SCHED != inheritsched) + { + return EINVAL; + } + + (*attr)->inheritsched = inheritsched; + return 0; +} + + +int +pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched) +{ + if (is_attr(attr) != 0 || inheritsched == NULL) + { + return EINVAL; + } + + *inheritsched = (*attr)->inheritsched; + return 0; +} + + +int +pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) { /* Validate the thread id. */ @@ -81,12 +174,16 @@ int pthread_setschedparam(pthread_t thread, int policy, /* Ensure the policy is SCHED_OTHER. */ if (policy != SCHED_OTHER) { - return ENOSUP; + return ENOTSUP; } - /* Validate priority level. */ - if (param->sched_priority < sched_get_priority_min(policy) || - param->sched_priority > sched_get_priority_max(policy)) + /* + * Validate priority level. Don't check the + * return values of the function calls because + * we're sure they will succeed. + */ + if (param->sched_priority < sched_get_priority_min(SCHED_OTHER) || + param->sched_priority > sched_get_priority_max(SCHED_OTHER)) { return EINVAL; } @@ -97,7 +194,9 @@ int pthread_setschedparam(pthread_t thread, int policy, return 0; } -int pthread_getschedparam(pthread_t thread, int *policy, + +int +pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) { int prio; @@ -108,8 +207,11 @@ int pthread_getschedparam(pthread_t thread, int *policy, return EINVAL; } - /* Validate the param structure. */ - if (param == NULL) + /* + * Validate the policy and param args. + * Check that a policy constant wasn't passed rather than &policy. + */ + if (policy <= (int *) SCHED_MAX || param == NULL) { return EINVAL; } @@ -141,14 +243,24 @@ int pthread_getschedparam(pthread_t thread, int *policy, * sched_get_priority_max() returns 1 */ + #define sched_Max(a,b) ((a)<(b)?(b):(a)) #define sched_Min(a,b) ((a)>(b)?(b):(a)) -int sched_get_priority_max(int policy) + +int +sched_get_priority_max(int policy) { if (policy < SCHED_MIN || policy > SCHED_MAX) { - return EINVAL; + errno = EINVAL; + return -1; + } + + if (policy != SCHED_OTHER) + { + errno = ENOTSUP; + return -1; } #if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) @@ -160,11 +272,20 @@ int sched_get_priority_max(int policy) #endif } -int sched_get_priority_min(int policy) + +int +sched_get_priority_min(int policy) { if (policy < SCHED_MIN || policy > SCHED_MAX) { - return EINVAL; + errno = EINVAL; + return -1; + } + + if (policy != SCHED_OTHER) + { + errno = ENOTSUP; + return -1; } #if (THREAD_PRIORITY_LOWEST > THREAD_PRIORITY_NORMAL) @@ -176,7 +297,259 @@ int sched_get_priority_min(int policy) #endif } -int sched_yield(void) + +int +sched_rr_get_interval(pid_t pid, struct timespec * interval) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function updates the timespec structure + * referenced by the interval argument to contain + * the current quantum for the process executing + * under the SCHED_RR policy. If a process, running under + * the round-robin scheduling policy, runs without + * blocking or yielding for more than this amount of + * time, it may be preempted by another runnable + * process (at the same priority). + * + * If the PID argument is zero, the current execution + * time limit for the calling process is returned. + * + * PARAMETERS + * pid Process identifier. + * + * + * DESCRIPTION + * This function updates the timespec structure + * referenced by the interval argument to contain + * the current quantum for the process executing + * under the SCHED_RR policy. If a process, running under + * the round-robin scheduling policy, runs without + * blocking or yielding for more than this amount of + * time, it may be preempted by another runnable + * process (at the same priority). + * + * If the PID argument is zero, the current execution + * time limit for the calling process is returned. + * + * RESULTS + * We don't support SCHED_RR so this routine always fails. + * + * NOTE: Since this is part of POSIX 1003.1b + * (realtime extensions), it is defined as returning + * -1 if an error occurs and sets errno to the actual + * error. + * + * errno: ESRCH Pid doesn't refer to a valid process. + * EPERM The process referenced by pid does + * not allow query access. + * ENOTSUP SCHED_RR is not supported. + * + * ------------------------------------------------------ + */ +{ + /* + * Provide other valid side-effects + * such as EPERM and ESRCH errors. + */ + if (0 != pid) + { + DWORD selfPid = GetCurrentProcessId(); + + if (pid != selfPid) + { + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + + if (NULL == h) + { + errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED) + ? EPERM + : ESRCH ); + + return -1; + } + + (void) CloseHandle(h); + } + } + + /* + * We can't return ENOSYS and stay strictly compliant with the + * standard. We don't support round-robin scheduling so + * we return ENOTSUP instead. This is consistent with + * routines which return ENOTSUP if SCHED_RR is given + * as the policy parameter. + */ + errno = ENOTSUP; + return -1; +} + + +int +sched_setscheduler(pid_t pid, int policy) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns sets the scheduling policy and + * scheduling parameters of the process specified by pid + * to policy and the parameters specified in the + * sched_param structure pointed to by param, respectively. + * The value of the sched_priority member in the sched_param + * structure is any integer within the inclusive priority + * range for the scheduling policy specified by policy. + * If the value of pid is negative, the behaviour of the + * sched_setscheduler() function is unspecified. + * + * PARAMETERS + * pid Identifier of the process in which the + * policy will be set. + * policy The new policy value. + * + * + * DESCRIPTION + * This function returns sets the scheduling policy and + * scheduling parameters of the process specified by pid + * to policy and the parameters specified in the + * sched_param structure pointed to by param, respectively. + * The value of the sched_priority member in the sched_param + * structure is any integer within the inclusive priority + * range for the scheduling policy specified by policy. + * If the value of pid is negative, the behaviour of the + * sched_setscheduler() function is unspecified. + * + * RESULTS + * SCHED_OTHER on success this is the only possible + * value that can be returned. + * + * NOTE: Since this is part of POSIX 1003.1b + * (realtime extensions), it is defined as returning + * -1 if an error occurs and sets errno to the actual + * error. + * + * errno: ESRCH 'pid' doesn't refer to an existing + * process. + * EPERM The process referenced by pid does + * not allow set access. + * EINVAL 'policy' is not a valid policy value. + * ENOSYS the policy specified is not supported. + * + * ------------------------------------------------------ + */ +{ + /* + * Win32 only has one policy which we call SCHED_OTHER. + * However, we try to provide other valid side-effects + * such as EPERM and ESRCH errors. + */ + if (0 != pid) + { + DWORD selfPid = GetCurrentProcessId(); + + if (pid != selfPid) + { + HANDLE h = OpenProcess(PROCESS_SET_INFORMATION, FALSE, pid); + + if (NULL == h) + { + errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED) + ? EPERM + : ESRCH ); + + return -1; + } + + (void) CloseHandle(h); + } + } + + if (policy < SCHED_MIN || policy > SCHED_MAX) + { + errno = EINVAL; + return -1; + } + + if (SCHED_OTHER != policy) + { + errno = ENOSYS; + return -1; + } + + /* + * Don't set anything because there is nothing to set. + * Just return the current (the only possible) value. + */ + return SCHED_OTHER; +} + + +int +sched_getscheduler(pid_t pid) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * This function returns the scheduling policy of the + * process specified by pid. If the value of pid is + * negative, the behaviour of the sched_getscheduler() + * function is unspecified. + * + * PARAMETERS + * pid Process identifier. + * + * + * DESCRIPTION + * This function returns the scheduling policy of the + * process specified by pid. If the value of pid is + * negative, the behaviour of the sched_getscheduler() + * function is unspecified. + * + * RESULTS + * SCHED_OTHER on success this is the only possible + * value that can be returned. + * + * NOTE: Since this is part of POSIX 1003.1b + * (realtime extensions), it is defined as returning + * -1 if an error occurs and sets errno to the actual + * error. + * + * errno: ESRCH Pid doesn't refer to a valid process. + * EPERM The process referenced by pid does + * not allow query access. + * + * ------------------------------------------------------ + */ +{ + /* + * Win32 only has one policy which we call SCHED_OTHER. + * However, we try to provide other valid side-effects + * such as EPERM and ESRCH errors. + */ + if (0 != pid) + { + DWORD selfPid = GetCurrentProcessId(); + + if (pid != selfPid) + { + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + + if (NULL == h) + { + errno = (GetLastError() == (0xFF & ERROR_ACCESS_DENIED) + ? EPERM + : ESRCH ); + + return -1; + } + + (void) CloseHandle(h); + } + } + + return SCHED_OTHER; +} + + +int +sched_yield(void) /* * ------------------------------------------------------ * DOCPUBLIC @@ -196,8 +569,7 @@ int sched_yield(void) * error. * * RESULTS - * 0 successfully created semaphore, - * ENOSYS sched_yield not supported, + * 0 always succeeds * * ------------------------------------------------------ */ |