Skip to content

Commit

Permalink
Make more fixups and quality assurance
Browse files Browse the repository at this point in the history
  • Loading branch information
jart committed Oct 7, 2024
1 parent 85c58be commit dcf9596
Show file tree
Hide file tree
Showing 17 changed files with 80 additions and 78 deletions.
1 change: 0 additions & 1 deletion libc/calls/getgroups.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "libc/dce.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"

/**
Expand Down
3 changes: 0 additions & 3 deletions libc/calls/pipe-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ static textwindows int sys_pipe_nt_impl(int pipefd[2], unsigned flags) {
__fds_unlock();
hin = CreateNamedPipe(pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped,
mode, 1, PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable);
__fds_lock();
if (hin != -1) {
if ((hout = CreateFile(
pipename, kNtGenericWrite,
Expand All @@ -73,15 +72,13 @@ static textwindows int sys_pipe_nt_impl(int pipefd[2], unsigned flags) {
g_fds.p[writer].handle = hout;
pipefd[0] = reader;
pipefd[1] = writer;
__fds_unlock();
return 0;
} else {
CloseHandle(hin);
}
}
__releasefd(writer);
__releasefd(reader);
__fds_unlock();
return -1;
}

Expand Down
7 changes: 4 additions & 3 deletions libc/calls/poll-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,14 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
}
}

textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds, uint32_t *ms,
textwindows int sys_poll_nt(struct pollfd *fds, uint64_t nfds,
const struct timespec *relative,
const sigset_t *sigmask) {
int rc;
struct timespec now, timeout, deadline;
BLOCK_SIGNALS;
now = ms ? sys_clock_gettime_monotonic_nt() : timespec_zero;
timeout = ms ? timespec_frommillis(*ms) : timespec_max;
now = relative ? sys_clock_gettime_monotonic_nt() : timespec_zero;
timeout = relative ? *relative : timespec_max;
deadline = timespec_add(now, timeout);
rc = sys_poll_nt_impl(fds, nfds, deadline, sigmask ? *sigmask : _SigMask);
ALLOW_SIGNALS;
Expand Down
20 changes: 8 additions & 12 deletions libc/calls/ppoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/strace.h"
#include "libc/limits.h"
#include "libc/runtime/stack.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
Expand Down Expand Up @@ -76,10 +77,13 @@ static int ppoll_impl(struct pollfd *fds, size_t nfds,
}
fdcount = sys_ppoll(fds, nfds, tsp, sigmask, 8);
if (fdcount == -1 && errno == ENOSYS) {
int ms;
int64_t ms;
errno = e;
if (!timeout || ckd_add(&ms, timeout->tv_sec,
(timeout->tv_nsec + 999999) / 1000000)) {
if (timeout) {
ms = timespec_tomillis(*timeout);
if (ms > INT_MAX)
ms = -1;
} else {
ms = -1;
}
if (sigmask)
Expand All @@ -89,15 +93,7 @@ static int ppoll_impl(struct pollfd *fds, size_t nfds,
sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
}
} else {
uint32_t ms;
uint32_t *msp;
if (timeout &&
!ckd_add(&ms, timeout->tv_sec, (timeout->tv_nsec + 999999) / 1000000)) {
msp = &ms;
} else {
msp = 0;
}
fdcount = sys_poll_nt(fds, nfds, msp, sigmask);
fdcount = sys_poll_nt(fds, nfds, timeout, sigmask);
}

if (IsOpenbsd() && fdcount != -1) {
Expand Down
10 changes: 1 addition & 9 deletions libc/calls/pselect.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
const struct timespec *timeout, const sigset_t *sigmask) {
int rc;
struct timeval tv, *tvp;
struct timespec ts, *tsp;
struct {
const sigset_t *s;
Expand Down Expand Up @@ -111,14 +110,7 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
rc = sys_pselect(nfds, readfds, writefds, exceptfds,
(struct timespec *)timeout, sigmask);
} else {
if (timeout) {
tv.tv_sec = timeout->tv_sec;
tv.tv_usec = timeout->tv_nsec / 1000;
tvp = &tv;
} else {
tvp = 0;
}
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, tvp, sigmask);
rc = sys_select_nt(nfds, readfds, writefds, exceptfds, timeout, sigmask);
}
}
END_CANCELATION_POINT;
Expand Down
22 changes: 2 additions & 20 deletions libc/calls/select-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/stdckdint.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
Expand All @@ -44,7 +43,7 @@
// </sync libc/sysv/consts.sh>

int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask) {
int pfds = 0;

Expand All @@ -68,21 +67,8 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
}
}

// convert the wait time to a word
uint32_t millis;
if (!timeout) {
millis = -1u;
} else {
int64_t ms = timeval_tomillis(*timeout);
if (ms < 0 || ms > UINT32_MAX) {
millis = -1u;
} else {
millis = ms;
}
}

// call our nt poll implementation
int fdcount = sys_poll_nt(fds, pfds, &millis, sigmask);
int fdcount = sys_poll_nt(fds, pfds, timeout, sigmask);
if (fdcount == -1)
return -1;

Expand Down Expand Up @@ -115,10 +101,6 @@ int sys_select_nt(int nfds, fd_set *readfds, fd_set *writefds,
}
}

// store remaining time back in caller's timeval
if (timeout)
*timeout = timeval_frommillis(millis);

return bits;
}

Expand Down
5 changes: 1 addition & 4 deletions libc/calls/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@
* such as out-of-band data on a socket; it is equivalent to POLLPRI
* in the revents of poll()
* @param timeout may be null which means to block indefinitely; cosmo's
* implementation of select() never modifies this parameter which is
* how most platforms except Linux work which modifies it to reflect
* elapsed time, noting that POSIX permits either behavior therefore
* portable code should assume that timeout memory becomes undefined
* implementation of select() never modifies this parameter
* @raise E2BIG if we exceeded the 64 socket limit on Windows
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINTR if signal was delivered
Expand Down
1 change: 0 additions & 1 deletion libc/calls/setgroups.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "libc/dce.h"
#include "libc/intrin/describeflags.h"
#include "libc/intrin/strace.h"
#include "libc/stdckdint.h"
#include "libc/sysv/errfuns.h"

/**
Expand Down
3 changes: 2 additions & 1 deletion libc/sock/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
Expand Down Expand Up @@ -60,7 +61,7 @@ int sys_socketpair_nt_stream(int, int, int, int[2]) ;
int sys_socketpair_nt_dgram(int, int, int, int[2]) ;
*/
int sys_socketpair_nt(int, int, int, int[2]);
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *,
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
const sigset_t *);

size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, size_t);
Expand Down
5 changes: 3 additions & 2 deletions libc/sock/send-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,

__sig_unblock(waitmask);

if (rc == -1 && errno == WSAESHUTDOWN) { // ESHUTDOWN
errno = kNtErrorBrokenPipe; // EPIPE
if (rc == -1 && (errno == WSAESHUTDOWN || // ESHUTDOWN
errno == WSAECONNABORTED)) { // ECONNABORTED
errno = kNtErrorBrokenPipe; // EPIPE
if (!(flags & _MSG_NOSIGNAL))
__sig_raise(SIGPIPE, SI_KERNEL);
}
Expand Down
5 changes: 3 additions & 2 deletions libc/sock/sendto-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,

__sig_unblock(waitmask);

if (rc == -1 && errno == WSAESHUTDOWN) { // ESHUTDOWN
errno = kNtErrorBrokenPipe; // EPIPE
if (rc == -1 && (errno == WSAESHUTDOWN || // ESHUTDOWN
errno == WSAECONNABORTED)) { // ECONNABORTED
errno = kNtErrorBrokenPipe; // EPIPE
if (!(flags & _MSG_NOSIGNAL))
__sig_raise(SIGPIPE, SI_KERNEL);
}
Expand Down
3 changes: 2 additions & 1 deletion libc/sock/struct/pollfd.internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ int32_t __sys_poll(struct pollfd *, uint64_t, signed);
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
const sigset_t *, size_t);
int sys_poll_metal(struct pollfd *, size_t, unsigned);
int sys_poll_nt(struct pollfd *, uint64_t, uint32_t *, const sigset_t *);
int sys_poll_nt(struct pollfd *, uint64_t, const struct timespec *,
const sigset_t *);

const char *_DescribePollFds(char[300], ssize_t, struct pollfd *, size_t);
#define DescribePollFds(x, y, z) _DescribePollFds(alloca(300), x, y, z)
Expand Down
3 changes: 1 addition & 2 deletions libc/stdio/fwrite_unlocked.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
size_t n, m;
const char *p;
struct iovec iov[2];
if (!stride || !count) {
if (!stride || !count)
return 0;
}
if ((f->iomode & O_ACCMODE) == O_RDONLY) {
f->state = errno = EBADF;
return 0;
Expand Down
11 changes: 4 additions & 7 deletions libc/stdio/vfprintf_unlocked.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/fmt/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/stdckdint.h"
#include "libc/stdio/internal.h"
#include "libc/stdio/stdio.h"
Expand Down Expand Up @@ -46,9 +47,8 @@ static int __vfprintf_flbuf(const char *s, struct state *t, size_t n) {
} else {
rc = -1;
}
if (ckd_add(&t->n, t->n, n)) {
if (ckd_add(&t->n, t->n, n))
rc = eoverflow();
}
} else {
rc = 0;
}
Expand All @@ -60,9 +60,8 @@ static int __vfprintf_nbuf(const char *s, struct state *t, size_t n) {
for (i = 0; i < n; ++i) {
t->b.p[t->b.n++] = s[i];
if (t->b.n == sizeof(t->b.p)) {
if (!fwrite_unlocked(t->b.p, 1, t->b.n, t->f)) {
if (!fwrite_unlocked(t->b.p, 1, t->b.n, t->f))
return -1;
}
t->b.n = 0;
} else if (ckd_add(&t->n, t->n, 1)) {
return eoverflow();
Expand Down Expand Up @@ -91,9 +90,7 @@ int vfprintf_unlocked(FILE *f, const char *fmt, va_list va) {
if (!st.b.n) {
rc = st.n;
} else if (fwrite_unlocked(st.b.p, 1, st.b.n, st.f)) {
if (ckd_add(&rc, st.n, st.b.n)) {
rc = eoverflow();
}
rc = st.n;
} else {
rc = -1;
}
Expand Down
43 changes: 43 additions & 0 deletions test/posix/printf_return_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 Justine Alexandra Roberts Tunney
//
// Permission to use, copy, modify, and/or distribute this software for
// any purpose with or without fee is hereby granted, provided that the
// above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main() {

if (close(1))
return 1;
if (open("/dev/null", O_WRONLY) != 1)
return 2;

if (printf("a") != 1)
return 4;
if (printf("%s", "") != 0)
return 5;
if (printf("%s", "a") != 1)
return 6;
if (printf("%10s", "a") != 10)
return 6;
if (printf("%-10s", "a") != 10)
return 6;
if (printf("%-10s%-40s %9s %8s %8s %8s\n", "Benchmark", "prog", "ops",
"time", "ops/sec", "time/op") != 89)
return 7;
if (fprintf(stdout, "%-10s%-40s %9s %8s %8s %8s\n", "Benchmark", "prog",
"ops", "time", "ops/sec", "time/op") != 89)
return 8;
}
4 changes: 0 additions & 4 deletions third_party/nsync/README.cosmo
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ LOCAL CHANGES
lets us use weak cas when appropriate. It also avoids a superfluous
relaxed load on failure. This mostly impacts aarch64, not x86_64.

- Modified *NSYNC to allocate waiter objects on the stack. We need it
because we use *NSYNC mutexes to implement POSIX mutexes, which are
too low-level to safely depend on malloc, or even mmap in our case.

- Rewrote most of the semaphore and futex system call support code so
it works well with Cosmopolitan's fat runtime portability. *NSYNC's
unit test suite passes on all supported platforms. However the BSDs
Expand Down
12 changes: 6 additions & 6 deletions third_party/nsync/mu.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,9 +477,9 @@ void nsync_mu_unlock (nsync_mu *mu) {
and deallocate the mutex before the current thread touched the mutex
word again. */
uint32_t old_word = MU_WLOCK;
if (!atomic_compare_exchange_weak_explicit (&mu->word, &old_word, 0,
memory_order_release,
memory_order_relaxed)) {
if (!atomic_compare_exchange_strong_explicit (&mu->word, &old_word, 0,
memory_order_release,
memory_order_relaxed)) {
/* Clear MU_ALL_FALSE because the critical section we're just
leaving may have made some conditions true. */
uint32_t new_word = (old_word - MU_WLOCK) & ~MU_ALL_FALSE;
Expand Down Expand Up @@ -508,9 +508,9 @@ void nsync_mu_runlock (nsync_mu *mu) {
IGNORE_RACES_START ();
/* See comment in nsync_mu_unlock(). */
uint32_t old_word = MU_RLOCK;
if (!atomic_compare_exchange_weak_explicit (&mu->word, &old_word, 0,
memory_order_release,
memory_order_relaxed)) {
if (!atomic_compare_exchange_strong_explicit (&mu->word, &old_word, 0,
memory_order_release,
memory_order_relaxed)) {
/* Sanity check: mutex must not be held in write mode and
reader count must not be 0. */
if (((old_word ^ MU_WLOCK) & (MU_WLOCK | MU_RLOCK_FIELD)) == 0) {
Expand Down

0 comments on commit dcf9596

Please sign in to comment.