forked from Bananymous/banan-os
LibC: Implement pthread cancelation
This code is not tested at all but it looks correct xD
This commit is contained in:
parent
56fdf6002c
commit
dbdefa0f4a
|
@ -351,8 +351,11 @@ namespace Kernel
|
||||||
.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
||||||
.master_tls_size = master_size,
|
.master_tls_size = master_size,
|
||||||
.cleanup_stack = nullptr,
|
.cleanup_stack = nullptr,
|
||||||
.id = -1,
|
.id = 0,
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
|
.cancel_type = 0,
|
||||||
|
.cancel_state = 0,
|
||||||
|
.canceled = 0,
|
||||||
};
|
};
|
||||||
const uintptr_t dtv[2] { 1, region->vaddr() };
|
const uintptr_t dtv[2] { 1, region->vaddr() };
|
||||||
|
|
||||||
|
|
|
@ -525,6 +525,8 @@ namespace Kernel
|
||||||
// Ignore the signal
|
// Ignore the signal
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
case SIGURG:
|
case SIGURG:
|
||||||
|
case SIGWINCH:
|
||||||
|
case SIGCANCEL:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Stop the process:
|
// Stop the process:
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int creat(const char* path, mode_t mode)
|
int creat(const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int open(const char* path, int oflag, ...)
|
int open(const char* path, int oflag, ...)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, oflag);
|
va_start(args, oflag);
|
||||||
mode_t mode = va_arg(args, mode_t);
|
mode_t mode = va_arg(args, mode_t);
|
||||||
|
@ -20,6 +24,8 @@ int open(const char* path, int oflag, ...)
|
||||||
|
|
||||||
int openat(int fd, const char* path, int oflag, ...)
|
int openat(int fd, const char* path, int oflag, ...)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, oflag);
|
va_start(args, oflag);
|
||||||
mode_t mode = va_arg(args, mode_t);
|
mode_t mode = va_arg(args, mode_t);
|
||||||
|
@ -30,6 +36,8 @@ int openat(int fd, const char* path, int oflag, ...)
|
||||||
|
|
||||||
int fcntl(int fildes, int cmd, ...)
|
int fcntl(int fildes, int cmd, ...)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, cmd);
|
va_start(args, cmd);
|
||||||
int extra = va_arg(args, int);
|
int extra = va_arg(args, int);
|
||||||
|
|
|
@ -32,10 +32,13 @@ struct uthread
|
||||||
struct _pthread_cleanup_t* cleanup_stack;
|
struct _pthread_cleanup_t* cleanup_stack;
|
||||||
pthread_t id;
|
pthread_t id;
|
||||||
int errno_;
|
int errno_;
|
||||||
|
int cancel_type;
|
||||||
|
int cancel_state;
|
||||||
|
int canceled;
|
||||||
uintptr_t dtv[];
|
uintptr_t dtv[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PTHREAD_CANCELED 1
|
#define PTHREAD_CANCELED (void*)1
|
||||||
|
|
||||||
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
|
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
|
||||||
#define PTHREAD_CANCEL_DEFERRED 0
|
#define PTHREAD_CANCEL_DEFERRED 0
|
||||||
|
@ -43,6 +46,9 @@ struct uthread
|
||||||
#define PTHREAD_CANCEL_DISABLE 0
|
#define PTHREAD_CANCEL_DISABLE 0
|
||||||
#define PTHREAD_CANCEL_ENABLE 1
|
#define PTHREAD_CANCEL_ENABLE 1
|
||||||
|
|
||||||
|
// cancellation points
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_09_05_02
|
||||||
|
|
||||||
#define PTHREAD_PRIO_INHERIT 1
|
#define PTHREAD_PRIO_INHERIT 1
|
||||||
#define PTHREAD_PRIO_NONE 0
|
#define PTHREAD_PRIO_NONE 0
|
||||||
#define PTHREAD_PRIO_PROTECT 2
|
#define PTHREAD_PRIO_PROTECT 2
|
||||||
|
|
|
@ -106,7 +106,8 @@ struct sigevent
|
||||||
#define SIGXCPU 27
|
#define SIGXCPU 27
|
||||||
#define SIGXFSZ 28
|
#define SIGXFSZ 28
|
||||||
#define SIGWINCH 29
|
#define SIGWINCH 29
|
||||||
#define SIGRTMIN 30
|
#define SIGCANCEL 30
|
||||||
|
#define SIGRTMIN 31
|
||||||
#define SIGRTMAX (SIGRTMIN+32)
|
#define SIGRTMAX (SIGRTMIN+32)
|
||||||
|
|
||||||
#define NSIG SIGRTMAX
|
#define NSIG SIGRTMAX
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
if (timeout < 0)
|
if (timeout < 0)
|
||||||
return ppoll(fds, nfds, nullptr, nullptr);
|
return ppoll(fds, nfds, nullptr, nullptr);
|
||||||
const timespec timeout_ts {
|
const timespec timeout_ts {
|
||||||
|
@ -15,5 +17,6 @@ int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||||
|
|
||||||
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask)
|
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_PPOLL, fds, nfds, timeout, sigmask);
|
return syscall(SYS_PPOLL, fds, nfds, timeout, sigmask);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,6 @@ extern "C" void _pthread_trampoline_cpp(void* arg)
|
||||||
{
|
{
|
||||||
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
|
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
|
||||||
info.uthread->id = syscall(SYS_PTHREAD_SELF);
|
info.uthread->id = syscall(SYS_PTHREAD_SELF);
|
||||||
info.uthread->errno_ = 0;
|
|
||||||
info.uthread->cleanup_stack = nullptr;
|
|
||||||
syscall(SYS_SET_TLS, info.uthread);
|
syscall(SYS_SET_TLS, info.uthread);
|
||||||
free(arg);
|
free(arg);
|
||||||
pthread_exit(info.start_routine(info.arg));
|
pthread_exit(info.start_routine(info.arg));
|
||||||
|
@ -315,14 +313,6 @@ int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_setcancelstate(int state, int* oldstate)
|
|
||||||
{
|
|
||||||
(void)state;
|
|
||||||
(void)oldstate;
|
|
||||||
dwarnln("TODO: pthread_setcancelstate");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
||||||
{
|
{
|
||||||
auto* info = static_cast<pthread_trampoline_info_t*>(malloc(sizeof(pthread_trampoline_info_t)));
|
auto* info = static_cast<pthread_trampoline_info_t*>(malloc(sizeof(pthread_trampoline_info_t)));
|
||||||
|
@ -350,6 +340,9 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
||||||
.cleanup_stack = nullptr,
|
.cleanup_stack = nullptr,
|
||||||
.id = -1,
|
.id = -1,
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
|
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||||
|
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||||
|
.canceled = false,
|
||||||
};
|
};
|
||||||
uthread->dtv[0] = 0;
|
uthread->dtv[0] = 0;
|
||||||
|
|
||||||
|
@ -376,6 +369,9 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
||||||
.cleanup_stack = nullptr,
|
.cleanup_stack = nullptr,
|
||||||
.id = -1,
|
.id = -1,
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
|
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||||
|
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||||
|
.canceled = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
|
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
|
||||||
|
@ -449,6 +445,7 @@ int pthread_equal(pthread_t t1, pthread_t t2)
|
||||||
|
|
||||||
int pthread_join(pthread_t thread, void** value_ptr)
|
int pthread_join(pthread_t thread, void** value_ptr)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
|
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,6 +470,72 @@ int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pthread_cancel_handler(int)
|
||||||
|
{
|
||||||
|
uthread* uthread = _get_uthread();
|
||||||
|
BAN::atomic_store(uthread->canceled, true);
|
||||||
|
if (BAN::atomic_load(uthread->cancel_state) != PTHREAD_CANCEL_ENABLE)
|
||||||
|
return;
|
||||||
|
switch (BAN::atomic_load(uthread->cancel_type))
|
||||||
|
{
|
||||||
|
case PTHREAD_CANCEL_ASYNCHRONOUS:
|
||||||
|
pthread_exit(PTHREAD_CANCELED);
|
||||||
|
case PTHREAD_CANCEL_DEFERRED:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_cancel(pthread_t thread)
|
||||||
|
{
|
||||||
|
signal(SIGCANCEL, &pthread_cancel_handler);
|
||||||
|
return pthread_kill(thread, SIGCANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_setcancelstate(int state, int* oldstate)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case PTHREAD_CANCEL_ENABLE:
|
||||||
|
case PTHREAD_CANCEL_DISABLE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::atomic_exchange(_get_uthread()->cancel_state, state);
|
||||||
|
if (oldstate)
|
||||||
|
*oldstate = state;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_setcanceltype(int type, int* oldtype)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case PTHREAD_CANCEL_DEFERRED:
|
||||||
|
case PTHREAD_CANCEL_ASYNCHRONOUS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::atomic_exchange(_get_uthread()->cancel_type, type);
|
||||||
|
if (oldtype)
|
||||||
|
*oldtype = type;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pthread_testcancel(void)
|
||||||
|
{
|
||||||
|
uthread* uthread = _get_uthread();
|
||||||
|
if (BAN::atomic_load(uthread->cancel_state) != PTHREAD_CANCEL_ENABLE)
|
||||||
|
return;
|
||||||
|
if (!BAN::atomic_load(uthread->canceled))
|
||||||
|
return;
|
||||||
|
pthread_exit(PTHREAD_CANCELED);
|
||||||
|
}
|
||||||
|
|
||||||
int pthread_spin_destroy(pthread_spinlock_t* lock)
|
int pthread_spin_destroy(pthread_spinlock_t* lock)
|
||||||
{
|
{
|
||||||
(void)lock;
|
(void)lock;
|
||||||
|
@ -909,11 +972,14 @@ int pthread_cond_signal(pthread_cond_t* cond)
|
||||||
|
|
||||||
int pthread_cond_wait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex)
|
int pthread_cond_wait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex)
|
||||||
{
|
{
|
||||||
|
// pthread_testcancel in pthread_cond_timedwait
|
||||||
return pthread_cond_timedwait(cond, mutex, nullptr);
|
return pthread_cond_timedwait(cond, mutex, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex, const struct timespec* __restrict abstime)
|
int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex, const struct timespec* __restrict abstime)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
constexpr auto has_timed_out =
|
constexpr auto has_timed_out =
|
||||||
[](const struct timespec* abstime, clockid_t clock_id) -> bool
|
[](const struct timespec* abstime, clockid_t clock_id) -> bool
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -25,6 +26,7 @@ int munmap(void* addr, size_t len)
|
||||||
|
|
||||||
int msync(void* addr, size_t len, int flags)
|
int msync(void* addr, size_t len, int flags)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_MSYNC, addr, len, flags);
|
return syscall(SYS_MSYNC, addr, len, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, const struct timespec* __restrict timeout, const sigset_t* __restrict sigmask)
|
int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, const struct timespec* __restrict timeout, const sigset_t* __restrict sigmask)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
sys_pselect_t arguments {
|
sys_pselect_t arguments {
|
||||||
.nfds = nfds,
|
.nfds = nfds,
|
||||||
.readfds = readfds,
|
.readfds = readfds,
|
||||||
|
@ -17,6 +19,7 @@ int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, f
|
||||||
|
|
||||||
int select(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, struct timeval* __restrict timeout)
|
int select(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, struct timeval* __restrict timeout)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
timespec* pts = nullptr;
|
timespec* pts = nullptr;
|
||||||
timespec ts;
|
timespec ts;
|
||||||
if (timeout)
|
if (timeout)
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int accept(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
|
int accept(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return accept4(socket, address, address_len, 0);
|
return accept4(socket, address, address_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int accept4(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len, int flags)
|
int accept4(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len, int flags)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_ACCEPT, socket, address, address_len, flags);
|
return syscall(SYS_ACCEPT, socket, address, address_len, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +22,7 @@ int bind(int socket, const struct sockaddr* address, socklen_t address_len)
|
||||||
|
|
||||||
int connect(int socket, const struct sockaddr* address, socklen_t address_len)
|
int connect(int socket, const struct sockaddr* address, socklen_t address_len)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_CONNECT, socket, address, address_len);
|
return syscall(SYS_CONNECT, socket, address, address_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +33,13 @@ int listen(int socket, int backlog)
|
||||||
|
|
||||||
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
|
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
|
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
|
ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
sys_recvfrom_t arguments {
|
sys_recvfrom_t arguments {
|
||||||
.socket = socket,
|
.socket = socket,
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
|
@ -47,11 +53,13 @@ ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags,
|
||||||
|
|
||||||
ssize_t send(int socket, const void* message, size_t length, int flags)
|
ssize_t send(int socket, const void* message, size_t length, int flags)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return sendto(socket, message, length, flags, nullptr, 0);
|
return sendto(socket, message, length, flags, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sendto(int socket, const void* message, size_t length, int flags, const struct sockaddr* dest_addr, socklen_t dest_len)
|
ssize_t sendto(int socket, const void* message, size_t length, int flags, const struct sockaddr* dest_addr, socklen_t dest_len)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
sys_sendto_t arguments {
|
sys_sendto_t arguments {
|
||||||
.socket = socket,
|
.socket = socket,
|
||||||
.message = message,
|
.message = message,
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
|
ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
for (int i = 0; i < iovcnt; i++)
|
for (int i = 0; i < iovcnt; i++)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +28,8 @@ ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
|
||||||
|
|
||||||
ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
|
ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
for (int i = 0; i < iovcnt; i++)
|
for (int i = 0; i < iovcnt; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
pid_t wait(int* stat_loc)
|
pid_t wait(int* stat_loc)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return waitpid(-1, stat_loc, 0);
|
return waitpid(-1, stat_loc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t waitpid(pid_t pid, int* stat_loc, int options)
|
pid_t waitpid(pid_t pid, int* stat_loc, int options)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return (pid_t)syscall(SYS_WAIT, pid, stat_loc, options);
|
return (pid_t)syscall(SYS_WAIT, pid, stat_loc, options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <BAN/Debug.h>
|
#include <BAN/Debug.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -64,9 +65,19 @@ int cfsetospeed(struct termios* termios, speed_t speed)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcdrain(int);
|
int tcdrain(int fd)
|
||||||
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
int tcflow(int, int);
|
dwarnln("TODO: tcdrain({})", fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tcflow(int fd, int action)
|
||||||
|
{
|
||||||
|
dwarnln("TODO: tcflow({}, {})", fd, action);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int tcflush(int fd, int queue_selector)
|
int tcflush(int fd, int queue_selector)
|
||||||
{
|
{
|
||||||
|
@ -81,7 +92,11 @@ int tcgetattr(int fildes, struct termios* termios)
|
||||||
|
|
||||||
pid_t tcgetsid(int);
|
pid_t tcgetsid(int);
|
||||||
|
|
||||||
int tcsendbreak(int, int);
|
int tcsendbreak(int fd, int duration)
|
||||||
|
{
|
||||||
|
dwarnln("FIXME: tcsendbreak({}, {})", fd, duration);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int tcsetattr(int fildes, int optional_actions, const struct termios* termios)
|
int tcsetattr(int fildes, int optional_actions, const struct termios* termios)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -20,6 +21,7 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
|
||||||
|
|
||||||
int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
|
int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_NANOSLEEP, rqtp, rmtp);
|
return syscall(SYS_NANOSLEEP, rqtp, rmtp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
||||||
self->cleanup_stack = nullptr;
|
self->cleanup_stack = nullptr;
|
||||||
self->id = syscall(SYS_PTHREAD_SELF);
|
self->id = syscall(SYS_PTHREAD_SELF);
|
||||||
self->errno_ = 0;
|
self->errno_ = 0;
|
||||||
|
self->cancel_type = PTHREAD_CANCEL_DEFERRED;
|
||||||
|
self->cancel_state = PTHREAD_CANCEL_ENABLE;
|
||||||
|
self->canceled = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -52,6 +55,9 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
||||||
.cleanup_stack = nullptr,
|
.cleanup_stack = nullptr,
|
||||||
.id = static_cast<pthread_t>(syscall(SYS_PTHREAD_SELF)),
|
.id = static_cast<pthread_t>(syscall(SYS_PTHREAD_SELF)),
|
||||||
.errno_ = 0,
|
.errno_ = 0,
|
||||||
|
.cancel_type = PTHREAD_CANCEL_DEFERRED,
|
||||||
|
.cancel_state = PTHREAD_CANCEL_ENABLE,
|
||||||
|
.canceled = false,
|
||||||
};
|
};
|
||||||
uthread.dtv[0] = 0;
|
uthread.dtv[0] = 0;
|
||||||
|
|
||||||
|
@ -108,16 +114,19 @@ long syscall(long syscall, ...)
|
||||||
|
|
||||||
int close(int fd)
|
int close(int fd)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_CLOSE, fd);
|
return syscall(SYS_CLOSE, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t read(int fildes, void* buf, size_t nbyte)
|
ssize_t read(int fildes, void* buf, size_t nbyte)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_READ, fildes, buf, nbyte);
|
return syscall(SYS_READ, fildes, buf, nbyte);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t write(int fildes, const void* buf, size_t nbyte)
|
ssize_t write(int fildes, const void* buf, size_t nbyte)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_WRITE, fildes, buf, nbyte);
|
return syscall(SYS_WRITE, fildes, buf, nbyte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,11 +142,13 @@ ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, si
|
||||||
|
|
||||||
ssize_t pread(int fildes, void* buf, size_t nbyte, off_t offset)
|
ssize_t pread(int fildes, void* buf, size_t nbyte, off_t offset)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_PREAD, fildes, buf, nbyte, offset);
|
return syscall(SYS_PREAD, fildes, buf, nbyte, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t pwrite(int fildes, const void* buf, size_t nbyte, off_t offset)
|
ssize_t pwrite(int fildes, const void* buf, size_t nbyte, off_t offset)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_PWRITE, fildes, buf, nbyte, offset);
|
return syscall(SYS_PWRITE, fildes, buf, nbyte, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +164,7 @@ int ftruncate(int fildes, off_t length)
|
||||||
|
|
||||||
int fsync(int fildes)
|
int fsync(int fildes)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
return syscall(SYS_FSYNC, fildes);
|
return syscall(SYS_FSYNC, fildes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +433,7 @@ int pipe(int fildes[2])
|
||||||
|
|
||||||
unsigned int sleep(unsigned int seconds)
|
unsigned int sleep(unsigned int seconds)
|
||||||
{
|
{
|
||||||
|
pthread_testcancel();
|
||||||
unsigned int ret = syscall(SYS_SLEEP, seconds);
|
unsigned int ret = syscall(SYS_SLEEP, seconds);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
errno = EINTR;
|
errno = EINTR;
|
||||||
|
@ -489,6 +502,15 @@ void syncsync(int should_block)
|
||||||
syscall(SYS_SYNC, should_block);
|
syscall(SYS_SYNC, should_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fdatasync(int fildes)
|
||||||
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
|
||||||
|
(void)fildes;
|
||||||
|
dprintln("TODO: fdatasync");
|
||||||
|
return syscall(SYS_SYNC, true);
|
||||||
|
}
|
||||||
|
|
||||||
int unlink(const char* path)
|
int unlink(const char* path)
|
||||||
{
|
{
|
||||||
return syscall(SYS_UNLINK, path);
|
return syscall(SYS_UNLINK, path);
|
||||||
|
|
Loading…
Reference in New Issue