| author | |
| committer | |
| log | d5d48c6f4ea8a16c2fa9dc9b083c1917a3accee0 |
| tree | 7b66d0a7fedcc782fdfb56afb19d627df21ac139 |
| parent | 682a29aefde09e31247088144a7e543daefb63f4 |
| parent | 1b4296831a60983adaaaab680ebacc03833f2ae5 |
| signature |
std: implement {get, set}rlimit for linux6 files changed, 141 insertions(+), 0 deletions(-)
lib/std/c.zig+3| ... | ... | @@ -342,3 +342,6 @@ pub extern "c" fn fsync(fd: c_int) c_int; |
| 342 | 342 | pub extern "c" fn fdatasync(fd: c_int) c_int; |
| 343 | 343 | |
| 344 | 344 | pub extern "c" fn prctl(option: c_int, ...) c_int; |
| 345 | ||
| 346 | pub extern "c" fn getrlimit(resource: rlimit_resource, rlim: *rlimit) c_int; | |
| 347 | pub extern "c" fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) c_int; |
lib/std/c/linux.zig+2| ... | ... | @@ -100,6 +100,8 @@ pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_ |
| 100 | 100 | |
| 101 | 101 | pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: c_uint) c_int; |
| 102 | 102 | |
| 103 | pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int; | |
| 104 | ||
| 103 | 105 | pub const pthread_attr_t = extern struct { |
| 104 | 106 | __size: [56]u8, |
| 105 | 107 | __align: c_long, |
lib/std/os.zig+30| ... | ... | @@ -5410,3 +5410,33 @@ pub fn prctl(option: i32, args: anytype) PrctlError!u31 { |
| 5410 | 5410 | else => |err| return std.os.unexpectedErrno(err), |
| 5411 | 5411 | } |
| 5412 | 5412 | } |
| 5413 | ||
| 5414 | pub const GetrlimitError = UnexpectedError; | |
| 5415 | ||
| 5416 | pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit { | |
| 5417 | // TODO implement for systems other than linux and enable test | |
| 5418 | var limits: rlimit = undefined; | |
| 5419 | const rc = system.getrlimit(resource, &limits); | |
| 5420 | switch (errno(rc)) { | |
| 5421 | 0 => return limits, | |
| 5422 | EFAULT => unreachable, // bogus pointer | |
| 5423 | EINVAL => unreachable, | |
| 5424 | else => |err| return std.os.unexpectedErrno(err), | |
| 5425 | } | |
| 5426 | } | |
| 5427 | ||
| 5428 | pub const SetrlimitError = error{ | |
| 5429 | PermissionDenied, | |
| 5430 | } || UnexpectedError; | |
| 5431 | ||
| 5432 | pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void { | |
| 5433 | // TODO implement for systems other than linux and enable test | |
| 5434 | const rc = system.setrlimit(resource, &limits); | |
| 5435 | switch (errno(rc)) { | |
| 5436 | 0 => return, | |
| 5437 | EFAULT => unreachable, // bogus pointer | |
| 5438 | EINVAL => unreachable, | |
| 5439 | EPERM => return error.PermissionDenied, | |
| 5440 | else => |err| return std.os.unexpectedErrno(err), | |
| 5441 | } | |
| 5442 | } |
lib/std/os/bits/linux.zig+76| ... | ... | @@ -1890,3 +1890,79 @@ pub const ifreq = extern struct { |
| 1890 | 1890 | data: ?[*]u8, |
| 1891 | 1891 | }, |
| 1892 | 1892 | }; |
| 1893 | ||
| 1894 | // doc comments copied from musl | |
| 1895 | pub const rlimit_resource = extern enum(c_int) { | |
| 1896 | /// Per-process CPU limit, in seconds. | |
| 1897 | CPU, | |
| 1898 | ||
| 1899 | /// Largest file that can be created, in bytes. | |
| 1900 | FSIZE, | |
| 1901 | ||
| 1902 | /// Maximum size of data segment, in bytes. | |
| 1903 | DATA, | |
| 1904 | ||
| 1905 | /// Maximum size of stack segment, in bytes. | |
| 1906 | STACK, | |
| 1907 | ||
| 1908 | /// Largest core file that can be created, in bytes. | |
| 1909 | CORE, | |
| 1910 | ||
| 1911 | /// Largest resident set size, in bytes. | |
| 1912 | /// This affects swapping; processes that are exceeding their | |
| 1913 | /// resident set size will be more likely to have physical memory | |
| 1914 | /// taken from them. | |
| 1915 | RSS, | |
| 1916 | ||
| 1917 | /// Number of processes. | |
| 1918 | NPROC, | |
| 1919 | ||
| 1920 | /// Number of open files. | |
| 1921 | NOFILE, | |
| 1922 | ||
| 1923 | /// Locked-in-memory address space. | |
| 1924 | MEMLOCK, | |
| 1925 | ||
| 1926 | /// Address space limit. | |
| 1927 | AS, | |
| 1928 | ||
| 1929 | /// Maximum number of file locks. | |
| 1930 | LOCKS, | |
| 1931 | ||
| 1932 | /// Maximum number of pending signals. | |
| 1933 | SIGPENDING, | |
| 1934 | ||
| 1935 | /// Maximum bytes in POSIX message queues. | |
| 1936 | MSGQUEUE, | |
| 1937 | ||
| 1938 | /// Maximum nice priority allowed to raise to. | |
| 1939 | /// Nice levels 19 .. -20 correspond to 0 .. 39 | |
| 1940 | /// values of this resource limit. | |
| 1941 | NICE, | |
| 1942 | ||
| 1943 | /// Maximum realtime priority allowed for non-priviledged | |
| 1944 | /// processes. | |
| 1945 | RTPRIO, | |
| 1946 | ||
| 1947 | /// Maximum CPU time in µs that a process scheduled under a real-time | |
| 1948 | /// scheduling policy may consume without making a blocking system | |
| 1949 | /// call before being forcibly descheduled. | |
| 1950 | RTTIME, | |
| 1951 | ||
| 1952 | _, | |
| 1953 | }; | |
| 1954 | ||
| 1955 | pub const rlim_t = u64; | |
| 1956 | ||
| 1957 | /// No limit | |
| 1958 | pub const RLIM_INFINITY = ~@as(rlim_t, 0); | |
| 1959 | ||
| 1960 | pub const RLIM_SAVED_MAX = RLIM_INFINITY; | |
| 1961 | pub const RLIM_SAVED_CUR = RLIM_INFINITY; | |
| 1962 | ||
| 1963 | pub const rlimit = extern struct { | |
| 1964 | /// Soft limit | |
| 1965 | cur: rlim_t, | |
| 1966 | /// Hard limit | |
| 1967 | max: rlim_t, | |
| 1968 | }; |
lib/std/os/linux.zig+20| ... | ... | @@ -1263,6 +1263,26 @@ pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) us |
| 1263 | 1263 | return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5); |
| 1264 | 1264 | } |
| 1265 | 1265 | |
| 1266 | pub fn getrlimit(resource: rlimit_resource, rlim: *rlimit) usize { | |
| 1267 | // use prlimit64 to have 64 bit limits on 32 bit platforms | |
| 1268 | return prlimit(0, resource, null, rlim); | |
| 1269 | } | |
| 1270 | ||
| 1271 | pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize { | |
| 1272 | // use prlimit64 to have 64 bit limits on 32 bit platforms | |
| 1273 | return prlimit(0, resource, rlim, null); | |
| 1274 | } | |
| 1275 | ||
| 1276 | pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize { | |
| 1277 | return syscall4( | |
| 1278 | .prlimit64, | |
| 1279 | @bitCast(usize, @as(isize, pid)), | |
| 1280 | @bitCast(usize, @as(isize, @enumToInt(resource))), | |
| 1281 | @ptrToInt(new_limit), | |
| 1282 | @ptrToInt(old_limit) | |
| 1283 | ); | |
| 1284 | } | |
| 1285 | ||
| 1266 | 1286 | test "" { |
| 1267 | 1287 | if (builtin.os.tag == .linux) { |
| 1268 | 1288 | _ = @import("linux/test.zig"); |
lib/std/os/test.zig+10| ... | ... | @@ -591,3 +591,13 @@ test "fsync" { |
| 591 | 591 | try os.fsync(file.handle); |
| 592 | 592 | try os.fdatasync(file.handle); |
| 593 | 593 | } |
| 594 | ||
| 595 | test "getrlimit and setrlimit" { | |
| 596 | // TODO enable for other systems when implemented | |
| 597 | if(builtin.os.tag != .linux){ | |
| 598 | return error.SkipZigTest; | |
| 599 | } | |
| 600 | ||
| 601 | const cpuLimit = try os.getrlimit(.CPU); | |
| 602 | try os.setrlimit(.CPU, cpuLimit); | |
| 603 | } |