| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// Linux implementation of nice. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "src/unistd/nice.h" |
| |
| #include "hdr/errno_macros.h" |
| #include "hdr/limits_macros.h" |
| #include "hdr/sys_resource_macros.h" |
| #include "src/__support/OSUtil/linux/syscall_wrappers/getpriority.h" |
| #include "src/__support/OSUtil/linux/syscall_wrappers/setpriority.h" |
| #include "src/__support/common.h" |
| #include "src/__support/libc_errno.h" |
| #include "src/__support/macros/config.h" |
| #include "src/__support/math_extras.h" |
| |
| namespace LIBC_NAMESPACE_DECL { |
| |
| LLVM_LIBC_FUNCTION(int, nice, (int incr)) { |
| // POSIX specifies default nice value as NZERO (20 in <limits.h>). |
| // Priority range in Linux is [-NZERO, NZERO - 1]. |
| constexpr int MIN_PRIO = -NZERO; |
| constexpr int MAX_PRIO = NZERO - 1; |
| |
| // Query current nice value. Linux raw SYS_getpriority returns (20 - nice), |
| // so current priority is (NZERO - prio_result.value()). |
| auto prio_result = linux_syscalls::getpriority(PRIO_PROCESS, 0); |
| if (!prio_result) { |
| libc_errno = prio_result.error(); |
| return -1; |
| } |
| int current_prio = NZERO - prio_result.value(); |
| |
| int target_prio = 0; |
| if (add_overflow(current_prio, incr, target_prio)) |
| target_prio = (incr > 0) ? MAX_PRIO : MIN_PRIO; |
| else if (target_prio > MAX_PRIO) |
| target_prio = MAX_PRIO; |
| else if (target_prio < MIN_PRIO) |
| target_prio = MIN_PRIO; |
| |
| auto set_result = linux_syscalls::setpriority(PRIO_PROCESS, 0, target_prio); |
| if (!set_result) { |
| int err = set_result.error(); |
| // POSIX mandates [EPERM] when lowering nice value without privileges. |
| // Linux setpriority returns EACCES; remap to EPERM for POSIX compliance. |
| if (err == EACCES) |
| err = EPERM; |
| libc_errno = err; |
| return -1; |
| } |
| |
| // Returns new nice value - NZERO (in [-NZERO, NZERO - 1]). |
| // Note: libc_errno is left unmodified on success to allow -1 disambiguation. |
| return target_prio; |
| } |
| |
| } // namespace LIBC_NAMESPACE_DECL |