summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2005-02-14 04:40:39 +0000
committerManuel Novoa III <mjn3@codepoet.org>2005-02-14 04:40:39 +0000
commit67256bd81271093c911a516aa00a5b33a63d6cbd (patch)
tree66977d3a91596e402c00b3e475b43470064e90cf
parent8b7d5c86ca6e6679ae8ad7bc16e97b3b204f217d (diff)
Fix some issues with nice(). SUSv3 specifies that it return the new
priority if successful, while the linux syscall returns 0. Also, in the non-syscall version, we must be sure to set errno to EPERM on failure since setpriority() can set errno to several possible values. Note: The version of glibc on my debian system is broken wrt EPERM too.
-rw-r--r--libc/sysdeps/linux/common/nice.c68
1 files changed, 52 insertions, 16 deletions
diff --git a/libc/sysdeps/linux/common/nice.c b/libc/sysdeps/linux/common/nice.c
index 27b0a7590..b21f63e08 100644
--- a/libc/sysdeps/linux/common/nice.c
+++ b/libc/sysdeps/linux/common/nice.c
@@ -3,35 +3,71 @@
* nice() for uClibc
*
* Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 2005 by Manuel Novoa III <mjn3@codepoet.org>
*
* GNU Library General Public License (LGPL) version 2 or later.
*/
#include "syscalls.h"
#include <unistd.h>
+#include <sys/resource.h>
+
#ifdef __NR_nice
-_syscall1(int, nice, int, inc);
+
+#define __NR___syscall_nice __NR_nice
+static inline _syscall1(int, __syscall_nice, int, incr);
+
#else
-#include <sys/resource.h>
-int nice(int incr)
+
+#include <limits.h>
+
+static inline int int_add_no_wrap(int a, int b)
{
- int save, prio, result;
+ int s = a + b;
- save = errno;
+ if (b < 0) {
+ if (s > a) s = INT_MIN;
+ } else {
+ if (s < a) s = INT_MAX;
+ }
+
+ return s;
+}
+
+static inline int __syscall_nice(int incr)
+{
+ int old_priority;
+#if 1
+ /* This should never fail. */
+ old_priority = getpriority(PRIO_PROCESS, 0);
+#else
+ /* But if you want to be paranoid... */
+ int old_errno;
+
+ old_errno = errno;
__set_errno(0);
- prio = getpriority(PRIO_PROCESS, 0);
- if (prio == -1) {
- if (errno != 0) {
- return -1;
- } else {
- __set_errno(save);
- }
+ old_priority = getpriority(PRIO_PROCESS, 0);
+ if ((old_priority == -1) && errno) {
+ return -1;
}
- result = setpriority(PRIO_PROCESS, 0, prio + incr);
- if (result != -1) {
- return prio + incr;
- } else {
+ __set_errno(old_errno);
+#endif
+
+ if (setpriority(PRIO_PROCESS, 0, int_add_no_wrap(old_priority, incr))) {
+ __set_errno(EPERM); /* SUSv3 mandates EPERM for nice failure. */
return -1;
}
+
+ return 0;
}
+
#endif
+
+int nice(int incr)
+{
+ if (__syscall_nice(incr)) {
+ return -1;
+ }
+
+ return getpriority(PRIO_PROCESS, 0);
+}