diff options
author | Jonathan Mini <mini@FreeBSD.org> | 2002-09-16 19:52:52 +0000 |
---|---|---|
committer | Jonathan Mini <mini@FreeBSD.org> | 2002-09-16 19:52:52 +0000 |
commit | 255ab70cdf6eb0005e7494657f35d318f666de50 (patch) | |
tree | 19954471d255ce812e704c80bd079f406bc31378 /lib/libpthread | |
parent | 51f42932d165603bcfdafe9d900a392fd821a9eb (diff) | |
download | src-255ab70cdf6eb0005e7494657f35d318f666de50.tar.gz src-255ab70cdf6eb0005e7494657f35d318f666de50.zip |
Make libpthread KSE aware.
Reviewed by: deischen, julian
Approved by: -arch
Notes
Notes:
svn path=/head/; revision=103419
Diffstat (limited to 'lib/libpthread')
26 files changed, 135 insertions, 2395 deletions
diff --git a/lib/libpthread/thread/thr_cancel.c b/lib/libpthread/thread/thr_cancel.c index 9c7fc033d2bc..e4e0216253ae 100644 --- a/lib/libpthread/thread/thr_cancel.c +++ b/lib/libpthread/thread/thr_cancel.c @@ -44,20 +44,13 @@ _pthread_cancel(pthread_t pthread) break; case PS_SPINBLOCK: - case PS_FDR_WAIT: - case PS_FDW_WAIT: - case PS_POLL_WAIT: - case PS_SELECT_WAIT: /* Remove these threads from the work queue: */ if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0) PTHREAD_WORKQ_REMOVE(pthread); /* Fall through: */ - case PS_SIGTHREAD: case PS_SLEEP_WAIT: case PS_WAIT_WAIT: - case PS_SIGSUSPEND: - case PS_SIGWAIT: /* Interrupt and resume: */ pthread->interrupted = 1; pthread->cancelflags |= PTHREAD_CANCELLING; @@ -80,9 +73,6 @@ _pthread_cancel(pthread_t pthread) case PS_SUSPENDED: case PS_MUTEX_WAIT: case PS_COND_WAIT: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: /* * Threads in these states may be in queues. * In order to preserve queue integrity, the diff --git a/lib/libpthread/thread/thr_close.c b/lib/libpthread/thread/thr_close.c index c6634a563ba1..d03961bcd4c7 100644 --- a/lib/libpthread/thread/thr_close.c +++ b/lib/libpthread/thread/thr_close.c @@ -42,73 +42,12 @@ __weak_reference(__close, close); int -_close(int fd) -{ - int flags; - int ret; - struct stat sb; - struct fd_table_entry *entry; - - if ((fd == _thread_kern_pipe[0]) || (fd == _thread_kern_pipe[1])) { - /* - * Don't allow silly programs to close the kernel pipe. - */ - errno = EBADF; - ret = -1; - } - /* - * Lock the file descriptor while the file is closed and get - * the file descriptor status: - */ - else if (((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) && - ((ret = __sys_fstat(fd, &sb)) == 0)) { - /* - * Check if the file should be left as blocking. - * - * This is so that the file descriptors shared with a parent - * process aren't left set to non-blocking if the child - * closes them prior to exit. An example where this causes - * problems with /bin/sh is when a child closes stdin. - * - * Setting a file as blocking causes problems if a threaded - * parent accesses the file descriptor before the child exits. - * Once the threaded parent receives a SIGCHLD then it resets - * all of its files to non-blocking, and so it is then safe - * to access them. - * - * Pipes are not set to blocking when they are closed, as - * the parent and child will normally close the file - * descriptor of the end of the pipe that they are not - * using, which would then cause any reads to block - * indefinitely. - */ - if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) - && (_thread_fd_getflags(fd) & O_NONBLOCK) == 0) { - /* Get the current flags: */ - flags = __sys_fcntl(fd, F_GETFL, NULL); - /* Clear the nonblocking file descriptor flag: */ - __sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); - } - - /* XXX: Assumes well behaved threads. */ - /* XXX: Defer real close to avoid race condition */ - entry = _thread_fd_table[fd]; - _thread_fd_table[fd] = NULL; - free(entry); - - /* Close the file descriptor: */ - ret = __sys_close(fd); - } - return (ret); -} - -int __close(int fd) { int ret; _thread_enter_cancellation_point(); - ret = _close(fd); + ret = __sys_close(fd); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c index 5211cb02a508..0e72e96b6b1a 100644 --- a/lib/libpthread/thread/thr_create.c +++ b/lib/libpthread/thread/thr_create.c @@ -121,27 +121,12 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, */ new_thread->magic = PTHREAD_MAGIC; - /* Initialise the thread for signals: */ - new_thread->sigmask = curthread->sigmask; - new_thread->sigmask_seqno = 0; - - /* Initialize the signal frame: */ - new_thread->curframe = NULL; - - /* Initialise the jump buffer: */ - _setjmp(new_thread->ctx.jb); - - /* - * Set up new stack frame so that it looks like it - * returned from a longjmp() to the beginning of - * _thread_start(). - */ - SET_RETURN_ADDR_JB(new_thread->ctx.jb, _thread_start); - - /* The stack starts high and builds down: */ - SET_STACK_JB(new_thread->ctx.jb, - (long)new_thread->stack + pattr->stacksize_attr - - sizeof(double)); + /* Initialise the machine context: */ + getcontext(&new_thread->ctx); + new_thread->ctx.uc_stack.ss_sp = new_thread->stack; + new_thread->ctx.uc_stack.ss_size = + pattr->stacksize_attr; + makecontext(&new_thread->ctx, _thread_start, 1); /* Copy the thread attributes: */ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); @@ -182,8 +167,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->specific = NULL; new_thread->cleanup = NULL; new_thread->flags = 0; - new_thread->poll_data.nfds = 0; - new_thread->poll_data.fds = NULL; new_thread->continuation = NULL; /* @@ -224,18 +207,8 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, /* Return a pointer to the thread structure: */ (*thread) = new_thread; - if (f_gc != 0) { - /* Install the scheduling timer: */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = _clock_res_usec; - itimer.it_value = itimer.it_interval; - if (setitimer(_ITIMER_SCHED_TIMER, &itimer, - NULL) != 0) - PANIC("Cannot set interval timer"); - } - /* Schedule the new user thread: */ - _thread_kern_sched(NULL); + _thread_kern_sched(); /* * Start a garbage collector thread @@ -257,7 +230,7 @@ _thread_start(void) { struct pthread *curthread = _get_curthread(); - /* We just left the scheduler via longjmp: */ + /* We just left the scheduler via swapcontext: */ _thread_kern_in_sched = 0; /* Run the current thread's start routine with argument: */ diff --git a/lib/libpthread/thread/thr_exit.c b/lib/libpthread/thread/thr_exit.c index 88535d047e6b..96d288e35958 100644 --- a/lib/libpthread/thread/thr_exit.c +++ b/lib/libpthread/thread/thr_exit.c @@ -45,42 +45,6 @@ __weak_reference(_pthread_exit, pthread_exit); -void _exit(int status) -{ - int flags; - int i; - struct itimerval itimer; - - /* Disable the interval timer: */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = 0; - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = 0; - setitimer(_ITIMER_SCHED_TIMER, &itimer, NULL); - - /* Close the pthread kernel pipe: */ - __sys_close(_thread_kern_pipe[0]); - __sys_close(_thread_kern_pipe[1]); - - /* - * Enter a loop to set all file descriptors to blocking - * if they were not created as non-blocking: - */ - for (i = 0; i < _thread_dtablesize; i++) { - /* Check if this file descriptor is in use: */ - if (_thread_fd_table[i] != NULL && - (_thread_fd_getflags(i) & O_NONBLOCK) == 0) { - /* Get the current flags: */ - flags = __sys_fcntl(i, F_GETFL, NULL); - /* Clear the nonblocking file descriptor flag: */ - __sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK); - } - } - - /* Call the _exit syscall: */ - __sys_exit(status); -} - void _thread_exit(char *fname, int lineno, char *string) { @@ -120,9 +84,6 @@ _thread_exit_cleanup(void) * internal to the threads library, including file and fd locks, * are not visible to the application and need to be released. */ - /* Unlock all owned fd locks: */ - _thread_fd_unlock_owned(curthread); - /* Unlock all private mutexes: */ _mutex_unlock_private(curthread); @@ -163,12 +124,6 @@ _pthread_exit(void *status) _thread_cleanupspecific(); } - /* Free thread-specific poll_data structure, if allocated: */ - if (curthread->poll_data.fds != NULL) { - free(curthread->poll_data.fds); - curthread->poll_data.fds = NULL; - } - /* * Lock the garbage collector mutex to ensure that the garbage * collector is not using the dead thread list. diff --git a/lib/libpthread/thread/thr_fcntl.c b/lib/libpthread/thread/thr_fcntl.c index 9e78d07fbdf8..33a1c2f61761 100644 --- a/lib/libpthread/thread/thr_fcntl.c +++ b/lib/libpthread/thread/thr_fcntl.c @@ -40,108 +40,6 @@ __weak_reference(__fcntl, fcntl); int -_fcntl(int fd, int cmd,...) -{ - int flags = 0; - int nonblock; - int oldfd; - int ret; - va_list ap; - - /* Lock the file descriptor: */ - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { - /* Initialise the variable argument list: */ - va_start(ap, cmd); - - /* Process according to file control command type: */ - switch (cmd) { - /* Duplicate a file descriptor: */ - case F_DUPFD: - /* - * Get the file descriptor that the caller wants to - * use: - */ - oldfd = va_arg(ap, int); - - /* Initialise the file descriptor table entry: */ - if ((ret = __sys_fcntl(fd, cmd, oldfd)) < 0) { - } - /* Initialise the file descriptor table entry: */ - else if (_thread_fd_table_init(ret) != 0) { - /* Quietly close the file: */ - __sys_close(ret); - - /* Reset the file descriptor: */ - ret = -1; - } else { - /* - * Save the file open flags so that they can - * be checked later: - */ - _thread_fd_setflags(ret, - _thread_fd_getflags(fd)); - } - break; - case F_SETFD: - flags = va_arg(ap, int); - ret = __sys_fcntl(fd, cmd, flags); - break; - case F_GETFD: - ret = __sys_fcntl(fd, cmd, 0); - break; - case F_GETFL: - ret = _thread_fd_getflags(fd); - break; - case F_SETFL: - /* - * Get the file descriptor flags passed by the - * caller: - */ - flags = va_arg(ap, int); - - /* - * Check if the user wants a non-blocking file - * descriptor: - */ - nonblock = flags & O_NONBLOCK; - - /* Set the file descriptor flags: */ - if ((ret = __sys_fcntl(fd, cmd, flags | O_NONBLOCK)) != 0) { - - /* Get the flags so that we behave like the kernel: */ - } else if ((flags = __sys_fcntl(fd, - F_GETFL, 0)) == -1) { - /* Error getting flags: */ - ret = -1; - - /* - * Check if the file descriptor is non-blocking - * with respect to the user: - */ - } else if (nonblock) - /* A non-blocking descriptor: */ - _thread_fd_setflags(fd, flags | O_NONBLOCK); - else - /* Save the flags: */ - _thread_fd_setflags(fd, flags & ~O_NONBLOCK); - break; - default: - /* Might want to make va_arg use a union */ - ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); - break; - } - - /* Free variable arguments: */ - va_end(ap); - - /* Unlock the file descriptor: */ - _FD_UNLOCK(fd, FD_RDWR); - } - /* Return the completion status: */ - return (ret); -} - -int __fcntl(int fd, int cmd,...) { int ret; @@ -154,14 +52,14 @@ __fcntl(int fd, int cmd,...) case F_DUPFD: case F_SETFD: case F_SETFL: - ret = _fcntl(fd, cmd, va_arg(ap, int)); + ret = __sys_fcntl(fd, cmd, va_arg(ap, int)); break; case F_GETFD: case F_GETFL: - ret = _fcntl(fd, cmd); + ret = __sys_fcntl(fd, cmd); break; default: - ret = _fcntl(fd, cmd, va_arg(ap, void *)); + ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); } va_end(ap); diff --git a/lib/libpthread/thread/thr_fork.c b/lib/libpthread/thread/thr_fork.c index 0f172917b2b8..5bb64f746732 100644 --- a/lib/libpthread/thread/thr_fork.c +++ b/lib/libpthread/thread/thr_fork.c @@ -63,44 +63,8 @@ _fork(void) if ((ret = __sys_fork()) != 0) { /* Parent process or error. Nothing to do here. */ } else { - /* Close the pthread kernel pipe: */ - __sys_close(_thread_kern_pipe[0]); - __sys_close(_thread_kern_pipe[1]); - - /* Reset signals pending for the running thread: */ - sigemptyset(&curthread->sigpend); - - /* - * Create a pipe that is written to by the signal handler to - * prevent signals being missed in calls to - * __sys_select: - */ - if (__sys_pipe(_thread_kern_pipe) != 0) { - /* Cannot create pipe, so abort: */ - PANIC("Cannot create pthread kernel pipe for forked process"); - } - /* Get the flags for the read pipe: */ - else if ((flags = __sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) { - /* Abort this application: */ - abort(); - } - /* Make the read pipe non-blocking: */ - else if (__sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) { - /* Abort this application: */ - abort(); - } - /* Get the flags for the write pipe: */ - else if ((flags = __sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) { - /* Abort this application: */ - abort(); - } - /* Make the write pipe non-blocking: */ - else if (__sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { - /* Abort this application: */ - abort(); - } /* Reinitialize the GC mutex: */ - else if (_mutex_reinit(&_gc_mutex) != 0) { + if (_mutex_reinit(&_gc_mutex) != 0) { /* Abort this application: */ PANIC("Cannot initialize GC mutex for forked process"); } @@ -180,32 +144,8 @@ _fork(void) /* No spinlocks yet: */ _spinblock_count = 0; - /* Don't queue signals yet: */ - _queue_signals = 0; - /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; - - /* Clear out any locks in the file descriptor table: */ - for (i = 0; i < _thread_dtablesize; i++) { - if (_thread_fd_table[i] != NULL) { - /* Initialise the file locks: */ - memset(&_thread_fd_table[i]->lock, 0, - sizeof(_thread_fd_table[i]->lock)); - _thread_fd_table[i]->r_owner = NULL; - _thread_fd_table[i]->w_owner = NULL; - _thread_fd_table[i]->r_fname = NULL; - _thread_fd_table[i]->w_fname = NULL; - _thread_fd_table[i]->r_lineno = 0;; - _thread_fd_table[i]->w_lineno = 0;; - _thread_fd_table[i]->r_lockcount = 0;; - _thread_fd_table[i]->w_lockcount = 0;; - - /* Initialise the read/write queues: */ - TAILQ_INIT(&_thread_fd_table[i]->r_queue); - TAILQ_INIT(&_thread_fd_table[i]->w_queue); - } - } } } @@ -236,8 +176,5 @@ free_thread_resources(struct pthread *thread) if (thread->specific != NULL) free(thread->specific); - if (thread->poll_data.fds != NULL) - free(thread->poll_data.fds); - free(thread); } diff --git a/lib/libpthread/thread/thr_fsync.c b/lib/libpthread/thread/thr_fsync.c index 608e8b055b56..0ede52952dd8 100644 --- a/lib/libpthread/thread/thr_fsync.c +++ b/lib/libpthread/thread/thr_fsync.c @@ -38,24 +38,12 @@ __weak_reference(__fsync, fsync); int -_fsync(int fd) -{ - int ret; - - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { - ret = __sys_fsync(fd); - _FD_UNLOCK(fd, FD_RDWR); - } - return (ret); -} - -int __fsync(int fd) { int ret; _thread_enter_cancellation_point(); - ret = _fsync(fd); + ret = __sys_fsync(fd); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_info.c b/lib/libpthread/thread/thr_info.c index 11b02f39f478..9ade1574f5ec 100644 --- a/lib/libpthread/thread/thr_info.c +++ b/lib/libpthread/thread/thr_info.c @@ -56,20 +56,10 @@ struct s_thread_info { /* Static variables: */ static const struct s_thread_info thread_info[] = { {PS_RUNNING , "Running"}, - {PS_SIGTHREAD , "Waiting on signal thread"}, {PS_MUTEX_WAIT , "Waiting on a mutex"}, {PS_COND_WAIT , "Waiting on a condition variable"}, - {PS_FDLR_WAIT , "Waiting for a file read lock"}, - {PS_FDLW_WAIT , "Waiting for a file write lock"}, - {PS_FDR_WAIT , "Waiting for read"}, - {PS_FDW_WAIT , "Waiting for write"}, - {PS_FILE_WAIT , "Waiting for FILE lock"}, - {PS_POLL_WAIT , "Waiting on poll"}, - {PS_SELECT_WAIT , "Waiting on select"}, {PS_SLEEP_WAIT , "Sleeping"}, {PS_WAIT_WAIT , "Waiting process"}, - {PS_SIGSUSPEND , "Suspended, waiting for a signal"}, - {PS_SIGWAIT , "Waiting for a signal"}, {PS_SPINBLOCK , "Waiting for a spinlock"}, {PS_JOIN , "Waiting to join"}, {PS_SUSPENDED , "Suspended"}, @@ -169,34 +159,6 @@ _thread_dump_info(void) } } - /* Output a header for file descriptors: */ - snprintf(s, sizeof(s), "\n\n=============\nFILE DESCRIPTOR " - "TABLE (table size %d)\n\n", _thread_dtablesize); - __sys_write(fd, s, strlen(s)); - - /* Enter a loop to report file descriptor lock usage: */ - for (i = 0; i < _thread_dtablesize; i++) { - /* - * Check if memory is allocated for this file - * descriptor: - */ - if (_thread_fd_table[i] != NULL) { - /* Report the file descriptor lock status: */ - snprintf(s, sizeof(s), - "fd[%3d] read owner %p count %d [%s:%d]\n" - " write owner %p count %d [%s:%d]\n", - i, _thread_fd_table[i]->r_owner, - _thread_fd_table[i]->r_lockcount, - _thread_fd_table[i]->r_fname, - _thread_fd_table[i]->r_lineno, - _thread_fd_table[i]->w_owner, - _thread_fd_table[i]->w_lockcount, - _thread_fd_table[i]->w_fname, - _thread_fd_table[i]->w_lineno); - __sys_write(fd, s, strlen(s)); - } - } - /* Close the dump file: */ __sys_close(fd); } @@ -237,33 +199,6 @@ dump_thread(int fd, pthread_t pthread, int long_version) } /* Process according to thread state: */ switch (pthread->state) { - /* File descriptor read lock wait: */ - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FDR_WAIT: - case PS_FDW_WAIT: - /* Write the lock details: */ - snprintf(s, sizeof(s), "fd %d[%s:%d]", - pthread->data.fd.fd, - pthread->data.fd.fname, - pthread->data.fd.branch); - __sys_write(fd, s, strlen(s)); - snprintf(s, sizeof(s), "owner %pr/%pw\n", - _thread_fd_table[pthread->data.fd.fd]->r_owner, - _thread_fd_table[pthread->data.fd.fd]->w_owner); - __sys_write(fd, s, strlen(s)); - break; - case PS_SIGWAIT: - snprintf(s, sizeof(s), "sigmask (hi)"); - __sys_write(fd, s, strlen(s)); - for (i = _SIG_WORDS - 1; i >= 0; i--) { - snprintf(s, sizeof(s), "%08x\n", - pthread->sigmask.__bits[i]); - __sys_write(fd, s, strlen(s)); - } - snprintf(s, sizeof(s), "(lo)\n"); - __sys_write(fd, s, strlen(s)); - break; /* * Trap other states that are not explicitly * coded to dump information: diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c index ba306a6b5ce0..9f6a533bc8eb 100644 --- a/lib/libpthread/thread/thr_init.c +++ b/lib/libpthread/thread/thr_init.c @@ -56,7 +56,6 @@ #include <errno.h> #include <fcntl.h> #include <paths.h> -#include <poll.h> #include <pthread.h> #include <signal.h> #include <stdio.h> @@ -163,7 +162,6 @@ _thread_init(void) int sched_stack_size; /* Size of scheduler stack. */ struct clockinfo clockinfo; - struct sigaction act; _pthread_page_size = getpagesize(); _pthread_guard_default = getpagesize(); @@ -209,57 +207,9 @@ _thread_init(void) PANIC("Can't dup2"); } - /* Get the standard I/O flags before messing with them : */ - for (i = 0; i < 3; i++) { - if (((_pthread_stdio_flags[i] = - __sys_fcntl(i, F_GETFL, NULL)) == -1) && - (errno != EBADF)) - PANIC("Cannot get stdio flags"); - } - - /* - * Create a pipe that is written to by the signal handler to prevent - * signals being missed in calls to _select: - */ - if (__sys_pipe(_thread_kern_pipe) != 0) { - /* Cannot create pipe, so abort: */ - PANIC("Cannot create kernel pipe"); - } - - /* - * Make sure the pipe does not get in the way of stdio: - */ - for (i = 0; i < 2; i++) { - if (_thread_kern_pipe[i] < 3) { - fd = __sys_fcntl(_thread_kern_pipe[i], F_DUPFD, 3); - if (fd == -1) - PANIC("Cannot create kernel pipe"); - __sys_close(_thread_kern_pipe[i]); - _thread_kern_pipe[i] = fd; - } - } - /* Get the flags for the read pipe: */ - if ((flags = __sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) { - /* Abort this application: */ - PANIC("Cannot get kernel read pipe flags"); - } - /* Make the read pipe non-blocking: */ - else if (__sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) { - /* Abort this application: */ - PANIC("Cannot make kernel read pipe non-blocking"); - } - /* Get the flags for the write pipe: */ - else if ((flags = __sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) { - /* Abort this application: */ - PANIC("Cannot get kernel write pipe flags"); - } - /* Make the write pipe non-blocking: */ - else if (__sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { - /* Abort this application: */ - PANIC("Cannot get kernel write pipe flags"); - } /* Allocate and initialize the ready queue: */ - else if (_pq_alloc(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_LAST_PRIORITY) != 0) { + if (_pq_alloc(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_LAST_PRIORITY) != + 0) { /* Abort this application: */ PANIC("Cannot allocate priority ready queue."); } @@ -312,15 +262,19 @@ _thread_init(void) /* Set the main thread stack pointer. */ _thread_initial->stack = _usrstack - PTHREAD_STACK_INITIAL; - /* Set the stack attributes: */ + /* Set the stack attributes. */ _thread_initial->attr.stackaddr_attr = _thread_initial->stack; _thread_initial->attr.stacksize_attr = PTHREAD_STACK_INITIAL; /* Setup the context for the scheduler: */ - _setjmp(_thread_kern_sched_jb); - SET_STACK_JB(_thread_kern_sched_jb, _thread_kern_sched_stack + - sched_stack_size - sizeof(double)); - SET_RETURN_ADDR_JB(_thread_kern_sched_jb, _thread_kern_scheduler); + getcontext(&_thread_kern_sched_ctx); + _thread_kern_sched_ctx.uc_stack.ss_sp = + _thread_kern_sched_stack; + _thread_kern_sched_ctx.uc_stack.ss_size = sched_stack_size; + makecontext(&_thread_kern_sched_ctx, _thread_kern_scheduler, 1); + + /* Block all signals to the scheduler's context. */ + sigfillset(&_thread_kern_sched_ctx.uc_sigmask); /* * Write a magic value to the thread structure @@ -332,6 +286,11 @@ _thread_init(void) _thread_initial->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED; + /* Setup the context for initial thread. */ + getcontext(&_thread_initial->ctx); + _thread_kern_sched_ctx.uc_stack.ss_sp = _thread_initial->stack; + _thread_kern_sched_ctx.uc_stack.ss_size = PTHREAD_STACK_INITIAL; + /* Default the priority of the initial thread: */ _thread_initial->base_priority = PTHREAD_DEFAULT_PRIORITY; _thread_initial->active_priority = PTHREAD_DEFAULT_PRIORITY; @@ -357,14 +316,8 @@ _thread_init(void) /* Initialize last active: */ _thread_initial->last_active = (long) _sched_ticks; - /* Initialize the initial context: */ - _thread_initial->curframe = NULL; - /* Initialise the rest of the fields: */ - _thread_initial->poll_data.nfds = 0; - _thread_initial->poll_data.fds = NULL; _thread_initial->sig_defer_count = 0; - _thread_initial->yield_on_sig_undefer = 0; _thread_initial->specific = NULL; _thread_initial->cleanup = NULL; _thread_initial->flags = 0; @@ -373,57 +326,6 @@ _thread_init(void) TAILQ_INSERT_HEAD(&_thread_list, _thread_initial, tle); _set_curthread(_thread_initial); - /* Initialise the global signal action structure: */ - sigfillset(&act.sa_mask); - act.sa_handler = (void (*) ()) _thread_sig_handler; - act.sa_flags = SA_SIGINFO | SA_ONSTACK; - - /* Clear pending signals for the process: */ - sigemptyset(&_process_sigpending); - - /* Clear the signal queue: */ - memset(_thread_sigq, 0, sizeof(_thread_sigq)); - - /* Enter a loop to get the existing signal status: */ - for (i = 1; i < NSIG; i++) { - /* Check for signals which cannot be trapped: */ - if (i == SIGKILL || i == SIGSTOP) { - } - - /* Get the signal handler details: */ - else if (__sys_sigaction(i, NULL, - &_thread_sigact[i - 1]) != 0) { - /* - * Abort this process if signal - * initialisation fails: - */ - PANIC("Cannot read signal handler info"); - } - - /* Initialize the SIG_DFL dummy handler count. */ - _thread_dfl_count[i] = 0; - } - - /* - * Install the signal handler for the most important - * signals that the user-thread kernel needs. Actually - * SIGINFO isn't really needed, but it is nice to have. - */ - if (__sys_sigaction(_SCHED_SIGNAL, &act, NULL) != 0 || - __sys_sigaction(SIGINFO, &act, NULL) != 0 || - __sys_sigaction(SIGCHLD, &act, NULL) != 0) { - /* - * Abort this process if signal initialisation fails: - */ - PANIC("Cannot initialise signal handler"); - } - _thread_sigact[_SCHED_SIGNAL - 1].sa_flags = SA_SIGINFO; - _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO; - _thread_sigact[SIGCHLD - 1].sa_flags = SA_SIGINFO; - - /* Get the process signal mask: */ - __sys_sigprocmask(SIG_SETMASK, NULL, &_process_sigmask); - /* Get the kernel clockrate: */ mib[0] = CTL_KERN; mib[1] = KERN_CLOCKRATE; @@ -432,50 +334,6 @@ _thread_init(void) _clock_res_usec = clockinfo.tick > CLOCK_RES_USEC_MIN ? clockinfo.tick : CLOCK_RES_USEC_MIN; - /* Get the table size: */ - if ((_thread_dtablesize = getdtablesize()) < 0) { - /* - * Cannot get the system defined table size, so abort - * this process. - */ - PANIC("Cannot get dtablesize"); - } - /* Allocate memory for the file descriptor table: */ - if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) { - /* Avoid accesses to file descriptor table on exit: */ - _thread_dtablesize = 0; - - /* - * Cannot allocate memory for the file descriptor - * table, so abort this process. - */ - PANIC("Cannot allocate memory for file descriptor table"); - } - /* Allocate memory for the pollfd table: */ - if ((_thread_pfd_table = (struct pollfd *) malloc(sizeof(struct pollfd) * _thread_dtablesize)) == NULL) { - /* - * Cannot allocate memory for the file descriptor - * table, so abort this process. - */ - PANIC("Cannot allocate memory for pollfd table"); - } else { - /* - * Enter a loop to initialise the file descriptor - * table: - */ - for (i = 0; i < _thread_dtablesize; i++) { - /* Initialise the file descriptor table: */ - _thread_fd_table[i] = NULL; - } - - /* Initialize stdio file descriptor table entries: */ - for (i = 0; i < 3; i++) { - if ((_thread_fd_table_init(i) != 0) && - (errno != EBADF)) - PANIC("Cannot initialize stdio file " - "descriptor table entry"); - } - } } /* Initialise the garbage collector mutex and condition variable. */ diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index 5b196903d689..36ed8d8fb7cb 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -38,7 +38,6 @@ #include <stdarg.h> #include <string.h> #include <unistd.h> -#include <setjmp.h> #include <sys/param.h> #include <sys/types.h> #include <sys/signalvar.h> @@ -60,7 +59,7 @@ /* Static function prototype definitions: */ static void -thread_kern_poll(int wait_reqd); +thread_kern_idle(void); static void dequeue_signals(void); @@ -70,37 +69,9 @@ thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in); /* Static variables: */ static int last_tick = 0; -static int called_from_handler = 0; - -/* - * This is called when a signal handler finishes and wants to - * return to a previous frame. - */ -void -_thread_kern_sched_frame(struct pthread_signal_frame *psf) -{ - struct pthread *curthread = _get_curthread(); - - /* - * Flag the pthread kernel as executing scheduler code - * to avoid a signal from interrupting this execution and - * corrupting the (soon-to-be) current frame. - */ - _thread_kern_in_sched = 1; - - /* Restore the signal frame: */ - _thread_sigframe_restore(curthread, psf); - - /* The signal mask was restored; check for any pending signals: */ - curthread->check_pending = 1; - - /* Switch to the thread scheduler: */ - ___longjmp(_thread_kern_sched_jb, 1); -} - void -_thread_kern_sched(ucontext_t *ucp) +_thread_kern_sched(void) { struct pthread *curthread = _get_curthread(); @@ -111,78 +82,40 @@ _thread_kern_sched(ucontext_t *ucp) */ _thread_kern_in_sched = 1; - /* Check if this function was called from the signal handler: */ - if (ucp != NULL) { - /* XXX - Save FP registers? */ - FP_SAVE_UC(ucp); - called_from_handler = 1; - DBG_MSG("Entering scheduler due to signal\n"); - } - - /* Save the state of the current thread: */ - if (_setjmp(curthread->ctx.jb) != 0) { - DBG_MSG("Returned from ___longjmp, thread %p\n", - curthread); - /* - * This point is reached when a longjmp() is called - * to restore the state of a thread. - * - * This is the normal way out of the scheduler. - */ - _thread_kern_in_sched = 0; + /* Switch into the scheduler's context. */ + swapcontext(&curthread->ctx, &_thread_kern_sched_ctx); + DBG_MSG("Returned from swapcontext, thread %p\n", curthread); - if (curthread->sig_defer_count == 0) { - if (((curthread->cancelflags & - PTHREAD_AT_CANCEL_POINT) == 0) && - ((curthread->cancelflags & - PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) - /* - * Cancellations override signals. - * - * Stick a cancellation point at the - * start of each async-cancellable - * thread's resumption. - * - * We allow threads woken at cancel - * points to do their own checks. - */ - pthread_testcancel(); - } - - if (_sched_switch_hook != NULL) { - /* Run the installed switch hook: */ - thread_run_switch_hook(_last_user_thread, curthread); - } - if (ucp == NULL) - return; - else { - /* XXX - Restore FP registers? */ - FP_RESTORE_UC(ucp); + /* + * This point is reached when swapcontext() is called + * to restore the state of a thread. + * + * This is the normal way out of the scheduler. + */ + _thread_kern_in_sched = 0; + if (curthread->sig_defer_count == 0) { + if (((curthread->cancelflags & + PTHREAD_AT_CANCEL_POINT) == 0) && + ((curthread->cancelflags & + PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) /* - * Set the process signal mask in the context; it - * could have changed by the handler. + * Stick a cancellation point at the + * start of each async-cancellable + * thread's resumption. + * + * We allow threads woken at cancel + * points to do their own checks. */ - ucp->uc_sigmask = _process_sigmask; - - /* Resume the interrupted thread: */ - __sys_sigreturn(ucp); - } + pthread_testcancel(); } - /* Switch to the thread scheduler: */ - ___longjmp(_thread_kern_sched_jb, 1); -} - -void -_thread_kern_sched_sig(void) -{ - struct pthread *curthread = _get_curthread(); - curthread->check_pending = 1; - _thread_kern_sched(NULL); + if (_sched_switch_hook != NULL) { + /* Run the installed switch hook: */ + thread_run_switch_hook(_last_user_thread, curthread); + } } - void _thread_kern_scheduler(void) { @@ -193,48 +126,28 @@ _thread_kern_scheduler(void) unsigned int current_tick; int add_to_prioq; - /* If the currently running thread is a user thread, save it: */ - if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0) - _last_user_thread = curthread; - - if (called_from_handler != 0) { - called_from_handler = 0; - - /* - * We were called from a signal handler; restore the process - * signal mask. - */ - if (__sys_sigprocmask(SIG_SETMASK, - &_process_sigmask, NULL) != 0) - PANIC("Unable to restore process mask after signal"); - } - /* * Enter a scheduling loop that finds the next thread that is * ready to run. This loop completes when there are no more threads - * in the global list or when a thread has its state restored by - * either a sigreturn (if the state was saved as a sigcontext) or a - * longjmp (if the state was saved by a setjmp). + * in the global list. It is interrupted each time a thread is + * scheduled, but will continue when we return. */ while (!(TAILQ_EMPTY(&_thread_list))) { + + /* If the currently running thread is a user thread, save it: */ + if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0) + _last_user_thread = curthread; + /* Get the current time of day: */ GET_CURRENT_TOD(tv); TIMEVAL_TO_TIMESPEC(&tv, &ts); current_tick = _sched_ticks; - /* - * Protect the scheduling queues from access by the signal - * handler. - */ - _queue_signals = 1; add_to_prioq = 0; - if (curthread != &_thread_kern_thread) { /* * This thread no longer needs to yield the CPU. */ - curthread->yield_on_sig_undefer = 0; - if (curthread->state != PS_RUNNING) { /* * Save the current time as the time that the @@ -278,14 +191,8 @@ _thread_kern_scheduler(void) * operations or timeouts: */ case PS_DEADLOCK: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: - case PS_SIGSUSPEND: - case PS_SIGTHREAD: - case PS_SIGWAIT: case PS_WAIT_WAIT: /* No timeouts for these states: */ curthread->wakeup_time.tv_sec = -1; @@ -318,62 +225,9 @@ _thread_kern_scheduler(void) _spinblock_count++; /* FALLTHROUGH */ - case PS_FDR_WAIT: - case PS_FDW_WAIT: - case PS_POLL_WAIT: - case PS_SELECT_WAIT: - /* Restart the time slice: */ - curthread->slice_usec = -1; - - /* Insert into the waiting queue: */ - PTHREAD_WAITQ_INSERT(curthread); - - /* Insert into the work queue: */ - PTHREAD_WORKQ_INSERT(curthread); - break; - } - - /* - * Are there pending signals for this thread? - * - * This check has to be performed after the thread - * has been placed in the queue(s) appropriate for - * its state. The process of adding pending signals - * can change a threads state, which in turn will - * attempt to add or remove the thread from any - * scheduling queue to which it belongs. - */ - if (curthread->check_pending != 0) { - curthread->check_pending = 0; - _thread_sig_check_pending(curthread); } } - /* - * Avoid polling file descriptors if there are none - * waiting: - */ - if (TAILQ_EMPTY(&_workq) != 0) { - } - /* - * Poll file descriptors only if a new scheduling signal - * has occurred or if we have no more runnable threads. - */ - else if (((current_tick = _sched_ticks) != last_tick) || - ((curthread->state != PS_RUNNING) && - (PTHREAD_PRIOQ_FIRST() == NULL))) { - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - - /* - * Poll file descriptors to update the state of threads - * waiting on file I/O where data may be available: - */ - thread_kern_poll(0); - - /* Protect the scheduling queues: */ - _queue_signals = 1; - } last_tick = current_tick; /* @@ -389,25 +243,16 @@ _thread_kern_scheduler(void) (pthread->wakeup_time.tv_sec < ts.tv_sec) || ((pthread->wakeup_time.tv_sec == ts.tv_sec) && (pthread->wakeup_time.tv_nsec <= ts.tv_nsec)))) { - switch (pthread->state) { - case PS_POLL_WAIT: - case PS_SELECT_WAIT: - /* Return zero file descriptors ready: */ - pthread->data.poll_data->nfds = 0; - /* FALLTHROUGH */ - default: - /* - * Remove this thread from the waiting queue - * (and work queue if necessary) and place it - * in the ready queue. - */ - PTHREAD_WAITQ_CLEARACTIVE(); - if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread, PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - break; - } + /* + * Remove this thread from the waiting queue + * (and work queue if necessary) and place it + * in the ready queue. + */ + PTHREAD_WAITQ_CLEARACTIVE(); + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); /* * Flag the timeout in the thread structure: */ @@ -483,14 +328,11 @@ _thread_kern_scheduler(void) DBG_MSG("No runnable threads, using kernel thread %p\n", curthread); - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - /* * There are no threads ready to run, so wait until * something happens that changes this condition: */ - thread_kern_poll(1); + thread_kern_idle(); /* * This process' usage will likely be very small @@ -503,54 +345,13 @@ _thread_kern_scheduler(void) gettimeofday((struct timeval *) &_sched_tod, NULL); /* Check once more for a runnable thread: */ - _queue_signals = 1; pthread_h = PTHREAD_PRIOQ_FIRST(); - _queue_signals = 0; } if (pthread_h != NULL) { /* Remove the thread from the ready queue: */ PTHREAD_PRIOQ_REMOVE(pthread_h); - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - - /* - * Check for signals queued while the scheduling - * queues were protected: - */ - while (_sigq_check_reqd != 0) { - /* Clear before handling queued signals: */ - _sigq_check_reqd = 0; - - /* Protect the scheduling queues again: */ - _queue_signals = 1; - - dequeue_signals(); - - /* - * Check for a higher priority thread that - * became runnable due to signal handling. - */ - if (((pthread = PTHREAD_PRIOQ_FIRST()) != NULL) && - (pthread->active_priority > pthread_h->active_priority)) { - /* Remove the thread from the ready queue: */ - PTHREAD_PRIOQ_REMOVE(pthread); - - /* - * Insert the lower priority thread - * at the head of its priority list: - */ - PTHREAD_PRIOQ_INSERT_HEAD(pthread_h); - - /* There's a new thread in town: */ - pthread_h = pthread; - } - - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - } - /* Make the selected thread the current thread: */ _set_curthread(pthread_h); curthread = pthread_h; @@ -584,13 +385,7 @@ _thread_kern_scheduler(void) /* * Continue the thread at its current frame: */ -#if NOT_YET - _setcontext(&curthread->ctx.uc); -#else - ___longjmp(curthread->ctx.jb, 1); -#endif - /* This point should not be reached. */ - PANIC("Thread has returned from sigreturn or longjmp"); + swapcontext(&_thread_kern_sched_ctx, &curthread->ctx); } } @@ -610,19 +405,13 @@ _thread_kern_sched_state(enum pthread_state state, char *fname, int lineno) */ _thread_kern_in_sched = 1; - /* - * Prevent the signal handler from fiddling with this thread - * before its state is set and is placed into the proper queue. - */ - _queue_signals = 1; - /* Change the state of the current thread: */ curthread->state = state; curthread->fname = fname; curthread->lineno = lineno; /* Schedule the next thread that is ready: */ - _thread_kern_sched(NULL); + _thread_kern_sched(); } void @@ -638,13 +427,6 @@ _thread_kern_sched_state_unlock(enum pthread_state state, */ _thread_kern_in_sched = 1; - /* - * Prevent the signal handler from fiddling with this thread - * before its state is set and it is placed into the proper - * queue(s). - */ - _queue_signals = 1; - /* Change the state of the current thread: */ curthread->state = state; curthread->fname = fname; @@ -653,13 +435,12 @@ _thread_kern_sched_state_unlock(enum pthread_state state, _SPINUNLOCK(lock); /* Schedule the next thread that is ready: */ - _thread_kern_sched(NULL); + _thread_kern_sched(); } static void -thread_kern_poll(int wait_reqd) +thread_kern_idle() { - int count = 0; int i, found; int kern_pipe_added = 0; int nfds = 0; @@ -668,57 +449,35 @@ thread_kern_poll(int wait_reqd) struct timespec ts; struct timeval tv; - /* Check if the caller wants to wait: */ - if (wait_reqd == 0) { - timeout_ms = 0; - } - else { - /* Get the current time of day: */ - GET_CURRENT_TOD(tv); - TIMEVAL_TO_TIMESPEC(&tv, &ts); + /* Get the current time of day: */ + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, &ts); - _queue_signals = 1; - pthread = TAILQ_FIRST(&_waitingq); - _queue_signals = 0; + pthread = TAILQ_FIRST(&_waitingq); - if ((pthread == NULL) || (pthread->wakeup_time.tv_sec == -1)) { - /* - * Either there are no threads in the waiting queue, - * or there are no threads that can timeout. - */ - timeout_ms = INFTIM; - } - else if (pthread->wakeup_time.tv_sec - ts.tv_sec > 60000) - /* Limit maximum timeout to prevent rollover. */ - timeout_ms = 60000; - else { - /* - * Calculate the time left for the next thread to - * timeout: - */ - timeout_ms = ((pthread->wakeup_time.tv_sec - ts.tv_sec) * - 1000) + ((pthread->wakeup_time.tv_nsec - ts.tv_nsec) / - 1000000); - /* - * Don't allow negative timeouts: - */ - if (timeout_ms < 0) - timeout_ms = 0; - } + if ((pthread == NULL) || (pthread->wakeup_time.tv_sec == -1)) { + /* + * Either there are no threads in the waiting queue, + * or there are no threads that can timeout. + */ + PANIC("Would idle forever"); } - - /* Protect the scheduling queues: */ - _queue_signals = 1; - - /* - * Check to see if the signal queue needs to be walked to look - * for threads awoken by a signal while in the scheduler. - */ - if (_sigq_check_reqd != 0) { - /* Reset flag before handling queued signals: */ - _sigq_check_reqd = 0; - - dequeue_signals(); + else if (pthread->wakeup_time.tv_sec - ts.tv_sec > 60000) + /* Limit maximum timeout to prevent rollover. */ + timeout_ms = 60000; + else { + /* + * Calculate the time left for the next thread to + * timeout: + */ + timeout_ms = ((pthread->wakeup_time.tv_sec - ts.tv_sec) * + 1000) + ((pthread->wakeup_time.tv_nsec - ts.tv_nsec) / + 1000000); + /* + * Only idle if we would be. + */ + if (timeout_ms <= 0) + return; } /* @@ -733,219 +492,11 @@ thread_kern_poll(int wait_reqd) } /* - * Form the poll table: + * Idle. */ - nfds = 0; - if (timeout_ms != 0) { - /* Add the kernel pipe to the poll table: */ - _thread_pfd_table[nfds].fd = _thread_kern_pipe[0]; - _thread_pfd_table[nfds].events = POLLRDNORM; - _thread_pfd_table[nfds].revents = 0; - nfds++; - kern_pipe_added = 1; - } - - PTHREAD_WAITQ_SETACTIVE(); - TAILQ_FOREACH(pthread, &_workq, qe) { - switch (pthread->state) { - case PS_SPINBLOCK: - /* - * If the lock is available, let the thread run. - */ - if (pthread->data.spinlock->access_lock == 0) { - PTHREAD_WAITQ_CLEARACTIVE(); - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - /* One less thread in a spinblock state: */ - _spinblock_count--; - /* - * Since there is at least one runnable - * thread, disable the wait. - */ - timeout_ms = 0; - } - break; - - /* File descriptor read wait: */ - case PS_FDR_WAIT: - /* Limit number of polled files to table size: */ - if (nfds < _thread_dtablesize) { - _thread_pfd_table[nfds].events = POLLRDNORM; - _thread_pfd_table[nfds].fd = pthread->data.fd.fd; - nfds++; - } - break; - - /* File descriptor write wait: */ - case PS_FDW_WAIT: - /* Limit number of polled files to table size: */ - if (nfds < _thread_dtablesize) { - _thread_pfd_table[nfds].events = POLLWRNORM; - _thread_pfd_table[nfds].fd = pthread->data.fd.fd; - nfds++; - } - break; - - /* File descriptor poll or select wait: */ - case PS_POLL_WAIT: - case PS_SELECT_WAIT: - /* Limit number of polled files to table size: */ - if (pthread->data.poll_data->nfds + nfds < - _thread_dtablesize) { - for (i = 0; i < pthread->data.poll_data->nfds; i++) { - _thread_pfd_table[nfds + i].fd = - pthread->data.poll_data->fds[i].fd; - _thread_pfd_table[nfds + i].events = - pthread->data.poll_data->fds[i].events; - } - nfds += pthread->data.poll_data->nfds; - } - break; - - /* Other states do not depend on file I/O. */ - default: - break; - } - } - PTHREAD_WAITQ_CLEARACTIVE(); - - /* - * Wait for a file descriptor to be ready for read, write, or - * an exception, or a timeout to occur: - */ - count = __sys_poll(_thread_pfd_table, nfds, timeout_ms); - - if (kern_pipe_added != 0) - /* - * Remove the pthread kernel pipe file descriptor - * from the pollfd table: - */ - nfds = 1; - else - nfds = 0; - - /* - * Check if it is possible that there are bytes in the kernel - * read pipe waiting to be read: - */ - if (count < 0 || ((kern_pipe_added != 0) && - (_thread_pfd_table[0].revents & POLLRDNORM))) { - /* - * If the kernel read pipe was included in the - * count: - */ - if (count > 0) { - /* Decrement the count of file descriptors: */ - count--; - } - - if (_sigq_check_reqd != 0) { - /* Reset flag before handling signals: */ - _sigq_check_reqd = 0; - - dequeue_signals(); - } - } - - /* - * Check if any file descriptors are ready: - */ - if (count > 0) { - /* - * Enter a loop to look for threads waiting on file - * descriptors that are flagged as available by the - * _poll syscall: - */ - PTHREAD_WAITQ_SETACTIVE(); - TAILQ_FOREACH(pthread, &_workq, qe) { - switch (pthread->state) { - case PS_SPINBLOCK: - /* - * If the lock is available, let the thread run. - */ - if (pthread->data.spinlock->access_lock == 0) { - PTHREAD_WAITQ_CLEARACTIVE(); - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - - /* - * One less thread in a spinblock state: - */ - _spinblock_count--; - } - break; - - /* File descriptor read wait: */ - case PS_FDR_WAIT: - if ((nfds < _thread_dtablesize) && - (_thread_pfd_table[nfds].revents - & (POLLRDNORM|POLLERR|POLLHUP|POLLNVAL)) - != 0) { - PTHREAD_WAITQ_CLEARACTIVE(); - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - } - nfds++; - break; - - /* File descriptor write wait: */ - case PS_FDW_WAIT: - if ((nfds < _thread_dtablesize) && - (_thread_pfd_table[nfds].revents - & (POLLWRNORM|POLLERR|POLLHUP|POLLNVAL)) - != 0) { - PTHREAD_WAITQ_CLEARACTIVE(); - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - } - nfds++; - break; - - /* File descriptor poll or select wait: */ - case PS_POLL_WAIT: - case PS_SELECT_WAIT: - if (pthread->data.poll_data->nfds + nfds < - _thread_dtablesize) { - /* - * Enter a loop looking for I/O - * readiness: - */ - found = 0; - for (i = 0; i < pthread->data.poll_data->nfds; i++) { - if (_thread_pfd_table[nfds + i].revents != 0) { - pthread->data.poll_data->fds[i].revents = - _thread_pfd_table[nfds + i].revents; - found++; - } - } - - /* Increment before destroying: */ - nfds += pthread->data.poll_data->nfds; - - if (found != 0) { - pthread->data.poll_data->nfds = found; - PTHREAD_WAITQ_CLEARACTIVE(); - PTHREAD_WORKQ_REMOVE(pthread); - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - PTHREAD_WAITQ_SETACTIVE(); - } - } - else - nfds += pthread->data.poll_data->nfds; - break; + __sys_poll(NULL, 0, timeout_ms); - /* Other states do not depend on file I/O. */ - default: - break; - } - } - PTHREAD_WAITQ_CLEARACTIVE(); - } - else if (_spinblock_count != 0) { + if (_spinblock_count != 0) { /* * Enter a loop to look for threads waiting on a spinlock * that is now available. @@ -971,22 +522,6 @@ thread_kern_poll(int wait_reqd) } PTHREAD_WAITQ_CLEARACTIVE(); } - - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - - while (_sigq_check_reqd != 0) { - /* Handle queued signals: */ - _sigq_check_reqd = 0; - - /* Protect the scheduling queues: */ - _queue_signals = 1; - - dequeue_signals(); - - /* Unprotect the scheduling queues: */ - _queue_signals = 0; - } } void @@ -1058,54 +593,13 @@ _thread_kern_sig_undefer(void) curthread->sig_defer_count = 0; /* - * Check if there are queued signals: - */ - if (_sigq_check_reqd != 0) - _thread_kern_sched(NULL); - - /* * Check for asynchronous cancellation before delivering any * pending signals: */ if (((curthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) && ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) pthread_testcancel(); - - /* - * If there are pending signals or this thread has - * to yield the CPU, call the kernel scheduler: - * - * XXX - Come back and revisit the pending signal problem - */ - if ((curthread->yield_on_sig_undefer != 0) || - SIGNOTEMPTY(curthread->sigpend)) { - curthread->yield_on_sig_undefer = 0; - _thread_kern_sched(NULL); - } - } -} - -static void -dequeue_signals(void) -{ - char bufr[128]; - int num; - - /* - * Enter a loop to clear the pthread kernel pipe: - */ - while (((num = __sys_read(_thread_kern_pipe[0], bufr, - sizeof(bufr))) > 0) || (num == -1 && errno == EINTR)) { - } - if ((num < 0) && (errno != EAGAIN)) { - /* - * The only error we should expect is if there is - * no data to read. - */ - PANIC("Unable to read from thread kernel pipe"); } - /* Handle any pending signals: */ - _thread_sig_handle_pending(); } static inline void diff --git a/lib/libpthread/thread/thr_kill.c b/lib/libpthread/thread/thr_kill.c index a8a1fc63978e..24f9150d7136 100644 --- a/lib/libpthread/thread/thr_kill.c +++ b/lib/libpthread/thread/thr_kill.c @@ -41,34 +41,8 @@ __weak_reference(_pthread_kill, pthread_kill); int _pthread_kill(pthread_t pthread, int sig) { - int ret; - - /* Check for invalid signal numbers: */ - if (sig < 0 || sig >= NSIG) - /* Invalid signal: */ - ret = EINVAL; /* - * Ensure the thread is in the list of active threads, and the - * signal is valid (signal 0 specifies error checking only) and - * not being ignored: + * All signals are unsupported. */ - else if (((ret = _find_thread(pthread)) == 0) && (sig > 0) && - (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - _thread_sig_send(pthread, sig); - - /* - * Undefer and handle pending signals, yielding if - * necessary: - */ - _thread_kern_sig_undefer(); - } - - /* Return the completion status: */ - return (ret); + return (EINVAL); } diff --git a/lib/libpthread/thread/thr_msync.c b/lib/libpthread/thread/thr_msync.c index 4d9a95093c1a..302f314fcf85 100644 --- a/lib/libpthread/thread/thr_msync.c +++ b/lib/libpthread/thread/thr_msync.c @@ -14,16 +14,6 @@ __weak_reference(__msync, msync); int -_msync(void *addr, size_t len, int flags) -{ - int ret; - - ret = __sys_msync(addr, len, flags); - - return (ret); -} - -int __msync(void *addr, size_t len, int flags) { int ret; @@ -35,7 +25,7 @@ __msync(void *addr, size_t len, int flags) * a cancellation point, as per the standard. sigh. */ _thread_enter_cancellation_point(); - ret = _msync(addr, len, flags); + ret = __sys_msync(addr, len, flags); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_open.c b/lib/libpthread/thread/thr_open.c index 3e0da32af7bc..b8a663523457 100644 --- a/lib/libpthread/thread/thr_open.c +++ b/lib/libpthread/thread/thr_open.c @@ -43,36 +43,6 @@ __weak_reference(__open, open); int -_open(const char *path, int flags,...) -{ - int fd; - int mode = 0; - va_list ap; - - /* Check if the file is being created: */ - if (flags & O_CREAT) { - /* Get the creation mode: */ - va_start(ap, flags); - mode = va_arg(ap, int); - va_end(ap); - } - /* Open the file: */ - if ((fd = __sys_open(path, flags, mode)) < 0) { - } - /* Initialise the file descriptor table entry: */ - else if (_thread_fd_table_init(fd) != 0) { - /* Quietly close the file: */ - __sys_close(fd); - - /* Reset the file descriptor: */ - fd = -1; - } - - /* Return the file descriptor or -1 on error: */ - return (fd); -} - -int __open(const char *path, int flags,...) { int ret; @@ -89,7 +59,7 @@ __open(const char *path, int flags,...) va_end(ap); } - ret = _open(path, flags, mode); + ret = __sys_open(path, flags, mode); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_poll.c b/lib/libpthread/thread/thr_poll.c index b4c495c123c9..353b3cc3cf3c 100644 --- a/lib/libpthread/thread/thr_poll.c +++ b/lib/libpthread/thread/thr_poll.c @@ -43,68 +43,13 @@ __weak_reference(__poll, poll); -int -_poll(struct pollfd *fds, unsigned int nfds, int timeout) -{ - struct pthread *curthread = _get_curthread(); - struct timespec ts; - int numfds = nfds; - int i, ret = 0; - struct pthread_poll_data data; - - if (numfds > _thread_dtablesize) { - numfds = _thread_dtablesize; - } - /* Check if a timeout was specified: */ - if (timeout == INFTIM) { - /* Wait for ever: */ - _thread_kern_set_timeout(NULL); - } else if (timeout > 0) { - /* Convert the timeout in msec to a timespec: */ - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - - /* Set the wake up time: */ - _thread_kern_set_timeout(&ts); - } else if (timeout < 0) { - /* a timeout less than zero but not == INFTIM is invalid */ - errno = EINVAL; - return (-1); - } - - if (((ret = __sys_poll(fds, numfds, 0)) == 0) && (timeout != 0)) { - data.nfds = numfds; - data.fds = fds; - - /* - * Clear revents in case of a timeout which leaves fds - * unchanged: - */ - for (i = 0; i < numfds; i++) { - fds[i].revents = 0; - } - - curthread->data.poll_data = &data; - curthread->interrupted = 0; - _thread_kern_sched_state(PS_POLL_WAIT, __FILE__, __LINE__); - if (curthread->interrupted) { - errno = EINTR; - ret = -1; - } else { - ret = data.nfds; - } - } - - return (ret); -} - int __poll(struct pollfd *fds, unsigned int nfds, int timeout) { int ret; _thread_enter_cancellation_point(); - ret = _poll(fds, nfds, timeout); + ret = __sys_poll(fds, nfds, timeout); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_priority_queue.c b/lib/libpthread/thread/thr_priority_queue.c index b938a3c3807e..1c1b269e446c 100644 --- a/lib/libpthread/thread/thr_priority_queue.c +++ b/lib/libpthread/thread/thr_priority_queue.c @@ -70,8 +70,8 @@ static int _pq_active = 0; } while (0) #define _PQ_ASSERT_PROTECTED(msg) \ PTHREAD_ASSERT((_thread_kern_in_sched != 0) || \ - ((_get_curthread())->sig_defer_count > 0) ||\ - (_sig_in_handler != 0), msg); + ((_get_curthread())->sig_defer_count > 0), \ + msg); #else diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index 4db52d98b9bf..2f49804f4e36 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -49,7 +49,6 @@ /* * Include files. */ -#include <setjmp.h> #include <signal.h> #include <stdio.h> #include <sys/queue.h> @@ -62,50 +61,6 @@ #include <pthread_np.h> /* - * Define machine dependent macros to get and set the stack pointer - * from the supported contexts. Also define a macro to set the return - * address in a jmp_buf context. - * - * XXX - These need to be moved into architecture dependent support files. - */ -#if defined(__i386__) -#define GET_STACK_JB(jb) ((unsigned long)((jb)[0]._jb[2])) -#define GET_STACK_SJB(sjb) ((unsigned long)((sjb)[0]._sjb[2])) -#define GET_STACK_UC(ucp) ((unsigned long)((ucp)->uc_mcontext.mc_esp)) -#define SET_STACK_JB(jb, stk) (jb)[0]._jb[2] = (int)(stk) -#define SET_STACK_SJB(sjb, stk) (sjb)[0]._sjb[2] = (int)(stk) -#define SET_STACK_UC(ucp, stk) (ucp)->uc_mcontext.mc_esp = (int)(stk) -#define FP_SAVE_UC(ucp) do { \ - char *fdata; \ - fdata = (char *) (ucp)->uc_mcontext.mc_fpregs; \ - __asm__("fnsave %0": :"m"(*fdata)); \ -} while (0) -#define FP_RESTORE_UC(ucp) do { \ - char *fdata; \ - fdata = (char *) (ucp)->uc_mcontext.mc_fpregs; \ - __asm__("frstor %0": :"m"(*fdata)); \ -} while (0) -#define SET_RETURN_ADDR_JB(jb, ra) (jb)[0]._jb[0] = (int)(ra) -#elif defined(__alpha__) -#include <machine/reg.h> -#define GET_STACK_JB(jb) ((unsigned long)((jb)[0]._jb[R_SP + 4])) -#define GET_STACK_SJB(sjb) ((unsigned long)((sjb)[0]._sjb[R_SP + 4])) -#define GET_STACK_UC(ucp) ((ucp)->uc_mcontext.mc_regs[R_SP]) -#define SET_STACK_JB(jb, stk) (jb)[0]._jb[R_SP + 4] = (long)(stk) -#define SET_STACK_SJB(sjb, stk) (sjb)[0]._sjb[R_SP + 4] = (long)(stk) -#define SET_STACK_UC(ucp, stk) (ucp)->uc_mcontext.mc_regs[R_SP] = (unsigned long)(stk) -#define FP_SAVE_UC(ucp) -#define FP_RESTORE_UC(ucp) -#define SET_RETURN_ADDR_JB(jb, ra) do { \ - (jb)[0]._jb[2] = (long)(ra); \ - (jb)[0]._jb[R_RA + 4] = (long)(ra); \ - (jb)[0]._jb[R_T12 + 4] = (long)(ra); \ -} while (0) -#else -#error "Don't recognize this architecture!" -#endif - -/* * Kernel fatal error handler macro. */ #define PANIC(string) _thread_exit(__FILE__,__LINE__,string) @@ -217,17 +172,6 @@ #endif /* - * Define the signals to be used for scheduling. - */ -#if defined(_PTHREADS_COMPAT_SCHED) -#define _ITIMER_SCHED_TIMER ITIMER_VIRTUAL -#define _SCHED_SIGNAL SIGVTALRM -#else -#define _ITIMER_SCHED_TIMER ITIMER_PROF -#define _SCHED_SIGNAL SIGPROF -#endif - -/* * Priority queues. * * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. @@ -487,20 +431,10 @@ struct pthread_rwlock { */ enum pthread_state { PS_RUNNING, - PS_SIGTHREAD, PS_MUTEX_WAIT, PS_COND_WAIT, - PS_FDLR_WAIT, - PS_FDLW_WAIT, - PS_FDR_WAIT, - PS_FDW_WAIT, - PS_FILE_WAIT, - PS_POLL_WAIT, - PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, - PS_SIGSUSPEND, - PS_SIGWAIT, PS_SPINBLOCK, PS_JOIN, PS_SUSPENDED, @@ -517,46 +451,9 @@ enum pthread_state { #define FD_WRITE 0x2 #define FD_RDWR (FD_READ | FD_WRITE) -/* - * File descriptor table structure. - */ -struct fd_table_entry { - /* - * Lock for accesses to this file descriptor table - * entry. This is passed to _spinlock() to provide atomic - * access to this structure. It does *not* represent the - * state of the lock on the file descriptor. - */ - spinlock_t lock; - TAILQ_HEAD(, pthread) r_queue; /* Read queue. */ - TAILQ_HEAD(, pthread) w_queue; /* Write queue. */ - struct pthread *r_owner; /* Ptr to thread owning read lock. */ - struct pthread *w_owner; /* Ptr to thread owning write lock. */ - char *r_fname; /* Ptr to read lock source file name */ - int r_lineno; /* Read lock source line number. */ - char *w_fname; /* Ptr to write lock source file name */ - int w_lineno; /* Write lock source line number. */ - int r_lockcount; /* Count for FILE read locks. */ - int w_lockcount; /* Count for FILE write locks. */ - int flags; /* Flags used in open. */ -}; - -struct pthread_poll_data { - int nfds; - struct pollfd *fds; -}; - union pthread_wait_data { pthread_mutex_t mutex; pthread_cond_t cond; - const sigset_t *sigwait; /* Waiting on a signal in sigwait */ - struct { - short fd; /* Used when thread waiting on fd */ - short branch; /* Line number, for debugging. */ - char *fname; /* Source file name for debugging.*/ - } fd; - FILE *fp; - struct pthread_poll_data *poll_data; spinlock_t *spinlock; struct pthread *thread; }; @@ -567,52 +464,12 @@ union pthread_wait_data { */ typedef void (*thread_continuation_t) (void *); -struct pthread_signal_frame; - -struct pthread_state_data { - struct pthread_signal_frame *psd_curframe; - sigset_t psd_sigmask; - struct timespec psd_wakeup_time; - union pthread_wait_data psd_wait_data; - enum pthread_state psd_state; - int psd_flags; - int psd_interrupted; - int psd_longjmp_val; - int psd_sigmask_seqno; - int psd_signo; - int psd_sig_defer_count; - /* XXX - What about thread->timeout and/or thread->error? */ -}; - struct join_status { struct pthread *thread; void *ret; int error; }; -/* - * The frame that is added to the top of a threads stack when setting up - * up the thread to run a signal handler. - */ -struct pthread_signal_frame { - /* - * This stores the threads state before the signal. - */ - struct pthread_state_data saved_state; - - /* - * Threads return context; we use only jmp_buf's for now. - */ - union { - jmp_buf jb; - ucontext_t uc; - } ctx; - int signo; /* signal, arg 1 to sighandler */ - int sig_has_args; /* use signal args if true */ - ucontext_t uc; - siginfo_t siginfo; -}; - struct pthread_specific_elem { const void *data; int seqno; @@ -652,19 +509,11 @@ struct pthread { struct pthread_attr attr; /* - * Threads return context; we use only jmp_buf's for now. + * Machine context, including signal state. */ - union { - jmp_buf jb; - ucontext_t uc; - } ctx; + ucontext_t ctx; /* - * Used for tracking delivery of signal handlers. - */ - struct pthread_signal_frame *curframe; - - /* * Cancelability flags - the lower 2 bits are used by cancel * definitions in pthread.h */ @@ -675,14 +524,6 @@ struct pthread { thread_continuation_t continuation; - /* - * Current signal mask and pending signals. - */ - sigset_t sigmask; - sigset_t sigpend; - int sigmask_seqno; - int check_pending; - /* Thread state: */ enum pthread_state state; @@ -700,7 +541,7 @@ struct pthread { /* * Time to wake up thread. This is used for sleeping threads and - * for any operation which may time out (such as select). + * for any operation which may time out. */ struct timespec wakeup_time; @@ -753,31 +594,17 @@ struct pthread { union pthread_wait_data data; /* - * Allocated for converting select into poll. - */ - struct pthread_poll_data poll_data; - - /* * Set to TRUE if a blocking operation was * interrupted by a signal: */ int interrupted; - /* Signal number when in state PS_SIGWAIT: */ - int signo; - /* * Set to non-zero when this thread has deferred signals. * We allow for recursive deferral. */ int sig_defer_count; - /* - * Set to TRUE if this thread should yield after undeferring - * signals. - */ - int yield_on_sig_undefer; - /* Miscellaneous flags; only set with signals deferred. */ int flags; #define PTHREAD_FLAGS_PRIVATE 0x0001 @@ -786,7 +613,7 @@ struct pthread { #define PTHREAD_FLAGS_IN_PRIOQ 0x0008 /* in priority queue using pqe link */ #define PTHREAD_FLAGS_IN_WORKQ 0x0010 /* in work queue using qe link */ #define PTHREAD_FLAGS_IN_FILEQ 0x0020 /* in file lock queue using qe link */ -#define PTHREAD_FLAGS_IN_FDQ 0x0040 /* in fd lock queue using qe link */ + /* 0x0040 Unused. */ #define PTHREAD_FLAGS_IN_CONDQ 0x0080 /* in condition queue using sqe link*/ #define PTHREAD_FLAGS_IN_MUTEXQ 0x0100 /* in mutex queue using sqe link */ #define PTHREAD_FLAGS_SUSPENDED 0x0200 /* thread is suspended */ @@ -876,25 +703,6 @@ SCLASS TAILQ_HEAD(, pthread) _thread_list ; #endif -/* - * Array of kernel pipe file descriptors that are used to ensure that - * no signals are missed in calls to _select. - */ -SCLASS int _thread_kern_pipe[2] -#ifdef GLOBAL_PTHREAD_PRIVATE -= { - -1, - -1 -}; -#else -; -#endif -SCLASS int volatile _queue_signals -#ifdef GLOBAL_PTHREAD_PRIVATE -= 0; -#else -; -#endif SCLASS int _thread_kern_in_sched #ifdef GLOBAL_PTHREAD_PRIVATE = 0; @@ -902,13 +710,6 @@ SCLASS int _thread_kern_in_sched ; #endif -SCLASS int _sig_in_handler -#ifdef GLOBAL_PTHREAD_PRIVATE -= 0; -#else -; -#endif - /* Time of day at last scheduling timer signal: */ SCLASS struct timeval volatile _sched_tod #ifdef GLOBAL_PTHREAD_PRIVATE @@ -969,42 +770,6 @@ SCLASS struct pthread_cond_attr pthread_condattr_default ; #endif -/* - * Standard I/O file descriptors need special flag treatment since - * setting one to non-blocking does all on *BSD. Sigh. This array - * is used to store the initial flag settings. - */ -SCLASS int _pthread_stdio_flags[3]; - -/* File table information: */ -SCLASS struct fd_table_entry **_thread_fd_table -#ifdef GLOBAL_PTHREAD_PRIVATE -= NULL; -#else -; -#endif - -/* Table for polling file descriptors: */ -SCLASS struct pollfd *_thread_pfd_table -#ifdef GLOBAL_PTHREAD_PRIVATE -= NULL; -#else -; -#endif - -SCLASS const int dtablecount -#ifdef GLOBAL_PTHREAD_PRIVATE -= 4096/sizeof(struct fd_table_entry); -#else -; -#endif -SCLASS int _thread_dtablesize /* Descriptor table size. */ -#ifdef GLOBAL_PTHREAD_PRIVATE -= 0; -#else -; -#endif - SCLASS int _clock_res_usec /* Clock resolution in usec. */ #ifdef GLOBAL_PTHREAD_PRIVATE = CLOCK_RES_USEC; @@ -1025,28 +790,6 @@ SCLASS pthread_cond_t _gc_cond ; /* - * Array of signal actions for this process. - */ -SCLASS struct sigaction _thread_sigact[NSIG]; - -/* - * Array of counts of dummy handlers for SIG_DFL signals. This is used to - * assure that there is always a dummy signal handler installed while there is a - * thread sigwait()ing on the corresponding signal. - */ -SCLASS int _thread_dfl_count[NSIG]; - -/* - * Pending signals and mask for this process: - */ -SCLASS sigset_t _process_sigpending; -SCLASS sigset_t _process_sigmask -#ifdef GLOBAL_PTHREAD_PRIVATE -= { {0, 0, 0, 0} } -#endif -; - -/* * Scheduling queues: */ SCLASS pq_queue_t _readyq; @@ -1064,28 +807,6 @@ SCLASS volatile int _spinblock_count #endif ; -/* Used to maintain pending and active signals: */ -struct sigstatus { - int pending; /* Is this a pending signal? */ - int blocked; /* - * A handler is currently active for - * this signal; ignore subsequent - * signals until the handler is done. - */ - int signo; /* arg 1 to signal handler */ - siginfo_t siginfo; /* arg 2 to signal handler */ - ucontext_t uc; /* arg 3 to signal handler */ -}; - -SCLASS struct sigstatus _thread_sigq[NSIG]; - -/* Indicates that the signal queue needs to be checked. */ -SCLASS volatile int _sigq_check_reqd -#ifdef GLOBAL_PTHREAD_PRIVATE -= 0 -#endif -; - /* Thread switch hook. */ SCLASS pthread_switch_routine_t _sched_switch_hook #ifdef GLOBAL_PTHREAD_PRIVATE @@ -1096,9 +817,9 @@ SCLASS pthread_switch_routine_t _sched_switch_hook /* * Declare the kernel scheduler jump buffer and stack: */ -SCLASS jmp_buf _thread_kern_sched_jb; +SCLASS ucontext_t _thread_kern_sched_ctx; -SCLASS void * _thread_kern_sched_stack +SCLASS void * _thread_kern_sched_stack #ifdef GLOBAL_PTHREAD_PRIVATE = NULL #endif @@ -1115,16 +836,6 @@ SCLASS int _thread_kern_new_state /* Undefine the storage class specifier: */ #undef SCLASS -#ifdef _LOCK_DEBUG -#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \ - _ts, __FILE__, __LINE__) -#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock_debug(_fd, _type, \ - __FILE__, __LINE__) -#else -#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts) -#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) -#endif - /* * Function prototype definitions. */ @@ -1133,7 +844,6 @@ char *__ttyname_basic(int); char *__ttyname_r_basic(int, char *, size_t); char *ttyname_r(int, char *, size_t); void _cond_wait_backout(pthread_t); -void _fd_lock_backout(pthread_t); int _find_thread(pthread_t); struct pthread *_get_curthread(void); void _set_curthread(struct pthread *); @@ -1175,35 +885,18 @@ void _waitq_clearactive(void); #endif void _thread_exit(char *, int, char *); void _thread_exit_cleanup(void); -int _thread_fd_getflags(int); -int _thread_fd_lock(int, int, struct timespec *); -int _thread_fd_lock_debug(int, int, struct timespec *,char *fname,int lineno); -void _thread_fd_setflags(int, int); -int _thread_fd_table_init(int fd); -void _thread_fd_unlock(int, int); -void _thread_fd_unlock_debug(int, int, char *, int); -void _thread_fd_unlock_owned(pthread_t); void *_thread_cleanup(pthread_t); void _thread_cleanupspecific(void); void _thread_dump_info(void); void _thread_init(void); -void _thread_kern_sched(ucontext_t *); +void _thread_kern_sched(void); void _thread_kern_scheduler(void); -void _thread_kern_sched_frame(struct pthread_signal_frame *psf); -void _thread_kern_sched_sig(void); void _thread_kern_sched_state(enum pthread_state, char *fname, int lineno); void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno); void _thread_kern_set_timeout(const struct timespec *); void _thread_kern_sig_defer(void); void _thread_kern_sig_undefer(void); -void _thread_sig_handler(int, siginfo_t *, ucontext_t *); -void _thread_sig_check_pending(struct pthread *pthread); -void _thread_sig_handle_pending(void); -void _thread_sig_send(struct pthread *pthread, int sig); -void _thread_sig_wrapper(void); -void _thread_sigframe_restore(struct pthread *thread, - struct pthread_signal_frame *psf); void _thread_start(void); void _thread_seterrno(pthread_t, int); pthread_addr_t _thread_gc(pthread_addr_t); @@ -1211,13 +904,6 @@ void _thread_enter_cancellation_point(void); void _thread_leave_cancellation_point(void); void _thread_cancellation_point(void); -/* #include <sys/acl.h> */ -#ifdef _SYS_ACL_H -int __sys___acl_aclcheck_fd(int, acl_type_t, struct acl *); -int __sys___acl_delete_fd(int, acl_type_t); -int __sys___acl_get_fd(int, acl_type_t, struct acl *); -int __sys___acl_set_fd(int, acl_type_t, struct acl *); -#endif /* #include <sys/aio.h> */ #ifdef _SYS_AIO_H_ @@ -1324,12 +1010,6 @@ ssize_t __sys_read(int, void *, size_t); ssize_t __sys_write(int, const void *, size_t); #endif -/* #include <setjmp.h> */ -#ifdef _SETJMP_H_ -extern void __siglongjmp(sigjmp_buf, int) __dead2; -extern void __longjmp(jmp_buf, int) __dead2; -extern void ___longjmp(jmp_buf, int) __dead2; -#endif __END_DECLS #endif /* !_THR_PRIVATE_H */ diff --git a/lib/libpthread/thread/thr_read.c b/lib/libpthread/thread/thr_read.c index f313a9c231aa..8d095c439820 100644 --- a/lib/libpthread/thread/thr_read.c +++ b/lib/libpthread/thread/thr_read.c @@ -43,68 +43,12 @@ __weak_reference(__read, read); ssize_t -_read(int fd, void *buf, size_t nbytes) -{ - struct pthread *curthread = _get_curthread(); - int ret; - int type; - - /* POSIX says to do just this: */ - if (nbytes == 0) { - return (0); - } - - /* Lock the file descriptor for read: */ - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { - /* Get the read/write mode type: */ - type = _thread_fd_getflags(fd) & O_ACCMODE; - - /* Check if the file is not open for read: */ - if (type != O_RDONLY && type != O_RDWR) { - /* File is not open for read: */ - errno = EBADF; - _FD_UNLOCK(fd, FD_READ); - return (-1); - } - - /* Perform a non-blocking read syscall: */ - while ((ret = __sys_read(fd, buf, nbytes)) < 0) { - if ((_thread_fd_getflags(fd) & O_NONBLOCK) == 0 && - (errno == EWOULDBLOCK || errno == EAGAIN)) { - curthread->data.fd.fd = fd; - _thread_kern_set_timeout(NULL); - - /* Reset the interrupted operation flag: */ - curthread->interrupted = 0; - - _thread_kern_sched_state(PS_FDR_WAIT, - __FILE__, __LINE__); - - /* - * Check if the operation was - * interrupted by a signal - */ - if (curthread->interrupted) { - errno = EINTR; - ret = -1; - break; - } - } else { - break; - } - } - _FD_UNLOCK(fd, FD_READ); - } - return (ret); -} - -ssize_t __read(int fd, void *buf, size_t nbytes) { ssize_t ret; _thread_enter_cancellation_point(); - ret = _read(fd, buf, nbytes); + ret = __sys_read(fd, buf, nbytes); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_readv.c b/lib/libpthread/thread/thr_readv.c index 707c04c96809..c3b03eb4d5c9 100644 --- a/lib/libpthread/thread/thr_readv.c +++ b/lib/libpthread/thread/thr_readv.c @@ -43,63 +43,12 @@ __weak_reference(__readv, readv); ssize_t -_readv(int fd, const struct iovec * iov, int iovcnt) -{ - struct pthread *curthread = _get_curthread(); - int ret; - int type; - - /* Lock the file descriptor for read: */ - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { - /* Get the read/write mode type: */ - type = _thread_fd_getflags(fd) & O_ACCMODE; - - /* Check if the file is not open for read: */ - if (type != O_RDONLY && type != O_RDWR) { - /* File is not open for read: */ - errno = EBADF; - _FD_UNLOCK(fd, FD_READ); - return (-1); - } - - /* Perform a non-blocking readv syscall: */ - while ((ret = __sys_readv(fd, iov, iovcnt)) < 0) { - if ((_thread_fd_getflags(fd) & O_NONBLOCK) == 0 && - (errno == EWOULDBLOCK || errno == EAGAIN)) { - curthread->data.fd.fd = fd; - _thread_kern_set_timeout(NULL); - - /* Reset the interrupted operation flag: */ - curthread->interrupted = 0; - - _thread_kern_sched_state(PS_FDR_WAIT, - __FILE__, __LINE__); - - /* - * Check if the operation was - * interrupted by a signal - */ - if (curthread->interrupted) { - errno = EINTR; - ret = -1; - break; - } - } else { - break; - } - } - _FD_UNLOCK(fd, FD_READ); - } - return (ret); -} - -ssize_t __readv(int fd, const struct iovec *iov, int iovcnt) { ssize_t ret; _thread_enter_cancellation_point(); - ret = _readv(fd, iov, iovcnt); + ret = __sys_readv(fd, iov, iovcnt); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_select.c b/lib/libpthread/thread/thr_select.c index a0415137f808..a4f4a1512b05 100644 --- a/lib/libpthread/thread/thr_select.c +++ b/lib/libpthread/thread/thr_select.c @@ -46,185 +46,13 @@ __weak_reference(__select, select); int -_select(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, - struct timeval * timeout) -{ - struct pthread *curthread = _get_curthread(); - struct timespec ts; - int i, ret = 0, f_wait = 1; - int pfd_index, got_events = 0, fd_count = 0; - struct pthread_poll_data data; - - if (numfds > _thread_dtablesize) { - numfds = _thread_dtablesize; - } - /* Check if a timeout was specified: */ - if (timeout) { - if (timeout->tv_sec < 0 || - timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { - errno = EINVAL; - return (-1); - } - - /* Convert the timeval to a timespec: */ - TIMEVAL_TO_TIMESPEC(timeout, &ts); - - /* Set the wake up time: */ - _thread_kern_set_timeout(&ts); - if (ts.tv_sec == 0 && ts.tv_nsec == 0) - f_wait = 0; - } else { - /* Wait for ever: */ - _thread_kern_set_timeout(NULL); - } - - /* Count the number of file descriptors to be polled: */ - if (readfds || writefds || exceptfds) { - for (i = 0; i < numfds; i++) { - if ((readfds && FD_ISSET(i, readfds)) || - (exceptfds && FD_ISSET(i, exceptfds)) || - (writefds && FD_ISSET(i, writefds))) { - fd_count++; - } - } - } - - /* - * Allocate memory for poll data if it hasn't already been - * allocated or if previously allocated memory is insufficient. - */ - if ((curthread->poll_data.fds == NULL) || - (curthread->poll_data.nfds < fd_count)) { - data.fds = (struct pollfd *) realloc(curthread->poll_data.fds, - sizeof(struct pollfd) * MAX(128, fd_count)); - if (data.fds == NULL) { - errno = ENOMEM; - ret = -1; - } - else { - /* - * Note that the threads poll data always - * indicates what is allocated, not what is - * currently being polled. - */ - curthread->poll_data.fds = data.fds; - curthread->poll_data.nfds = MAX(128, fd_count); - } - } - if (ret == 0) { - /* Setup the wait data. */ - data.fds = curthread->poll_data.fds; - data.nfds = fd_count; - - /* - * Setup the array of pollfds. Optimize this by - * running the loop in reverse and stopping when - * the number of selected file descriptors is reached. - */ - for (i = numfds - 1, pfd_index = fd_count - 1; - (i >= 0) && (pfd_index >= 0); i--) { - data.fds[pfd_index].events = 0; - if (readfds && FD_ISSET(i, readfds)) { - data.fds[pfd_index].events = POLLRDNORM; - } - if (exceptfds && FD_ISSET(i, exceptfds)) { - data.fds[pfd_index].events |= POLLRDBAND; - } - if (writefds && FD_ISSET(i, writefds)) { - data.fds[pfd_index].events |= POLLWRNORM; - } - if (data.fds[pfd_index].events != 0) { - /* - * Set the file descriptor to be polled and - * clear revents in case of a timeout which - * leaves fds unchanged: - */ - data.fds[pfd_index].fd = i; - data.fds[pfd_index].revents = 0; - pfd_index--; - } - } - if (((ret = __sys_poll(data.fds, data.nfds, 0)) == 0) && - (f_wait != 0)) { - curthread->data.poll_data = &data; - curthread->interrupted = 0; - _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); - if (curthread->interrupted) { - errno = EINTR; - data.nfds = 0; - ret = -1; - } else - ret = data.nfds; - } - } - - if (ret >= 0) { - numfds = 0; - for (i = 0; i < fd_count; i++) { - /* - * Check the results of the poll and clear - * this file descriptor from the fdset if - * the requested event wasn't ready. - */ - - /* - * First check for invalid descriptor. - * If found, set errno and return -1. - */ - if (data.fds[i].revents & POLLNVAL) { - errno = EBADF; - return -1; - } - - got_events = 0; - if (readfds != NULL) { - if (FD_ISSET(data.fds[i].fd, readfds)) { - if ((data.fds[i].revents & (POLLIN - | POLLRDNORM | POLLERR - | POLLHUP | POLLNVAL)) != 0) - got_events++; - else - FD_CLR(data.fds[i].fd, readfds); - } - } - if (writefds != NULL) { - if (FD_ISSET(data.fds[i].fd, writefds)) { - if ((data.fds[i].revents & (POLLOUT - | POLLWRNORM | POLLWRBAND | POLLERR - | POLLHUP | POLLNVAL)) != 0) - got_events++; - else - FD_CLR(data.fds[i].fd, - writefds); - } - } - if (exceptfds != NULL) { - if (FD_ISSET(data.fds[i].fd, exceptfds)) { - if (data.fds[i].revents & (POLLRDBAND | - POLLPRI)) - got_events++; - else - FD_CLR(data.fds[i].fd, - exceptfds); - } - } - if (got_events != 0) - numfds+=got_events; - } - ret = numfds; - } - - return (ret); -} - -int __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int ret; _thread_enter_cancellation_point(); - ret = _select(numfds, readfds, writefds, exceptfds, timeout); + ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_sigmask.c b/lib/libpthread/thread/thr_sigmask.c index c26fefc53b8e..846062aff7ad 100644 --- a/lib/libpthread/thread/thr_sigmask.c +++ b/lib/libpthread/thread/thr_sigmask.c @@ -44,63 +44,6 @@ __weak_reference(_pthread_sigmask, pthread_sigmask); int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { - struct pthread *curthread = _get_curthread(); - sigset_t sigset; - int ret = 0; - /* Check if the existing signal process mask is to be returned: */ - if (oset != NULL) { - /* Return the current mask: */ - *oset = curthread->sigmask; - } - /* Check if a new signal set was provided by the caller: */ - if (set != NULL) { - /* Process according to what to do: */ - switch (how) { - /* Block signals: */ - case SIG_BLOCK: - /* Add signals to the existing mask: */ - SIGSETOR(curthread->sigmask, *set); - break; - - /* Unblock signals: */ - case SIG_UNBLOCK: - /* Clear signals from the existing mask: */ - SIGSETNAND(curthread->sigmask, *set); - break; - - /* Set the signal process mask: */ - case SIG_SETMASK: - /* Set the new mask: */ - curthread->sigmask = *set; - break; - - /* Trap invalid actions: */ - default: - /* Return an invalid argument: */ - errno = EINVAL; - ret = -1; - break; - } - - /* Increment the sequence number: */ - curthread->sigmask_seqno++; - - /* - * Check if there are pending signals for the running - * thread or process that aren't blocked: - */ - sigset = curthread->sigpend; - SIGSETOR(sigset, _process_sigpending); - SIGSETNAND(sigset, curthread->sigmask); - if (SIGNOTEMPTY(sigset)) - /* - * Call the kernel scheduler which will safely - * install a signal frame for the running thread: - */ - _thread_kern_sched_sig(); - } - - /* Return the completion status: */ - return (ret); + return (sigprocmask(how, set, oset)); } diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c index 90638f4a458d..dc805ac38314 100644 --- a/lib/libpthread/thread/thr_sigsuspend.c +++ b/lib/libpthread/thread/thr_sigsuspend.c @@ -41,60 +41,12 @@ __weak_reference(__sigsuspend, sigsuspend); int -_sigsuspend(const sigset_t * set) -{ - struct pthread *curthread = _get_curthread(); - int ret = -1; - sigset_t oset, sigset; - - /* Check if a new signal set was provided by the caller: */ - if (set != NULL) { - /* Save the current signal mask: */ - oset = curthread->sigmask; - - /* Change the caller's mask: */ - curthread->sigmask = *set; - - /* - * Check if there are pending signals for the running - * thread or process that aren't blocked: - */ - sigset = curthread->sigpend; - SIGSETOR(sigset, _process_sigpending); - SIGSETNAND(sigset, curthread->sigmask); - if (SIGNOTEMPTY(sigset)) { - /* - * Call the kernel scheduler which will safely - * install a signal frame for the running thread: - */ - _thread_kern_sched_sig(); - } else { - /* Wait for a signal: */ - _thread_kern_sched_state(PS_SIGSUSPEND, - __FILE__, __LINE__); - } - - /* Always return an interrupted error: */ - errno = EINTR; - - /* Restore the signal mask: */ - curthread->sigmask = oset; - } else { - /* Return an invalid argument error: */ - errno = EINVAL; - } - - /* Return the completion status: */ - return (ret); -} - -int __sigsuspend(const sigset_t * set) { int ret; _thread_enter_cancellation_point(); - ret = _sigsuspend(set); + ret = __sys_sigsuspend(set); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_sigwait.c b/lib/libpthread/thread/thr_sigwait.c index 209d3e70ea4d..3cc9ff0385a5 100644 --- a/lib/libpthread/thread/thr_sigwait.c +++ b/lib/libpthread/thread/thr_sigwait.c @@ -1,3 +1,4 @@ +//depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko) /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -43,132 +44,9 @@ __weak_reference(_sigwait, sigwait); int _sigwait(const sigset_t *set, int *sig) { - struct pthread *curthread = _get_curthread(); - int ret = 0; - int i; - sigset_t tempset, waitset; - struct sigaction act; - - _thread_enter_cancellation_point(); - /* - * Specify the thread kernel signal handler. - */ - act.sa_handler = (void (*) ()) _thread_sig_handler; - act.sa_flags = SA_RESTART | SA_SIGINFO; - /* Ensure the signal handler cannot be interrupted by other signals: */ - sigfillset(&act.sa_mask); - - /* - * Initialize the set of signals that will be waited on: - */ - waitset = *set; - - /* These signals can't be waited on. */ - sigdelset(&waitset, SIGKILL); - sigdelset(&waitset, SIGSTOP); - sigdelset(&waitset, _SCHED_SIGNAL); - sigdelset(&waitset, SIGCHLD); - sigdelset(&waitset, SIGINFO); - - /* Check to see if a pending signal is in the wait mask. */ - tempset = curthread->sigpend; - SIGSETOR(tempset, _process_sigpending); - SIGSETAND(tempset, waitset); - if (SIGNOTEMPTY(tempset)) { - /* Enter a loop to find a pending signal: */ - for (i = 1; i < NSIG; i++) { - if (sigismember (&tempset, i)) - break; - } - - /* Clear the pending signal: */ - if (sigismember(&curthread->sigpend,i)) - sigdelset(&curthread->sigpend,i); - else - sigdelset(&_process_sigpending,i); - - /* Return the signal number to the caller: */ - *sig = i; - - _thread_leave_cancellation_point(); - return (0); - } - - /* - * Access the _thread_dfl_count array under the protection of signal - * deferral. - */ - _thread_kern_sig_defer(); /* - * Enter a loop to find the signals that are SIG_DFL. For - * these signals we must install a dummy signal handler in - * order for the kernel to pass them in to us. POSIX says - * that the _application_ must explicitly install a dummy - * handler for signals that are SIG_IGN in order to sigwait - * on them. Note that SIG_IGN signals are left in the - * mask because a subsequent sigaction could enable an - * ignored signal. + * All signals are invalid for waiting. */ - sigemptyset(&tempset); - for (i = 1; i < NSIG; i++) { - if (sigismember(&waitset, i) && - (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { - _thread_dfl_count[i]++; - sigaddset(&tempset, i); - if (_thread_dfl_count[i] == 1) { - if (__sys_sigaction(i,&act,NULL) != 0) - ret = -1; - } - } - } - /* Done accessing _thread_dfl_count for now. */ - _thread_kern_sig_undefer(); - - if (ret == 0) { - /* - * Save the wait signal mask. The wait signal - * mask is independent of the threads signal mask - * and requires separate storage. - */ - curthread->data.sigwait = &waitset; - - /* Wait for a signal: */ - _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); - - /* Return the signal number to the caller: */ - *sig = curthread->signo; - - /* - * Probably unnecessary, but since it's in a union struct - * we don't know how it could be used in the future. - */ - curthread->data.sigwait = NULL; - } - - /* - * Access the _thread_dfl_count array under the protection of signal - * deferral. - */ - _thread_kern_sig_defer(); - - /* Restore the sigactions: */ - act.sa_handler = SIG_DFL; - for (i = 1; i < NSIG; i++) { - if (sigismember(&tempset, i)) { - _thread_dfl_count[i]--; - if ((_thread_sigact[i - 1].sa_handler == SIG_DFL) && - (_thread_dfl_count[i] == 0)) { - if (__sys_sigaction(i,&act,NULL) != 0) - ret = -1; - } - } - } - /* Done accessing _thread_dfl_count. */ - _thread_kern_sig_undefer(); - - _thread_leave_cancellation_point(); - - /* Return the completion status: */ - return (ret); + return (EINVAL); } diff --git a/lib/libpthread/thread/thr_wait4.c b/lib/libpthread/thread/thr_wait4.c index 90df876b1760..07b0c847eacb 100644 --- a/lib/libpthread/thread/thr_wait4.c +++ b/lib/libpthread/thread/thr_wait4.c @@ -41,35 +41,6 @@ __weak_reference(__wait4, wait4); pid_t -_wait4(pid_t pid, int *istat, int options, struct rusage * rusage) -{ - struct pthread *curthread = _get_curthread(); - pid_t ret; - - _thread_kern_sig_defer(); - - /* Perform a non-blocking wait4 syscall: */ - while ((ret = __sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) { - /* Reset the interrupted operation flag: */ - curthread->interrupted = 0; - - /* Schedule the next thread while this one waits: */ - _thread_kern_sched_state(PS_WAIT_WAIT, __FILE__, __LINE__); - - /* Check if this call was interrupted by a signal: */ - if (curthread->interrupted) { - errno = EINTR; - ret = -1; - break; - } - } - - _thread_kern_sig_undefer(); - - return (ret); -} - -pid_t __wait4(pid_t pid, int *istat, int options, struct rusage *rusage) { pid_t ret; diff --git a/lib/libpthread/thread/thr_write.c b/lib/libpthread/thread/thr_write.c index 80925ec88de2..4c8c171fd85e 100644 --- a/lib/libpthread/thread/thr_write.c +++ b/lib/libpthread/thread/thr_write.c @@ -43,104 +43,12 @@ __weak_reference(__write, write); ssize_t -_write(int fd, const void *buf, size_t nbytes) -{ - struct pthread *curthread = _get_curthread(); - int blocking; - int type; - ssize_t n; - ssize_t num = 0; - ssize_t ret; - - /* POSIX says to do just this: */ - if (nbytes == 0) - return (0); - - /* Lock the file descriptor for write: */ - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { - /* Get the read/write mode type: */ - type = _thread_fd_getflags(fd) & O_ACCMODE; - - /* Check if the file is not open for write: */ - if (type != O_WRONLY && type != O_RDWR) { - /* File is not open for write: */ - errno = EBADF; - _FD_UNLOCK(fd, FD_WRITE); - return (-1); - } - - /* Check if file operations are to block */ - blocking = ((_thread_fd_getflags(fd) & O_NONBLOCK) == 0); - - /* - * Loop while no error occurs and until the expected number - * of bytes are written if performing a blocking write: - */ - while (ret == 0) { - /* Perform a non-blocking write syscall: */ - n = __sys_write(fd, buf + num, nbytes - num); - - /* Check if one or more bytes were written: */ - if (n > 0) - /* - * Keep a count of the number of bytes - * written: - */ - num += n; - - /* - * If performing a blocking write, check if the - * write would have blocked or if some bytes - * were written but there are still more to - * write: - */ - if (blocking && ((n < 0 && (errno == EWOULDBLOCK || - errno == EAGAIN)) || (n >= 0 && num < nbytes))) { - curthread->data.fd.fd = fd; - _thread_kern_set_timeout(NULL); - - /* Reset the interrupted operation flag: */ - curthread->interrupted = 0; - - _thread_kern_sched_state(PS_FDW_WAIT, - __FILE__, __LINE__); - - /* - * Check if the operation was - * interrupted by a signal - */ - if (curthread->interrupted) { - /* Return an error: */ - ret = -1; - } - - /* - * If performing a non-blocking write or if an - * error occurred, just return whatever the write - * syscall did: - */ - } else if (!blocking || n < 0) { - /* A non-blocking call might return zero: */ - ret = n; - break; - - /* Check if the write has completed: */ - } else if (num >= nbytes) - /* Return the number of bytes written: */ - ret = num; - } - _FD_UNLOCK(fd, FD_WRITE); - } - return (ret); -} - -ssize_t __write(int fd, const void *buf, size_t nbytes) { ssize_t ret; _thread_enter_cancellation_point(); - ret = _write(fd, buf, nbytes); + ret = __sys_write(fd, buf, nbytes); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_writev.c b/lib/libpthread/thread/thr_writev.c index 4fcb9f1069ab..cff95b12d6f9 100644 --- a/lib/libpthread/thread/thr_writev.c +++ b/lib/libpthread/thread/thr_writev.c @@ -45,171 +45,12 @@ __weak_reference(__writev, writev); ssize_t -_writev(int fd, const struct iovec * iov, int iovcnt) -{ - struct pthread *curthread = _get_curthread(); - int blocking; - int idx = 0; - int type; - ssize_t cnt; - ssize_t n; - ssize_t num = 0; - ssize_t ret; - struct iovec liov[20]; - struct iovec *p_iov = liov; - - /* Check if the array size exceeds to compiled in size: */ - if (iovcnt > (sizeof(liov) / sizeof(struct iovec))) { - /* Allocate memory for the local array: */ - if ((p_iov = (struct iovec *) - malloc(iovcnt * sizeof(struct iovec))) == NULL) { - /* Insufficient memory: */ - errno = ENOMEM; - return (-1); - } - } - - /* Copy the caller's array so that it can be modified locally: */ - memcpy(p_iov,iov,iovcnt * sizeof(struct iovec)); - - /* Lock the file descriptor for write: */ - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { - /* Get the read/write mode type: */ - type = _thread_fd_getflags(fd) & O_ACCMODE; - - /* Check if the file is not open for write: */ - if (type != O_WRONLY && type != O_RDWR) { - /* File is not open for write: */ - errno = EBADF; - _FD_UNLOCK(fd, FD_WRITE); - return (-1); - } - - /* Check if file operations are to block */ - blocking = ((_thread_fd_getflags(fd) & O_NONBLOCK) == 0); - - /* - * Loop while no error occurs and until the expected number - * of bytes are written if performing a blocking write: - */ - while (ret == 0) { - /* Perform a non-blocking write syscall: */ - n = __sys_writev(fd, &p_iov[idx], iovcnt - idx); - - /* Check if one or more bytes were written: */ - if (n > 0) { - /* - * Keep a count of the number of bytes - * written: - */ - num += n; - - /* - * Enter a loop to check if a short write - * occurred and move the index to the - * array entry where the short write - * ended: - */ - cnt = n; - while (cnt > 0 && idx < iovcnt) { - /* - * If the residual count exceeds - * the size of this vector, then - * it was completely written: - */ - if (cnt >= p_iov[idx].iov_len) - /* - * Decrement the residual - * count and increment the - * index to the next array - * entry: - */ - cnt -= p_iov[idx++].iov_len; - else { - /* - * This entry was only - * partially written, so - * adjust it's length - * and base pointer ready - * for the next write: - */ - p_iov[idx].iov_len -= cnt; - p_iov[idx].iov_base += cnt; - cnt = 0; - } - } - } else if (n == 0) { - /* - * Avoid an infinite loop if the last iov_len is - * 0. - */ - while (idx < iovcnt && p_iov[idx].iov_len == 0) - idx++; - - if (idx == iovcnt) { - ret = num; - break; - } - } - - /* - * If performing a blocking write, check if the - * write would have blocked or if some bytes - * were written but there are still more to - * write: - */ - if (blocking && ((n < 0 && (errno == EWOULDBLOCK || - errno == EAGAIN)) || (n >= 0 && idx < iovcnt))) { - curthread->data.fd.fd = fd; - _thread_kern_set_timeout(NULL); - - /* Reset the interrupted operation flag: */ - curthread->interrupted = 0; - - _thread_kern_sched_state(PS_FDW_WAIT, - __FILE__, __LINE__); - - /* - * Check if the operation was - * interrupted by a signal - */ - if (curthread->interrupted) { - /* Return an error: */ - ret = -1; - } - - /* - * If performing a non-blocking write or if an - * error occurred, just return whatever the write - * syscall did: - */ - } else if (!blocking || n < 0) { - /* A non-blocking call might return zero: */ - ret = n; - break; - - /* Check if the write has completed: */ - } else if (idx == iovcnt) - /* Return the number of bytes written: */ - ret = num; - } - _FD_UNLOCK(fd, FD_RDWR); - } - - /* If memory was allocated for the array, free it: */ - if (p_iov != liov) - free(p_iov); - - return (ret); -} - -ssize_t __writev(int fd, const struct iovec *iov, int iovcnt) { ssize_t ret; _thread_enter_cancellation_point(); - ret = _writev(fd, iov, iovcnt); + ret = __sys_writev(fd, iov, iovcnt); _thread_leave_cancellation_point(); return ret; diff --git a/lib/libpthread/thread/thr_yield.c b/lib/libpthread/thread/thr_yield.c index ed66da61a804..e652a9cb3a3d 100644 --- a/lib/libpthread/thread/thr_yield.c +++ b/lib/libpthread/thread/thr_yield.c @@ -46,7 +46,7 @@ _sched_yield(void) curthread->slice_usec = -1; /* Schedule the next thread: */ - _thread_kern_sched(NULL); + _thread_kern_sched(); /* Always return no error. */ return(0); @@ -62,5 +62,5 @@ _pthread_yield(void) curthread->slice_usec = -1; /* Schedule the next thread: */ - _thread_kern_sched(NULL); + _thread_kern_sched(); } |