kernel, libc - add pipe2()
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 19 May 2015 18:45:09 +0000 (11:45 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 19 May 2015 18:45:09 +0000 (11:45 -0700)
* Add the pipe2() system call.

15 files changed:
include/unistd.h
lib/libc/sys/Symbol.map
lib/libc/x86_64/sys/Makefile.inc
lib/libc/x86_64/sys/pipe2.S [new file with mode: 0644]
sys/kern/init_sysent.c
sys/kern/kern_descrip.c
sys/kern/sys_pipe.c
sys/kern/syscalls.c
sys/kern/syscalls.master
sys/sys/kern_syscall.h
sys/sys/param.h
sys/sys/syscall.h
sys/sys/syscall.mk
sys/sys/sysproto.h
sys/sys/sysunion.h

index fd850fd..fbb9227 100644 (file)
@@ -350,6 +350,7 @@ off_t        lseek(int, off_t, int);
 long    pathconf(const char *, int);
 int     pause(void);
 int     pipe(int *);
+int     pipe2(int *, int);
 ssize_t         read(int, void *, size_t);
 int     rmdir(const char *);
 int     setgid(gid_t);
index 76b80be..813811d 100644 (file)
@@ -167,6 +167,7 @@ DF402.0 {
     openat;
     pathconf;
     pipe;
+    pipe2;
     poll;
     pread;
     preadv;
@@ -466,6 +467,7 @@ DFprivate_1.0 {
     __sys_openat;
     __sys_pathconf;
     __sys_pipe;
+    __sys_pipe2;
     __sys_poll;
     __sys_profil;
     __sys_pselect;
@@ -754,6 +756,7 @@ DFprivate_1.0 {
     _openat;
     _pathconf;
     _pipe;
+    _pipe2;
     _poll;
     _profil;
     _pselect;
index c7f42e1..069bf2d 100644 (file)
@@ -3,7 +3,7 @@
 
 SRCS+= amd64_get_fsbase.c amd64_get_gsbase.c amd64_set_fsbase.c amd64_set_gsbase.c
 
-MDASM= vfork.S brk.S cerror.S exect.S getcontext.S pipe.S ptrace.S \
+MDASM= vfork.S brk.S cerror.S exect.S getcontext.S pipe.S pipe2.S ptrace.S \
        reboot.S sbrk.S setlogin.S sigreturn.S
 
 # Don't generate default code for these syscalls:
diff --git a/lib/libc/x86_64/sys/pipe2.S b/lib/libc/x86_64/sys/pipe2.S
new file mode 100644 (file)
index 0000000..abdeff1
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pipe.s  5.1 (Berkeley) 4/23/90
+ * $FreeBSD: src/lib/libc/amd64/sys/pipe.S,v 1.15 2008/11/02 01:10:54 peter Exp $
+ */
+
+#include <machine/asm.h>
+#include "SYS.h"
+
+       .weak   _pipe2
+       .set    _pipe2,__sys_pipe2
+       .weak   pipe2
+       .set    pipe2,__sys_pipe2
+ENTRY(__sys_pipe2)
+       mov     $SYS_pipe2,%rax
+       KERNCALL
+       jb      1f
+       movl    %eax,(%rdi)     /* %rdi is preserved by syscall */
+       movl    %edx,4(%rdi)
+       movq    $0,%rax
+       ret
+1:
+#ifdef PIC
+       movq    PIC_GOT(HIDENAME(cerror)),%rdx
+       jmp     *%rdx
+#else
+       jmp     HIDENAME(cerror)
+#endif
+END(__sys_pipe2)
index 2d32b5f..ef08a77 100644 (file)
@@ -574,4 +574,5 @@ struct sysent sysent[] = {
        { AS(vmm_guest_sync_addr_args), (sy_call_t *)sys_vmm_guest_sync_addr }, /* 535 = vmm_guest_sync_addr */
        { AS(procctl_args), (sy_call_t *)sys_procctl }, /* 536 = procctl */
        { AS(chflagsat_args), (sy_call_t *)sys_chflagsat },     /* 537 = chflagsat */
+       { AS(pipe2_args), (sy_call_t *)sys_pipe2 },     /* 538 = pipe2 */
 };
index 9eebfe0..6c28197 100644 (file)
@@ -133,7 +133,7 @@ extern int cmask;
 /*
  * Fixup fd_freefile and fd_lastfile after a descriptor has been cleared.
  *
- * MPSAFE - must be called with fdp->fd_spin exclusively held
+ * must be called with fdp->fd_spin exclusively held
  */
 static __inline
 void
@@ -152,8 +152,6 @@ fdfixup_locked(struct filedesc *fdp, int fd)
 
 /*
  * System calls on descriptors.
- *
- * MPSAFE
  */
 int
 sys_getdtablesize(struct getdtablesize_args *uap) 
@@ -184,8 +182,6 @@ sys_getdtablesize(struct getdtablesize_args *uap)
  *
  * note: keep in mind that a potential race condition exists when closing
  * descriptors from a shared descriptor table (via rfork).
- *
- * MPSAFE
  */
 int
 sys_dup2(struct dup2_args *uap)
@@ -201,8 +197,6 @@ sys_dup2(struct dup2_args *uap)
 
 /*
  * Duplicate a file descriptor.
- *
- * MPSAFE
  */
 int
 sys_dup(struct dup_args *uap)
@@ -410,8 +404,6 @@ kern_fcntl(int fd, int cmd, union fcntl_dat *dat, struct ucred *cred)
 
 /*
  * The file control system call.
- *
- * MPSAFE
  */
 int
 sys_fcntl(struct fcntl_args *uap)
@@ -488,8 +480,6 @@ sys_fcntl(struct fcntl_args *uap)
  * to find the lowest unused file descriptor that is greater than or
  * equal to "new".  DUP_CLOEXEC, which works with either of the first
  * two flags, sets the close-on-exec flag on the "new" file descriptor.
- *
- * MPSAFE
  */
 int
 kern_dup(int flags, int old, int new, int *res)
@@ -540,7 +530,7 @@ retry:
        }
        fp = fdp->fd_files[old].fp;
        oldflags = fdp->fd_files[old].fileflags;
-       fhold(fp);      /* MPSAFE - can be called with a spinlock held */
+       fhold(fp);
 
        /*
         * Allocate a new descriptor if DUP_VARIABLE, or expand the table
@@ -681,8 +671,6 @@ retry:
  * If sigio is on the list associated with a process or process group,
  * disable signalling from the device, remove sigio from the list and
  * free sigio.
- *
- * MPSAFE
  */
 void
 funsetown(struct sigio **sigiop)
@@ -725,8 +713,6 @@ funsetown(struct sigio **sigiop)
 /*
  * Free a list of sigio structures.  Caller is responsible for ensuring
  * that the list is MPSAFE.
- *
- * MPSAFE
  */
 void
 funsetownlst(struct sigiolst *sigiolst)
@@ -742,8 +728,6 @@ funsetownlst(struct sigiolst *sigiolst)
  *
  * After permission checking, add a sigio structure to the sigio list for
  * the process or process group.
- *
- * MPSAFE
  */
 int
 fsetown(pid_t pgid, struct sigio **sigiop)
@@ -834,8 +818,6 @@ done:
 
 /*
  * This is common code for FIOGETOWN ioctl called by fcntl(fd, F_GETOWN, arg).
- *
- * MPSAFE
  */
 pid_t
 fgetown(struct sigio **sigiop)
@@ -853,8 +835,6 @@ fgetown(struct sigio **sigiop)
 
 /*
  * Close many file descriptors.
- *
- * MPSAFE
  */
 int
 sys_closefrom(struct closefrom_args *uap)
@@ -864,8 +844,6 @@ sys_closefrom(struct closefrom_args *uap)
 
 /*
  * Close all file descriptors greater then or equal to fd
- *
- * MPSAFE
  */
 int
 kern_closefrom(int fd)
@@ -902,8 +880,6 @@ kern_closefrom(int fd)
 
 /*
  * Close a file descriptor.
- *
- * MPSAFE
  */
 int
 sys_close(struct close_args *uap)
@@ -912,7 +888,7 @@ sys_close(struct close_args *uap)
 }
 
 /*
- * MPSAFE
+ * close() helper
  */
 int
 kern_close(int fd)
@@ -1000,7 +976,7 @@ sys_shutdown(struct shutdown_args *uap)
 }
 
 /*
- * MPSAFE
+ * fstat() helper
  */
 int
 kern_fstat(int fd, struct stat *ub)
@@ -1022,8 +998,6 @@ kern_fstat(int fd, struct stat *ub)
 
 /*
  * Return status information about a file descriptor.
- *
- * MPSAFE
  */
 int
 sys_fstat(struct fstat_args *uap)
@@ -1087,8 +1061,6 @@ SYSCTL_INT(_debug, OID_AUTO, fdexpand, CTLFLAG_RD, &fdexpand, 0,
  *
  * The fdp's spinlock must be held exclusively on entry and may be held
  * exclusively on return.  The spinlock may be cycled by the routine.
- *
- * MPSAFE
  */
 static void
 fdgrow_locked(struct filedesc *fdp, int want)
@@ -1168,7 +1140,7 @@ left_ancestor(int n)
  * Traverse the in-place binary tree buttom-up adjusting the allocation
  * count so scans can determine where free descriptors are located.
  *
- * MPSAFE - caller must be holding an exclusive spinlock on fdp
+ * caller must be holding an exclusive spinlock on fdp
  */
 static
 void
@@ -1185,8 +1157,6 @@ fdreserve_locked(struct filedesc *fdp, int fd, int incr)
  * Reserve a file descriptor for the process.  If no error occurs, the
  * caller MUST at some point call fsetfd() or assign a file pointer
  * or dispose of the reservation.
- *
- * MPSAFE
  */
 int
 fdalloc(struct proc *p, int want, int *result)
@@ -1309,8 +1279,6 @@ found:
 /*
  * Check to see whether n user file descriptors
  * are available to the process p.
- *
- * MPSAFE
  */
 int
 fdavail(struct proc *p, int n)
@@ -1527,8 +1495,6 @@ fdrevoke_proc_callback(struct proc *p, void *vinfo)
  *     file pointer is NOT associated with the descriptor.  If falloc
  *     returns success, fsetfd() MUST be called to either associate the
  *     file pointer or clear the reservation.
- *
- * MPSAFE
  */
 int
 falloc(struct lwp *lp, struct file **resultfp, int *resultfd)
@@ -1586,8 +1552,6 @@ done:
  * Check for races against a file descriptor by determining that the
  * file pointer is still associated with the specified file descriptor,
  * and a close is not currently in progress.
- *
- * MPSAFE
  */
 int
 checkfdclosed(struct filedesc *fdp, int fd, struct file *fp)
@@ -1611,7 +1575,7 @@ checkfdclosed(struct filedesc *fdp, int fd, struct file *fp)
  */
 
 /*
- * MPSAFE (exclusive spinlock must be held on call)
+ * (exclusive spinlock must be held on call)
  */
 static void
 fsetfd_locked(struct filedesc *fdp, struct file *fp, int fd)
@@ -1629,9 +1593,6 @@ fsetfd_locked(struct filedesc *fdp, struct file *fp, int fd)
        }
 }
 
-/*
- * MPSAFE
- */
 void
 fsetfd(struct filedesc *fdp, struct file *fp, int fd)
 {
@@ -1641,7 +1602,7 @@ fsetfd(struct filedesc *fdp, struct file *fp, int fd)
 }
 
 /*
- * MPSAFE (exclusive spinlock must be held on call)
+ * (exclusive spinlock must be held on call)
  */
 static 
 struct file *
@@ -1662,7 +1623,7 @@ funsetfd_locked(struct filedesc *fdp, int fd)
 }
 
 /*
- * MPSAFE
+ * WARNING: May not be called before initial fsetfd().
  */
 int
 fgetfdflags(struct filedesc *fdp, int fd, int *flagsp)
@@ -1683,7 +1644,7 @@ fgetfdflags(struct filedesc *fdp, int fd, int *flagsp)
 }
 
 /*
- * MPSAFE
+ * WARNING: May not be called before initial fsetfd().
  */
 int
 fsetfdflags(struct filedesc *fdp, int fd, int add_flags)
@@ -1704,7 +1665,7 @@ fsetfdflags(struct filedesc *fdp, int fd, int add_flags)
 }
 
 /*
- * MPSAFE
+ * WARNING: May not be called before initial fsetfd().
  */
 int
 fclrfdflags(struct filedesc *fdp, int fd, int rem_flags)
@@ -1787,8 +1748,6 @@ fdinit_bootstrap(struct proc *p0, struct filedesc *fdp0, int cmask)
 
 /*
  * Build a new filedesc structure.
- *
- * NOT MPSAFE (vref)
  */
 struct filedesc *
 fdinit(struct proc *p)
@@ -1833,8 +1792,6 @@ fdinit(struct proc *p)
 
 /*
  * Share a filedesc structure.
- *
- * MPSAFE
  */
 struct filedesc *
 fdshare(struct proc *p)
@@ -1850,8 +1807,6 @@ fdshare(struct proc *p)
 
 /*
  * Copy a filedesc structure.
- *
- * MPSAFE
  */
 int
 fdcopy(struct proc *p, struct filedesc **fpp)
@@ -2145,8 +2100,6 @@ fdfree(struct proc *p, struct filedesc *repl)
 
 /*
  * Retrieve and reference the file pointer associated with a descriptor.
- *
- * MPSAFE
  */
 struct file *
 holdfp(struct filedesc *fdp, int fd, int flag)
@@ -2174,8 +2127,6 @@ done:
  * holdsock() - load the struct file pointer associated
  * with a socket into *fpp.  If an error occurs, non-zero
  * will be returned and *fpp will be set to NULL.
- *
- * MPSAFE
  */
 int
 holdsock(struct filedesc *fdp, int fd, struct file **fpp)
@@ -2207,8 +2158,6 @@ done:
 
 /*
  * Convert a user file descriptor to a held file pointer.
- *
- * MPSAFE
  */
 int
 holdvnode(struct filedesc *fdp, int fd, struct file **fpp)
@@ -2460,8 +2409,6 @@ closef(struct file *fp, struct proc *p)
 }
 
 /*
- * MPSAFE
- *
  * fhold() can only be called if f_count is already at least 1 (i.e. the
  * caller of fhold() already has a reference to the file pointer in some
  * manner or other). 
@@ -2602,8 +2549,6 @@ fdopen(struct dev_open_args *ap)
 /*
  * The caller has reserved the file descriptor dfd for us.  On success we
  * must fsetfd() it.  On failure the caller will clean it up.
- *
- * MPSAFE
  */
 int
 dupfdopen(struct filedesc *fdp, int dfd, int sfd, int mode, int error)
@@ -2707,8 +2652,6 @@ filedesc_to_leader_alloc(struct filedesc_to_leader *old,
 /*
  * Scan all file pointers in the system.  The callback is made with
  * the master list spinlock held exclusively.
- *
- * MPSAFE
  */
 void
 allfiles_scan_exclusive(int (*callback)(struct file *, void *), void *data)
@@ -2869,9 +2812,6 @@ fildesc_drvinit(void *unused)
        make_dev(&fildesc_ops, 2, UID_ROOT, GID_WHEEL, 0666, "stderr");
 }
 
-/*
- * MPSAFE
- */
 struct fileops badfileops = {
        .fo_read = badfo_readwrite,
        .fo_write = badfo_readwrite,
@@ -2909,36 +2849,24 @@ badfo_kqfilter(struct file *fp, struct knote *kn)
        return (EOPNOTSUPP);
 }
 
-/*
- * MPSAFE
- */
 int
 badfo_stat(struct file *fp, struct stat *sb, struct ucred *cred)
 {
        return (EBADF);
 }
 
-/*
- * MPSAFE
- */
 int
 badfo_close(struct file *fp)
 {
        return (EBADF);
 }
 
-/*
- * MPSAFE
- */
 int
 badfo_shutdown(struct file *fp, int how)
 {
        return (EBADF);
 }
 
-/*
- * MPSAFE
- */
 int
 nofo_shutdown(struct file *fp, int how)
 {
index 951314f..d197d04 100644 (file)
@@ -46,6 +46,7 @@
 #include <sys/malloc.h>
 #include <sys/sysctl.h>
 #include <sys/socket.h>
+#include <sys/kern_syscall.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -230,6 +231,18 @@ pipe_end_uio(struct pipe *cpipe, int *ipp)
  */
 int
 sys_pipe(struct pipe_args *uap)
+{
+       return kern_pipe(uap->sysmsg_fds, 0);
+}
+
+int
+sys_pipe2(struct pipe2_args *uap)
+{
+       return kern_pipe(uap->sysmsg_fds, uap->flags);
+}
+
+int
+kern_pipe(long *fds, int flags)
 {
        struct thread *td = curthread;
        struct filedesc *fdp = td->td_proc->p_fd;
@@ -250,7 +263,7 @@ sys_pipe(struct pipe_args *uap)
                pipeclose(wpipe);
                return (error);
        }
-       uap->sysmsg_fds[0] = fd1;
+       fds[0] = fd1;
 
        /*
         * Warning: once we've gotten past allocation of the fd for the
@@ -262,6 +275,11 @@ sys_pipe(struct pipe_args *uap)
        rf->f_flag = FREAD | FWRITE;
        rf->f_ops = &pipeops;
        rf->f_data = rpipe;
+       if (flags & O_NONBLOCK)
+               rf->f_flag |= O_NONBLOCK;
+       if (flags & O_CLOEXEC)
+               fdp->fd_files[fd1].fileflags |= UF_EXCLOSE;
+
        error = falloc(td->td_lwp, &wf, &fd2);
        if (error) {
                fsetfd(fdp, NULL, fd1);
@@ -274,7 +292,12 @@ sys_pipe(struct pipe_args *uap)
        wf->f_flag = FREAD | FWRITE;
        wf->f_ops = &pipeops;
        wf->f_data = wpipe;
-       uap->sysmsg_fds[1] = fd2;
+       if (flags & O_NONBLOCK)
+               wf->f_flag |= O_NONBLOCK;
+       if (flags & O_CLOEXEC)
+               fdp->fd_files[fd2].fileflags |= UF_EXCLOSE;
+
+       fds[1] = fd2;
 
        rpipe->pipe_slock = kmalloc(sizeof(struct lock),
                                    M_PIPE, M_WAITOK|M_ZERO);
index 054204e..eddd64b 100644 (file)
@@ -546,4 +546,5 @@ const char *syscallnames[] = {
        "vmm_guest_sync_addr",                  /* 535 = vmm_guest_sync_addr */
        "procctl",                      /* 536 = procctl */
        "chflagsat",                    /* 537 = chflagsat */
+       "pipe2",                        /* 538 = pipe2 */
 };
index 7f71dc2..462cce6 100644 (file)
 535    STD     { int vmm_guest_sync_addr(long *dstaddr, long *srcaddr); }
 536    STD     { int procctl(idtype_t idtype, id_t id, int cmd, void *data); }
 537    STD     { int chflagsat(int fd, const char *path, int flags, int atflags);}
+538    STD     { int pipe2(int *fildes, int flags); }
index 4da574b..dbef8c6 100644 (file)
@@ -128,6 +128,11 @@ int kern_setsockopt(int s, struct sockopt *sopt);
 int kern_socket(int domain, int type, int protocol, int *res);
 int kern_socketpair(int domain, int type, int protocol, int *sockv);
 
+/*
+ * Prototypes for syscalls in kern/sys_pipe.c
+ */
+int kern_pipe(long *fds, int flags);
+
 /*
  * Prototypes for syscalls in kern/vfs_syscalls.c
  */
index 9331fd8..127db47 100644 (file)
  * 400103 - Milestone - availability of gcc50 in base
  * 400104 - struct lwp_params (a public struct) members renaming
  * 400105 - Switch to gcc50 as the primary compiler
+ * 400106 - Added pipe2() system call
  */
 #undef __DragonFly_version
-#define __DragonFly_version 400105     /* propagated to newvers */
+#define __DragonFly_version 400106     /* propagated to newvers */
 
 #include <sys/_null.h>
 
index 671740c..fcaf955 100644 (file)
 #define        SYS_vmm_guest_sync_addr 535
 #define        SYS_procctl     536
 #define        SYS_chflagsat   537
-#define        SYS_MAXSYSCALL  538
+#define        SYS_pipe2       538
+#define        SYS_MAXSYSCALL  539
index 796bce9..f4cf937 100644 (file)
@@ -300,4 +300,5 @@ MIASM =  \
        vmm_guest_ctl.o \
        vmm_guest_sync_addr.o \
        procctl.o \
-       chflagsat.o
+       chflagsat.o \
+       pipe2.o
index b148b1d..1fc7a63 100644 (file)
@@ -2278,6 +2278,13 @@ struct   chflagsat_args {
        int     flags;  char flags_[PAD_(int)];
        int     atflags;        char atflags_[PAD_(int)];
 };
+struct pipe2_args {
+#ifdef _KERNEL
+       struct sysmsg sysmsg;
+#endif
+       int *   fildes; char fildes_[PAD_(int *)];
+       int     flags;  char flags_[PAD_(int)];
+};
 
 #ifdef COMPAT_43
 
@@ -2885,6 +2892,7 @@ int       sys_vmm_guest_ctl (struct vmm_guest_ctl_args *);
 int    sys_vmm_guest_sync_addr (struct vmm_guest_sync_addr_args *);
 int    sys_procctl (struct procctl_args *);
 int    sys_chflagsat (struct chflagsat_args *);
+int    sys_pipe2 (struct pipe2_args *);
 
 #endif /* !_SYS_SYSPROTO_H_ */
 #undef PAD_
index cffe742..a12b9a7 100644 (file)
@@ -408,4 +408,5 @@ union sysunion {
        struct  vmm_guest_sync_addr_args vmm_guest_sync_addr;
        struct  procctl_args procctl;
        struct  chflagsat_args chflagsat;
+       struct  pipe2_args pipe2;
 };