thr_write.c revision 53812
1161196Simp/* 2157873Simp * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 3157873Simp * All rights reserved. 4157873Simp * 5157873Simp * Redistribution and use in source and binary forms, with or without 6157873Simp * modification, are permitted provided that the following conditions 7157873Simp * are met: 8157873Simp * 1. Redistributions of source code must retain the above copyright 9157873Simp * notice, this list of conditions and the following disclaimer. 10157873Simp * 2. Redistributions in binary form must reproduce the above copyright 11157873Simp * notice, this list of conditions and the following disclaimer in the 12157873Simp * documentation and/or other materials provided with the distribution. 13157873Simp * 3. All advertising materials mentioning features or use of this software 14157873Simp * must display the following acknowledgement: 15157873Simp * This product includes software developed by John Birrell. 16157873Simp * 4. Neither the name of the author nor the names of any co-contributors 17157873Simp * may be used to endorse or promote products derived from this software 18157873Simp * without specific prior written permission. 19157873Simp * 20157873Simp * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21161196Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22157873Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23161196Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24157873Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25157873Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26161196Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27157873Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28157873Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29157873Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30161196Simp * SUCH DAMAGE. 31157873Simp * 32161196Simp * $FreeBSD: head/lib/libkse/thread/thr_write.c 53812 1999-11-28 05:38:13Z alfred $ 33157873Simp * 34163533Simp */ 35163533Simp#include <sys/types.h> 36163533Simp#include <sys/fcntl.h> 37163533Simp#include <sys/uio.h> 38163533Simp#include <errno.h> 39163533Simp#include <unistd.h> 40163533Simp#ifdef _THREAD_SAFE 41161196Simp#include <pthread.h> 42157873Simp#include "pthread_private.h" 43157873Simp 44157873Simpssize_t 45157873Simpwrite(int fd, const void *buf, size_t nbytes) 46157873Simp{ 47157873Simp int blocking; 48157873Simp int type; 49157873Simp ssize_t n; 50157873Simp ssize_t num = 0; 51157873Simp ssize_t ret; 52157873Simp 53157873Simp _thread_enter_cancellation_point(); 54157873Simp /* POSIX says to do just this: */ 55161196Simp if (nbytes == 0) { 56157873Simp _thread_leave_cancellation_point(); 57157873Simp return (0); 58157873Simp } 59157873Simp 60161196Simp /* Lock the file descriptor for write: */ 61157873Simp if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { 62157873Simp /* Get the read/write mode type: */ 63161196Simp type = _thread_fd_table[fd]->flags & O_ACCMODE; 64157873Simp 65161196Simp /* Check if the file is not open for write: */ 66157873Simp if (type != O_WRONLY && type != O_RDWR) { 67157873Simp /* File is not open for write: */ 68157873Simp errno = EBADF; 69157873Simp _FD_UNLOCK(fd, FD_WRITE); 70157873Simp _thread_leave_cancellation_point(); 71157873Simp return (-1); 72157873Simp } 73157873Simp 74157873Simp /* Check if file operations are to block */ 75157873Simp blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); 76157873Simp 77157873Simp /* 78157873Simp * Loop while no error occurs and until the expected number 79157873Simp * of bytes are written if performing a blocking write: 80157873Simp */ 81161196Simp while (ret == 0) { 82157873Simp /* Perform a non-blocking write syscall: */ 83161196Simp n = _thread_sys_write(fd, buf + num, nbytes - num); 84163533Simp 85157873Simp /* Check if one or more bytes were written: */ 86157873Simp if (n > 0) 87157873Simp /* 88157873Simp * Keep a count of the number of bytes 89157873Simp * written: 90157873Simp */ 91157873Simp num += n; 92157873Simp 93163533Simp /* 94163533Simp * If performing a blocking write, check if the 95157873Simp * write would have blocked or if some bytes 96163533Simp * were written but there are still more to 97161196Simp * write: 98157873Simp */ 99157873Simp if (blocking && ((n < 0 && (errno == EWOULDBLOCK || 100157873Simp errno == EAGAIN)) || (n >= 0 && num < nbytes))) { 101157873Simp _thread_run->data.fd.fd = fd; 102157873Simp _thread_kern_set_timeout(NULL); 103157873Simp 104157873Simp /* Reset the interrupted operation flag: */ 105157873Simp _thread_run->interrupted = 0; 106157873Simp 107157873Simp _thread_kern_sched_state(PS_FDW_WAIT, 108157873Simp __FILE__, __LINE__); 109157873Simp 110157873Simp /* 111157873Simp * Check if the operation was 112157873Simp * interrupted by a signal 113157873Simp */ 114157873Simp if (_thread_run->interrupted) { 115157873Simp /* Return an error: */ 116157873Simp ret = -1; 117157873Simp } 118157873Simp 119157873Simp /* 120157873Simp * If performing a non-blocking write or if an 121163533Simp * error occurred, just return whatever the write 122163533Simp * syscall did: 123157873Simp */ 124157873Simp } else if (!blocking || n < 0) { 125161196Simp /* A non-blocking call might return zero: */ 126157873Simp ret = n; 127157873Simp break; 128157873Simp 129157873Simp /* Check if the write has completed: */ 130157873Simp } else if (num >= nbytes) 131157873Simp /* Return the number of bytes written: */ 132157873Simp ret = num; 133157873Simp } 134157873Simp _FD_UNLOCK(fd, FD_RDWR); 135157873Simp } 136163533Simp _thread_leave_cancellation_point(); 137163533Simp return (ret); 138161196Simp} 139161196Simp#endif 140157873Simp