thr_write.c revision 36830
167480Smarkm/*
289806Sdavidc * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
367480Smarkm * All rights reserved.
467480Smarkm *
567480Smarkm * Redistribution and use in source and binary forms, with or without
667480Smarkm * modification, are permitted provided that the following conditions
767480Smarkm * are met:
889806Sdavidc * 1. Redistributions of source code must retain the above copyright
989806Sdavidc *    notice, this list of conditions and the following disclaimer.
1089806Sdavidc * 2. Redistributions in binary form must reproduce the above copyright
1167480Smarkm *    notice, this list of conditions and the following disclaimer in the
1289806Sdavidc *    documentation and/or other materials provided with the distribution.
1367480Smarkm * 3. All advertising materials mentioning features or use of this software
1467480Smarkm *    must display the following acknowledgement:
1589806Sdavidc *	This product includes software developed by John Birrell.
1689806Sdavidc * 4. Neither the name of the author nor the names of any co-contributors
1789806Sdavidc *    may be used to endorse or promote products derived from this software
1889806Sdavidc *    without specific prior written permission.
1989806Sdavidc *
2089806Sdavidc * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
2189806Sdavidc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2289806Sdavidc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2389806Sdavidc * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2489806Sdavidc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2589806Sdavidc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2667480Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2767480Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2867480Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29274606Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3067480Smarkm * SUCH DAMAGE.
3179538Sru *
3267480Smarkm * $Id: uthread_write.c,v 1.6 1998/05/25 21:45:50 jb Exp $
3367480Smarkm *
3489806Sdavidc */
3567480Smarkm#include <sys/types.h>
36176711Sattilio#include <sys/fcntl.h>
37177962Sattilio#include <sys/uio.h>
38175169Sattilio#include <errno.h>
39175577Sattilio#include <unistd.h>
40176253Sattilio#ifdef _THREAD_SAFE
41177962Sattilio#include <pthread.h>
42177697Sbrueffer#include "pthread_private.h"
43176713Sattilio
44176253Sattiliossize_t
4589806Sdavidcwrite(int fd, const void *buf, size_t nbytes)
4667480Smarkm{
4784306Sru	int	blocking;
48176710Sattilio	int	status;
4989806Sdavidc	ssize_t n;
5067480Smarkm	ssize_t num = 0;
5194480Sdavidc	ssize_t	ret;
5289806Sdavidc
5389806Sdavidc	/* POSIX says to do just this: */
5467480Smarkm	if (nbytes == 0)
55177962Sattilio		return (0);
5689806Sdavidc
57177962Sattilio	/* Lock the file descriptor for write: */
58177962Sattilio	if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) {
59177962Sattilio		/* Check if file operations are to block */
6089806Sdavidc		blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0);
61175169Sattilio
62175169Sattilio		/*
63227588Spjd		 * Loop while no error occurs and until the expected number
64175577Sattilio		 * of bytes are written if performing a blocking write:
65227588Spjd		 */
66176711Sattilio		while (ret == 0) {
67177962Sattilio			/* Perform a non-blocking write syscall: */
68177962Sattilio			n = _thread_sys_write(fd, buf + num, nbytes - num);
69227588Spjd
70177697Sbrueffer			/* Check if one or more bytes were written: */
71227588Spjd			if (n > 0)
72176253Sattilio				/*
73176253Sattilio				 * Keep a count of the number of bytes
74176253Sattilio				 * written:
75176253Sattilio				 */
76227588Spjd				num += n;
7767480Smarkm
7889806Sdavidc			/*
7967480Smarkm			 * If performing a blocking write, check if the
8089806Sdavidc			 * write would have blocked or if some bytes
8193060Sdavidc			 * were written but there are still more to
8289806Sdavidc			 * write:
8389806Sdavidc			 */
8489806Sdavidc			if (blocking && ((n < 0 && (errno == EWOULDBLOCK ||
8589806Sdavidc			    errno == EAGAIN)) || num < nbytes)) {
8689806Sdavidc				_thread_run->data.fd.fd = fd;
8789806Sdavidc				_thread_kern_set_timeout(NULL);
88167387Sjhb
8989806Sdavidc				/* Reset the interrupted operation flag: */
9089806Sdavidc				_thread_run->interrupted = 0;
9189806Sdavidc
92167387Sjhb				_thread_kern_sched_state(PS_FDW_WAIT,
9389806Sdavidc				    __FILE__, __LINE__);
9489806Sdavidc
95167387Sjhb				/*
9689806Sdavidc				 * Check if the operation was
97176710Sattilio				 * interrupted by a signal
98176016Sattilio				 */
99194317Sattilio				if (_thread_run->interrupted) {
100194317Sattilio					/* Return an error: */
101194317Sattilio					ret = -1;
10289806Sdavidc				}
10389806Sdavidc
104176710Sattilio			/*
105176710Sattilio			 * If performing a non-blocking write or if an
106159809Smaxim			 * error occurred, just return whatever the write
107159809Smaxim			 * syscall did:
108176016Sattilio			 */
109176016Sattilio			} else if (!blocking || n < 0) {
110176016Sattilio				/* A non-blocking call might return zero: */
111176016Sattilio				ret = n;
112176016Sattilio				break;
113176016Sattilio
114176016Sattilio			/* Check if the write has completed: */
115176710Sattilio			} else if (num >= nbytes)
116176710Sattilio				/* Return the number of bytes written: */
117176710Sattilio				ret = num;
118176710Sattilio		}
11989806Sdavidc		_FD_UNLOCK(fd, FD_RDWR);
12089806Sdavidc	}
12189806Sdavidc	return (ret);
12289806Sdavidc}
12389806Sdavidc#endif
12489806Sdavidc