Skip to main content

yash_env/system/
resource.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2024 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Resource types and limits
18//!
19//! This module defines resource types, their limit values, and traits for
20//! getting and setting resource limits.
21
22use super::Result;
23use std::rc::Rc;
24
25#[cfg(unix)]
26type RawLimit = libc::rlim_t;
27#[cfg(not(unix))]
28type RawLimit = u64;
29
30/// Unsigned integer type for resource limits
31///
32/// The size of this type may vary depending on the platform.
33pub type Limit = RawLimit;
34
35#[cfg(unix)]
36const RLIM_INFINITY: Limit = libc::RLIM_INFINITY;
37#[cfg(not(unix))]
38const RLIM_INFINITY: Limit = Limit::MAX;
39
40/// Constant to specify an unlimited resource limit
41///
42/// The value of this constant is platform-specific.
43pub const INFINITY: Limit = RLIM_INFINITY;
44
45// No platforms are known to define `RLIM_SAVED_CUR` and `RLIM_SAVED_MAX` that
46// have different values from `RLIM_INFINITY`, so they are not defined here.
47
48// When adding a new resource type, also update the yash_builtin::ulimit::resource module.
49
50/// Resource type definition
51///
52/// A `Resource` value represents a resource whose limit can be retrieved or
53/// set using [`GetRlimit`] and [`SetRlimit`].
54///
55/// This enum contains all possible resource types that may or may not be
56/// available depending on the platform.
57#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
58#[non_exhaustive]
59pub enum Resource {
60    /// Maximum total memory size of the process
61    AS,
62    /// Maximum size of a core file created by a terminated process
63    CORE,
64    /// Maximum amount of CPU time the process can consume
65    CPU,
66    /// Maximum size of a data segment of the process
67    DATA,
68    /// Maximum size of a file the process can create
69    FSIZE,
70    /// Maximum number of kernel event queues (kqueues)
71    KQUEUES,
72    /// Maximum number of file locks the process can hold
73    LOCKS,
74    /// Maximum size of memory locked into RAM
75    MEMLOCK,
76    /// Maximum total size of POSIX message queues
77    MSGQUEUE,
78    /// Maximum process priority
79    ///
80    /// This resource specifies the highest priority that a process can set using
81    /// `setpriority` or `nice`. When the resource value is set to *n*, the process
82    /// can lower its nice value (that is, raise the priority) to (20 - *n*).
83    NICE,
84    /// Maximum number of open files in the process
85    NOFILE,
86    /// Maximum number of processes the user can run
87    NPROC,
88    /// Maximum physical memory size of the process
89    RSS,
90    /// Maximum real-time priority
91    RTPRIO,
92    /// Maximum amount of CPU time the process can consume in real-time
93    /// scheduling mode without a blocking system call (microseconds)
94    RTTIME,
95    /// Maximum size of the socket buffer
96    SBSIZE,
97    /// Maximum number of signals that can be queued to the process
98    SIGPENDING,
99    /// Maximum size of the process stack
100    STACK,
101    /// Maximum size of the swap space that can be used by the user
102    SWAP,
103}
104
105impl Resource {
106    /// Slice of all resource types (including those not available on the current platform)
107    pub const ALL: &'static [Resource] = &[
108        Self::AS,
109        Self::CORE,
110        Self::CPU,
111        Self::DATA,
112        Self::FSIZE,
113        Self::KQUEUES,
114        Self::LOCKS,
115        Self::MEMLOCK,
116        Self::MSGQUEUE,
117        Self::NICE,
118        Self::NOFILE,
119        Self::NPROC,
120        Self::RSS,
121        Self::RTPRIO,
122        Self::RTTIME,
123        Self::SBSIZE,
124        Self::SIGPENDING,
125        Self::STACK,
126        Self::SWAP,
127    ];
128}
129
130/// Pair of soft and hard limits
131#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
132pub struct LimitPair {
133    pub soft: Limit,
134    pub hard: Limit,
135}
136
137impl LimitPair {
138    /// Returns `true` if the soft limit exceeds the hard limit
139    #[must_use]
140    pub fn soft_exceeds_hard(&self) -> bool {
141        self.hard != INFINITY && (self.soft == INFINITY || self.soft > self.hard)
142    }
143}
144
145pub trait GetRlimit {
146    /// Returns the limits for the specified resource.
147    ///
148    /// This function returns a pair of the soft and hard limits for the given
149    /// resource. The soft limit is the current limit, and the hard limit is the
150    /// maximum value that the soft limit can be set to.
151    ///
152    /// When no limit is set, the limit value is [`INFINITY`].
153    ///
154    /// This is a thin wrapper around the `getrlimit` system call.
155    fn getrlimit(&self, resource: Resource) -> Result<LimitPair>;
156}
157
158impl<S: GetRlimit> GetRlimit for Rc<S> {
159    #[inline]
160    fn getrlimit(&self, resource: Resource) -> Result<LimitPair> {
161        (self as &S).getrlimit(resource)
162    }
163}
164
165pub trait SetRlimit {
166    /// Sets the limits for the specified resource.
167    ///
168    /// Specify [`INFINITY`] as the limit value to remove the limit.
169    ///
170    /// This is a thin wrapper around the `setrlimit` system call.
171    fn setrlimit(&self, resource: Resource, limits: LimitPair) -> Result<()>;
172}
173
174impl<S: SetRlimit> SetRlimit for Rc<S> {
175    #[inline]
176    fn setrlimit(&self, resource: Resource, limits: LimitPair) -> Result<()> {
177        (self as &S).setrlimit(resource, limits)
178    }
179}