mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 23:08:31 +00:00
Make important improvements
- Fix preadv() and pwritev() for old distros - Introduce _npassert() and _unassert() macros - Prove that file locks work properly on Windows - Support fcntl(F_DUPFD_CLOEXEC) on more systems
This commit is contained in:
parent
1ad2f530f9
commit
3f49889841
130 changed files with 1225 additions and 431 deletions
|
@ -26,35 +26,36 @@
|
|||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_chdir_nt(const char *path) {
|
||||
textwindows int sys_chdir_nt_impl(char16_t path[hasatleast PATH_MAX],
|
||||
uint32_t len) {
|
||||
uint32_t n;
|
||||
int e, ms, err, len;
|
||||
char16_t path16[PATH_MAX], var[4];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (!len) return enoent();
|
||||
if (len && path16[len - 1] != u'\\') {
|
||||
int e, ms, err;
|
||||
char16_t var[4];
|
||||
|
||||
if (len && path[len - 1] != u'\\') {
|
||||
if (len + 2 > PATH_MAX) return enametoolong();
|
||||
path16[len + 0] = u'\\';
|
||||
path16[len + 1] = u'\0';
|
||||
path[len + 0] = u'\\';
|
||||
path[len + 1] = u'\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* chdir() seems flaky on windows 7
|
||||
* in a similar way to rmdir() sigh
|
||||
*/
|
||||
for (err = errno, ms = 1;; ms *= 2) {
|
||||
if (SetCurrentDirectory(path16)) {
|
||||
if (SetCurrentDirectory(path)) {
|
||||
/*
|
||||
* Now we need to set a magic environment variable.
|
||||
*/
|
||||
if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) {
|
||||
if (n < ARRAYLEN(path16)) {
|
||||
if (!((path16[0] == '/' && path16[1] == '/') ||
|
||||
(path16[0] == '\\' && path16[1] == '\\'))) {
|
||||
if ((n = GetCurrentDirectory(PATH_MAX, path))) {
|
||||
if (n < PATH_MAX) {
|
||||
if (!((path[0] == '/' && path[1] == '/') ||
|
||||
(path[0] == '\\' && path[1] == '\\'))) {
|
||||
var[0] = '=';
|
||||
var[1] = path16[0];
|
||||
var[1] = path[0];
|
||||
var[2] = ':';
|
||||
var[3] = 0;
|
||||
if (!SetEnvironmentVariable(var, path16)) {
|
||||
if (!SetEnvironmentVariable(var, path)) {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
|
@ -77,5 +78,13 @@ textwindows int sys_chdir_nt(const char *path) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return __fix_enotdir(-1, path16);
|
||||
return __fix_enotdir(-1, path);
|
||||
}
|
||||
|
||||
textwindows int sys_chdir_nt(const char *path) {
|
||||
int len;
|
||||
char16_t path16[PATH_MAX];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (!len) return enoent();
|
||||
return sys_chdir_nt_impl(path16, len);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
|
@ -32,10 +33,9 @@
|
|||
*/
|
||||
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
||||
int64_t rc, proc, handle;
|
||||
|
||||
// validate the api usage
|
||||
if (oldfd < 0) return ebadf();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
_unassert(oldfd >= 0);
|
||||
_unassert(newfd >= -1);
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
__fds_lock();
|
||||
|
||||
|
|
|
@ -16,41 +16,52 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define F_DUP2FD 10
|
||||
#define F_DUP2FD_CLOEXEC 18
|
||||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
static bool once;
|
||||
static bool demodernize;
|
||||
int olderr, how, fd;
|
||||
if (!once) {
|
||||
olderr = errno;
|
||||
fd = __sys_dup3(oldfd, newfd, flags);
|
||||
if (fd == -1 && errno == ENOSYS) {
|
||||
STRACE("demodernizing %s() due to %s", "dup3", "RHEL5:CVE-2010-3301");
|
||||
demodernize = true;
|
||||
once = true;
|
||||
errno = olderr;
|
||||
} else {
|
||||
once = true;
|
||||
return fd;
|
||||
}
|
||||
} else if (!demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
static struct Dup3 {
|
||||
pthread_once_t once;
|
||||
bool demodernize;
|
||||
} g_dup3;
|
||||
|
||||
static void sys_dup3_test(void) {
|
||||
int e = errno;
|
||||
__sys_dup3(-1, -1, 0);
|
||||
if ((g_dup3.demodernize = errno == ENOSYS)) {
|
||||
STRACE("demodernizing %s() due to %s", "dup3", "ENOSYS");
|
||||
}
|
||||
if (oldfd == newfd) return einval();
|
||||
if (flags & ~O_CLOEXEC) return einval();
|
||||
errno = e;
|
||||
}
|
||||
|
||||
int32_t sys_dup3(int32_t oldfd, int32_t newfd, int flags) {
|
||||
int how;
|
||||
_unassert(oldfd >= 0);
|
||||
_unassert(newfd >= 0);
|
||||
_unassert(!(flags & ~O_CLOEXEC));
|
||||
|
||||
if (IsFreebsd()) {
|
||||
how = flags & O_CLOEXEC ? F_DUP2FD_CLOEXEC : F_DUP2FD;
|
||||
if (flags & O_CLOEXEC) {
|
||||
how = F_DUP2FD_CLOEXEC;
|
||||
} else {
|
||||
how = F_DUP2FD;
|
||||
}
|
||||
return __sys_fcntl(oldfd, how, newfd);
|
||||
}
|
||||
|
||||
pthread_once(&g_dup3.once, sys_dup3_test);
|
||||
|
||||
if (!g_dup3.demodernize) {
|
||||
return __sys_dup3(oldfd, newfd, flags);
|
||||
} else {
|
||||
return __fixupnewfd(sys_dup2(oldfd, newfd), flags);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -46,14 +47,14 @@
|
|||
*/
|
||||
int dup3(int oldfd, int newfd, int flags) {
|
||||
int rc;
|
||||
if (__isfdkind(oldfd, kFdZip)) {
|
||||
if (oldfd == newfd || (flags & ~O_CLOEXEC)) {
|
||||
rc = einval(); // NetBSD doesn't do this
|
||||
} else if (oldfd < 0 || newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (__isfdkind(oldfd, kFdZip)) {
|
||||
rc = eopnotsupp();
|
||||
} else if (oldfd == newfd) {
|
||||
rc = einval();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_dup3(oldfd, newfd, flags);
|
||||
} else if (newfd < 0) {
|
||||
rc = ebadf();
|
||||
} else {
|
||||
rc = sys_dup_nt(oldfd, newfd, flags, -1);
|
||||
}
|
||||
|
|
|
@ -23,20 +23,12 @@
|
|||
#include "libc/nt/files.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_chdir_nt_impl(char16_t[hasatleast PATH_MAX], uint32_t);
|
||||
|
||||
textwindows int sys_fchdir_nt(int dirfd) {
|
||||
uint32_t len;
|
||||
char16_t dir[PATH_MAX];
|
||||
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
|
||||
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos);
|
||||
if (len + 1 + 1 > ARRAYLEN(dir)) return enametoolong();
|
||||
if (dir[len - 1] != u'\\') {
|
||||
dir[len + 0] = u'\\';
|
||||
dir[len + 1] = u'\0';
|
||||
}
|
||||
if (SetCurrentDirectory(dir)) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
return sys_chdir_nt_impl(
|
||||
dir, GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
|
||||
kNtFileNameNormalized | kNtVolumeNameDos));
|
||||
}
|
||||
|
|
|
@ -24,42 +24,47 @@
|
|||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
bool __force_sqlite_to_work_until_we_can_fix_it;
|
||||
|
||||
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
|
||||
if (start < 0) return einval();
|
||||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
||||
}
|
||||
|
||||
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
||||
int e;
|
||||
struct flock *l;
|
||||
uint32_t flags, err;
|
||||
struct NtOverlapped ov;
|
||||
int64_t pos, off, len, size;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!GetFileInformationByHandle(f->handle, &info)) return __winerr();
|
||||
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) return __winerr();
|
||||
|
||||
if (!GetFileInformationByHandle(f->handle, &info)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
l = (struct flock *)arg;
|
||||
len = l->l_len;
|
||||
off = l->l_start;
|
||||
size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow;
|
||||
|
||||
switch (l->l_whence) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
|
@ -72,37 +77,60 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
|
|||
default:
|
||||
return einval();
|
||||
}
|
||||
if (!len) len = size - off;
|
||||
if (off < 0 || len < 0) return einval();
|
||||
_offset2overlap(f->handle, off, &ov);
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd == F_SETLK) flags |= kNtLockfileFailImmediately;
|
||||
/* TODO: How can we make SQLite locks on Windows to work? */
|
||||
/* if (l->l_type == F_WRLCK) flags |= kNtLockfileExclusiveLock; */
|
||||
if (LockFileEx(f->handle, flags, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorLockViolation) err = EAGAIN;
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
} else if (l->l_type == F_UNLCK) {
|
||||
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
err = GetLastError();
|
||||
if (err == kNtErrorNotLocked) {
|
||||
return 0;
|
||||
} else {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!len) {
|
||||
len = size - off;
|
||||
}
|
||||
|
||||
if (off < 0 || len < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
bool32 ok;
|
||||
struct NtOverlapped ov = {.hEvent = f->handle,
|
||||
.Pointer = (void *)(uintptr_t)off};
|
||||
|
||||
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
|
||||
flags = 0;
|
||||
if (cmd != F_SETLKW) {
|
||||
flags |= kNtLockfileFailImmediately;
|
||||
}
|
||||
if (l->l_type == F_WRLCK) {
|
||||
flags |= kNtLockfileExclusiveLock;
|
||||
}
|
||||
ok = LockFileEx(f->handle, flags, 0, len, len >> 32, &ov);
|
||||
if (cmd == F_GETLK) {
|
||||
if (ok) {
|
||||
l->l_type = F_UNLCK;
|
||||
if (!UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
notpossible;
|
||||
}
|
||||
} else {
|
||||
l->l_pid = -1;
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
if (ok || __force_sqlite_to_work_until_we_can_fix_it) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (l->l_type == F_UNLCK) {
|
||||
if (cmd == F_GETLK) return einval();
|
||||
e = errno;
|
||||
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
|
||||
return 0;
|
||||
} else if (errno == ENOLCK) {
|
||||
errno = e;
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return einval();
|
||||
}
|
||||
|
||||
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_fcntl(int fd, int cmd, uintptr_t arg) {
|
||||
int rc;
|
||||
int e, rc;
|
||||
bool islock;
|
||||
if ((islock = cmd == F_GETLK || //
|
||||
cmd == F_SETLK || //
|
||||
|
@ -37,9 +39,13 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg) {
|
|||
}
|
||||
cosmo2flock(arg);
|
||||
}
|
||||
e = errno;
|
||||
rc = __sys_fcntl(fd, cmd, arg);
|
||||
if (islock) {
|
||||
flock2cosmo(arg);
|
||||
} else if (rc == -1 && cmd == F_DUPFD_CLOEXEC && errno == EINVAL) {
|
||||
errno = e;
|
||||
rc = __fixupnewfd(__sys_fcntl(fd, F_DUPFD, arg), O_CLOEXEC);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -37,11 +37,9 @@
|
|||
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3);
|
||||
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3);
|
||||
*
|
||||
* This function implements POSIX Advisory Locks, e.g.
|
||||
*
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));
|
||||
* // ...
|
||||
* CHECK_NE(-1, fcntl(zfd, F_SETLK, &(struct flock){F_UNLCK}));
|
||||
* This function implements POSIX Advisory Locks, which let independent
|
||||
* processes (and on Windows, threads too!) read/write lock byte ranges
|
||||
* of files. See `test/libc/calls/lock_test.c` for an example.
|
||||
*
|
||||
* Please be warned that locks currently do nothing on Windows since
|
||||
* figuring out how to polyfill them correctly is a work in progress.
|
||||
|
|
|
@ -16,19 +16,19 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
/**
|
||||
* Applies file descriptor fixups on XNU or old Linux.
|
||||
* @see __fixupnewsockfd() for socket file descriptors
|
||||
*/
|
||||
// Applies file descriptor fixups on XNU or old Linux.
|
||||
// See __fixupnewsockfd() for socket file descriptors.
|
||||
int __fixupnewfd(int fd, int flags) {
|
||||
if (fd != -1) {
|
||||
if (flags & O_CLOEXEC) {
|
||||
__sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
_npassert(!__sys_fcntl(fd, F_SETFD, FD_CLOEXEC));
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
|
|
|
@ -17,28 +17,49 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/enum/filelockflags.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||
#include "libc/nt/struct/overlapped.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/lock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define _LOCK_SH 0
|
||||
#define _LOCK_EX kNtLockfileExclusiveLock
|
||||
#define _LOCK_NB kNtLockfileFailImmediately
|
||||
#define _LOCK_UN 8
|
||||
|
||||
textwindows int sys_flock_nt(int fd, int op) {
|
||||
struct NtOverlapped ov;
|
||||
int64_t h;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
bzero(&ov, sizeof(ov));
|
||||
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
|
||||
((!(op & LOCK_UN) &&
|
||||
LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow,
|
||||
info.nFileSizeHigh, &ov)) ||
|
||||
((op & LOCK_UN) && UnlockFileEx(g_fds.p[fd].handle, 0, info.nFileSizeLow,
|
||||
info.nFileSizeHigh, &ov)))) {
|
||||
return 0;
|
||||
} else {
|
||||
h = g_fds.p[fd].handle;
|
||||
struct NtOverlapped ov = {.hEvent = h};
|
||||
|
||||
if (!GetFileInformationByHandle(h, &info)) {
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
if (op & _LOCK_UN) {
|
||||
if (op & ~_LOCK_UN) {
|
||||
return einval();
|
||||
}
|
||||
if (UnlockFileEx(h, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (op & ~(_LOCK_SH | _LOCK_EX | _LOCK_NB)) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (LockFileEx(h, op, 0, info.nFileSizeLow, info.nFileSizeHigh, &ov)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,16 +24,18 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int32_t sys_pipe2(int pipefd[hasatleast 2], unsigned flags) {
|
||||
int rc, olderr;
|
||||
int e, rc;
|
||||
if (!flags) goto OldSkool;
|
||||
olderr = errno;
|
||||
e = errno;
|
||||
rc = __sys_pipe2(pipefd, flags);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = olderr;
|
||||
errno = e;
|
||||
OldSkool:
|
||||
if ((rc = sys_pipe(pipefd)) != -1) {
|
||||
__fixupnewfd(pipefd[0], flags);
|
||||
__fixupnewfd(pipefd[1], flags);
|
||||
if (flags) {
|
||||
__fixupnewfd(pipefd[0], flags);
|
||||
__fixupnewfd(pipefd[1], flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
|
|
@ -46,8 +46,11 @@
|
|||
*/
|
||||
ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
||||
ssize_t rc;
|
||||
if (fd == -1 || offset < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = _weaken(__zipos_read)(
|
||||
|
@ -60,7 +63,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
assert(rc == -1 || (size_t)rc <= size);
|
||||
_npassert(rc == -1 || (size_t)rc <= size);
|
||||
DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,
|
||||
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
return rc;
|
||||
|
|
|
@ -16,91 +16,104 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
static bool once, demodernize;
|
||||
int i, err;
|
||||
ssize_t rc;
|
||||
size_t got, toto;
|
||||
int e, i;
|
||||
size_t got;
|
||||
bool masked;
|
||||
ssize_t rc, toto;
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
if (fd < 0) {
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (fd < 0) return einval();
|
||||
if (iovlen < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
} else if (IsWindows()) {
|
||||
}
|
||||
|
||||
if (IsMetal()) {
|
||||
return espipe(); // must be serial or console if not zipos
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
if (fd < g_fds.n) {
|
||||
return sys_read_nt(g_fds.p + fd, iov, iovlen, off);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pread(fd, iov[0].iov_base, iov[0].iov_len, off, off);
|
||||
}
|
||||
|
||||
/*
|
||||
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
|
||||
*/
|
||||
if (!__vforked && !once) {
|
||||
err = errno;
|
||||
rc = sys_preadv(fd, iov, iovlen, off, off);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = err;
|
||||
once = true;
|
||||
demodernize = true;
|
||||
STRACE("demodernizing %s() due to %s", "preadv", "ENOSYS");
|
||||
} else {
|
||||
once = true;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!demodernize) {
|
||||
return sys_preadv(fd, iov, iovlen, off, off);
|
||||
while (iovlen && !iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
}
|
||||
|
||||
if (!iovlen) {
|
||||
return sys_pread(fd, NULL, 0, off, off);
|
||||
return sys_pread(fd, 0, 0, off, off);
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pread(fd, iov->iov_base, iov->iov_len, off, off);
|
||||
}
|
||||
|
||||
e = errno;
|
||||
rc = sys_preadv(fd, iov, iovlen, off, off);
|
||||
if (rc != -1 || errno != ENOSYS) return rc;
|
||||
errno = e;
|
||||
|
||||
for (toto = i = 0; i < iovlen; ++i) {
|
||||
rc = sys_pread(fd, iov[i].iov_base, iov[i].iov_len, off, off);
|
||||
if (rc == -1) {
|
||||
if (toto && (errno == EINTR || errno == EAGAIN)) {
|
||||
return toto;
|
||||
} else {
|
||||
return -1;
|
||||
if (!toto) {
|
||||
toto = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
got = rc;
|
||||
toto += got;
|
||||
off += got;
|
||||
if (got != iov[i].iov_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!masked) {
|
||||
sigfillset(&mask);
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
|
||||
masked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (masked) {
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
|
||||
}
|
||||
|
||||
return toto;
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -46,9 +46,11 @@
|
|||
ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
if (fd == -1 || offset < 0) return einval();
|
||||
size = MIN(size, 0x7ffff000);
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
if (offset < 0) {
|
||||
rc = einval();
|
||||
} else if (fd == -1) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pwrite(fd, buf, size, offset, offset);
|
||||
|
@ -59,10 +61,10 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
}
|
||||
if (rc != -1) {
|
||||
wrote = (size_t)rc;
|
||||
if (wrote == 0) {
|
||||
assert(size == 0);
|
||||
if (!wrote) {
|
||||
_npassert(size == 0);
|
||||
} else {
|
||||
assert(wrote <= size);
|
||||
_npassert(wrote <= size);
|
||||
}
|
||||
}
|
||||
DATATRACE("pwrite(%d, %#.*hhs%s, %'zu, %'zd) → %'zd% m", fd,
|
||||
|
|
|
@ -16,90 +16,105 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
int64_t off) {
|
||||
static bool once, demodernize;
|
||||
int i, err;
|
||||
ssize_t rc;
|
||||
size_t sent, toto;
|
||||
int i, e;
|
||||
bool masked;
|
||||
size_t sent;
|
||||
ssize_t rc, toto;
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
if (fd < 0) {
|
||||
return ebadf();
|
||||
}
|
||||
|
||||
if (iovlen < 0) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
if (fd < 0) return einval();
|
||||
if (iovlen < 0) return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return _weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, off);
|
||||
} else if (IsWindows()) {
|
||||
}
|
||||
|
||||
if (IsWindows()) {
|
||||
if (fd < g_fds.n) {
|
||||
return sys_write_nt(fd, iov, iovlen, off);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else if (IsMetal()) {
|
||||
return enosys();
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pwrite(fd, iov[0].iov_base, iov[0].iov_len, off, off);
|
||||
if (IsMetal()) {
|
||||
return espipe(); // must be serial or console if not zipos
|
||||
}
|
||||
|
||||
/*
|
||||
* NT, 2018-era XNU, and 2007-era Linux don't support this system call
|
||||
*/
|
||||
if (!once) {
|
||||
err = errno;
|
||||
rc = sys_pwritev(fd, iov, iovlen, off, off);
|
||||
if (rc == -1 && errno == ENOSYS) {
|
||||
errno = err;
|
||||
once = true;
|
||||
demodernize = true;
|
||||
STRACE("demodernizing %s() due to %s", "pwritev", "ENOSYS");
|
||||
} else {
|
||||
once = true;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!demodernize) {
|
||||
return sys_pwritev(fd, iov, iovlen, off, off);
|
||||
while (iovlen && !iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
}
|
||||
|
||||
if (!iovlen) {
|
||||
return sys_pwrite(fd, NULL, 0, off, off);
|
||||
return sys_pwrite(fd, 0, 0, off, off);
|
||||
}
|
||||
|
||||
if (iovlen == 1) {
|
||||
return sys_pwrite(fd, iov->iov_base, iov->iov_len, off, off);
|
||||
}
|
||||
|
||||
e = errno;
|
||||
rc = sys_pwritev(fd, iov, iovlen, off, off);
|
||||
if (rc != -1 || errno != ENOSYS) return rc;
|
||||
errno = e;
|
||||
|
||||
for (toto = i = 0; i < iovlen; ++i) {
|
||||
rc = sys_pwrite(fd, iov[i].iov_base, iov[i].iov_len, off, off);
|
||||
if (rc == -1) {
|
||||
if (toto && (errno == EINTR || errno == EAGAIN)) {
|
||||
return toto;
|
||||
} else {
|
||||
return -1;
|
||||
if (!toto) {
|
||||
toto = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
sent = rc;
|
||||
toto += sent;
|
||||
off += sent;
|
||||
if (sent != iov[i].iov_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!masked) {
|
||||
sigfillset(&mask);
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
|
||||
masked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (masked) {
|
||||
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
|
||||
}
|
||||
|
||||
return toto;
|
||||
|
|
|
@ -16,14 +16,16 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
@ -35,8 +37,10 @@
|
|||
|
||||
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||
size_t size, ssize_t offset) {
|
||||
int64_t p;
|
||||
uint32_t got, avail;
|
||||
struct NtOverlapped overlap;
|
||||
|
||||
if (GetFileType(fd->handle) == kNtFileTypePipe) {
|
||||
for (;;) {
|
||||
if (!PeekNamedPipe(fd->handle, 0, 0, 0, &avail, 0)) break;
|
||||
|
@ -52,10 +56,20 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
|||
}
|
||||
POLLTRACE("sys_read_nt ready to read");
|
||||
}
|
||||
|
||||
if (offset != -1) {
|
||||
// windows changes the file pointer even if overlapped is passed
|
||||
_npassert(SetFilePointerEx(fd->handle, 0, &p, SEEK_CUR));
|
||||
}
|
||||
|
||||
if (ReadFile(fd->handle, data, _clampio(size), &got,
|
||||
_offset2overlap(fd->handle, offset, &overlap))) {
|
||||
if (offset != -1) {
|
||||
_npassert(SetFilePointerEx(fd->handle, p, 0, SEEK_SET));
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
switch (GetLastError()) {
|
||||
case kNtErrorBrokenPipe: // broken pipe
|
||||
case kNtErrorNoData: // closing named pipe
|
||||
|
@ -73,6 +87,7 @@ textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
|
|||
ssize_t rc;
|
||||
uint32_t size;
|
||||
size_t i, total;
|
||||
if (opt_offset < -1) return einval();
|
||||
if (_check_interrupts(true, fd)) return eintr();
|
||||
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
||||
if (iovlen) {
|
||||
|
|
|
@ -18,7 +18,7 @@ int sys_sched_setscheduler(int, int, const struct sched_param *);
|
|||
int sys_sched_yield(void) hidden;
|
||||
int64_t sys_sched_getaffinity(int, uint64_t, void *) hidden;
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int);
|
||||
int sys_sched_getscheduler_netbsd(int, struct sched_param *);
|
||||
int sys_sched_setparam_netbsd(int, int, int, const struct sched_param *) //
|
||||
asm("sys_sched_setparam");
|
||||
int sys_sched_getparam_netbsd(int, int, int *, struct sched_param *) //
|
||||
|
|
|
@ -16,11 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
|
@ -52,7 +54,7 @@ static textwindows int sys_sched_getaffinity_nt(int tid, size_t size,
|
|||
* @param bitset receives bitset and should be uint64_t[16] in order to
|
||||
* work on older versions of Linux
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on non-Linux
|
||||
* @raise ENOSYS if not Linux, NetBSD, or Windows
|
||||
*/
|
||||
int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) {
|
||||
int rc;
|
||||
|
@ -60,6 +62,12 @@ int sched_getaffinity(int tid, size_t size, cpu_set_t *bitset) {
|
|||
rc = einval();
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_sched_getaffinity_nt(tid, size, bitset);
|
||||
} else if (IsNetbsd()) {
|
||||
if (!sys_sched_getaffinity_netbsd(0, tid, MIN(size, 32), bitset)) {
|
||||
rc = MIN(size, 32);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_getaffinity(tid, size, bitset);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,31 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy parameter.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
*/
|
||||
int sched_getparam(int pid, struct sched_param *param) {
|
||||
return sys_sched_getparam(pid, param);
|
||||
int rc;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if (!(rc = sys_sched_getscheduler_netbsd(pid, &p))) {
|
||||
*param = p;
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_getparam(pid, param);
|
||||
}
|
||||
STRACE("sched_getparam(%d, [%s]) → %d% m", pid, DescribeSchedParam(param),
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,9 @@
|
|||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int pid) {
|
||||
int sys_sched_getscheduler_netbsd(int pid, struct sched_param *sp) {
|
||||
int policy;
|
||||
struct sched_param sp;
|
||||
if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, &sp) != -1) {
|
||||
if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, sp) != -1) {
|
||||
return policy;
|
||||
} else {
|
||||
return -1;
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy for `pid`.
|
||||
|
@ -40,7 +40,8 @@
|
|||
int sched_getscheduler(int pid) {
|
||||
int rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
struct sched_param p;
|
||||
rc = sys_sched_getscheduler_netbsd(pid, &p);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/processaccess.h"
|
||||
#include "libc/nt/enum/threadaccess.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
@ -34,14 +35,14 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows dontinline int sys_sched_setaffinity_nt(int pid,
|
||||
uint64_t bitsetsize,
|
||||
uint64_t size,
|
||||
const void *bitset) {
|
||||
int rc;
|
||||
uintptr_t mask;
|
||||
int64_t handle;
|
||||
uintptr_t mask;
|
||||
typeof(SetThreadAffinityMask) *SetAffinityMask = SetThreadAffinityMask;
|
||||
mask = 0;
|
||||
memcpy(&mask, bitset, min(bitsetsize, sizeof(uintptr_t)));
|
||||
memcpy(&mask, bitset, min(size, sizeof(uintptr_t)));
|
||||
handle = 0;
|
||||
if (!pid) pid = GetCurrentThreadId();
|
||||
if (0 < pid && pid <= UINT32_MAX) {
|
||||
|
@ -69,19 +70,21 @@ static textwindows dontinline int sys_sched_setaffinity_nt(int pid,
|
|||
* Asks kernel to only schedule thread on particular CPUs.
|
||||
*
|
||||
* @param tid is the process or thread id (or 0 for caller)
|
||||
* @param bitsetsize is byte length of bitset, which should be 128
|
||||
* @param size is byte length of bitset, which should be 128
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS if not Linux or Windows
|
||||
* @raise ENOSYS if not Linux, NetBSD, or Windows
|
||||
*/
|
||||
int sched_setaffinity(int tid, size_t bitsetsize, const cpu_set_t *bitset) {
|
||||
int sched_setaffinity(int tid, size_t size, const cpu_set_t *bitset) {
|
||||
int rc;
|
||||
if (bitsetsize != 128) {
|
||||
if (size != 128) {
|
||||
rc = einval();
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_sched_setaffinity_nt(tid, bitsetsize, bitset);
|
||||
rc = sys_sched_setaffinity_nt(tid, size, bitset);
|
||||
} else if (IsNetbsd()) {
|
||||
rc = sys_sched_setaffinity_netbsd(0, tid, MIN(size, 32), bitset);
|
||||
} else {
|
||||
rc = sys_sched_setaffinity(tid, bitsetsize, bitset);
|
||||
rc = sys_sched_setaffinity(tid, size, bitset);
|
||||
}
|
||||
STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, bitsetsize, bitset);
|
||||
STRACE("sched_setaffinity(%d, %'zu, %p) → %d% m", tid, size, bitset);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,30 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets scheduler policy parameter.
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
*/
|
||||
int sched_setparam(int pid, const struct sched_param *param) {
|
||||
return sys_sched_setparam(pid, param);
|
||||
int rc, policy;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if ((rc = policy = sys_sched_getscheduler_netbsd(pid, &p)) != -1) {
|
||||
rc = sys_sched_setparam_netbsd(pid, P_ALL_LWPS, policy, param);
|
||||
}
|
||||
} else {
|
||||
rc = sys_sched_setparam(pid, param);
|
||||
}
|
||||
STRACE("sched_setparam(%d, %s) → %d% m", pid, DescribeSchedParam(param), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
* Sets scheduling policy of process, e.g.
|
||||
|
@ -94,9 +94,10 @@
|
|||
*/
|
||||
int sched_setscheduler(int pid, int policy, const struct sched_param *param) {
|
||||
int rc, old;
|
||||
struct sched_param p;
|
||||
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
rc = sys_sched_getscheduler_netbsd(pid, &p);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
|
@ -26,6 +28,7 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -35,12 +38,25 @@
|
|||
|
||||
static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
||||
ssize_t offset) {
|
||||
int64_t h, p;
|
||||
uint32_t err, sent;
|
||||
struct NtOverlapped overlap;
|
||||
if (WriteFile(g_fds.p[fd].handle, data, _clampio(size), &sent,
|
||||
_offset2overlap(g_fds.p[fd].handle, offset, &overlap))) {
|
||||
|
||||
h = g_fds.p[fd].handle;
|
||||
|
||||
if (offset != -1) {
|
||||
// windows changes the file pointer even if overlapped is passed
|
||||
_npassert(SetFilePointerEx(h, 0, &p, SEEK_CUR));
|
||||
}
|
||||
|
||||
if (WriteFile(h, data, _clampio(size), &sent,
|
||||
_offset2overlap(h, offset, &overlap))) {
|
||||
if (offset != -1) {
|
||||
_npassert(SetFilePointerEx(h, p, 0, SEEK_SET));
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
switch (GetLastError()) {
|
||||
// case kNtErrorInvalidHandle:
|
||||
// return ebadf(); /* handled by consts.sh */
|
||||
|
@ -68,6 +84,7 @@ textwindows ssize_t sys_write_nt(int fd, const struct iovec *iov, size_t iovlen,
|
|||
size_t i, total;
|
||||
uint32_t size, wrote;
|
||||
struct NtOverlapped overlap;
|
||||
if (opt_offset < -1) return einval();
|
||||
while (iovlen && !iov[0].iov_len) iov++, iovlen--;
|
||||
if (iovlen) {
|
||||
for (total = i = 0; i < iovlen; ++i) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue