Home | History | Annotate | Line # | Download | only in libshmif
shmif_user.c revision 1.1.34.1
      1  1.1.34.1  pgoyette /*      $NetBSD: shmif_user.c,v 1.1.34.1 2018/04/07 04:12:20 pgoyette Exp $	*/
      2       1.1     pooka 
      3       1.1     pooka /*-
      4       1.1     pooka  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
      5       1.1     pooka  *
      6       1.1     pooka  * Redistribution and use in source and binary forms, with or without
      7       1.1     pooka  * modification, are permitted provided that the following conditions
      8       1.1     pooka  * are met:
      9       1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     10       1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     11       1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     13       1.1     pooka  *    documentation and/or other materials provided with the distribution.
     14       1.1     pooka  *
     15       1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16       1.1     pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17       1.1     pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18       1.1     pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19       1.1     pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20       1.1     pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21       1.1     pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22       1.1     pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23       1.1     pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24       1.1     pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25       1.1     pooka  * SUCH DAMAGE.
     26       1.1     pooka  */
     27       1.1     pooka #ifndef _KERNEL
     28       1.1     pooka #include <sys/types.h>
     29       1.1     pooka #include <sys/mman.h>
     30       1.1     pooka 
     31       1.1     pooka #include <errno.h>
     32  1.1.34.1  pgoyette #include <unistd.h>
     33       1.1     pooka 
     34       1.1     pooka #include <rump/rumpuser_component.h>
     35       1.1     pooka 
     36       1.1     pooka #include "shmif_user.h"
     37       1.1     pooka 
     38       1.1     pooka #define seterr(_v_) if ((_v_) == -1) *error = errno; else *error = 0;
     39       1.1     pooka 
     40       1.1     pooka /*
     41       1.1     pooka  * On BSD we use kqueue, on Linux we use inotify.  The underlying
     42       1.1     pooka  * interface requirements aren't quite the same, but we have a very
     43       1.1     pooka  * good chance of doing the fd->path mapping on Linux thanks to dcache,
     44       1.1     pooka  * so just keep the existing interfaces for now.
     45       1.1     pooka  */
     46       1.1     pooka #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) \
     47       1.1     pooka     || defined(__OpenBSD__)
     48       1.1     pooka #include <sys/event.h>
     49       1.1     pooka 
     50       1.1     pooka #include <stdlib.h>
     51       1.1     pooka 
     52       1.1     pooka int
     53       1.1     pooka rumpcomp_shmif_watchsetup(int *kqp, int fd)
     54       1.1     pooka {
     55       1.1     pooka 	struct kevent kev;
     56       1.1     pooka 	int rv, kq;
     57       1.1     pooka 
     58       1.1     pooka 	kq = *kqp;
     59       1.1     pooka 	if (kq == -1) {
     60       1.1     pooka 		kq = kqueue();
     61       1.1     pooka 		if (kq == -1) {
     62       1.1     pooka 			rv = errno;
     63       1.1     pooka 			goto out;
     64       1.1     pooka 		}
     65       1.1     pooka 	}
     66       1.1     pooka 
     67       1.1     pooka 	EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR,
     68       1.1     pooka 	    NOTE_WRITE, 0, 0);
     69       1.1     pooka 	if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) {
     70       1.1     pooka 		rv = errno;
     71       1.1     pooka 	} else {
     72       1.1     pooka 		rv = 0;
     73       1.1     pooka 		*kqp = kq;
     74       1.1     pooka 	}
     75       1.1     pooka 
     76       1.1     pooka  out:
     77       1.1     pooka 	return rumpuser_component_errtrans(rv);
     78       1.1     pooka }
     79       1.1     pooka 
     80       1.1     pooka int
     81       1.1     pooka rumpcomp_shmif_watchwait(int kq)
     82       1.1     pooka {
     83       1.1     pooka 	void *cookie;
     84       1.1     pooka 	struct kevent kev;
     85       1.1     pooka 	int rv;
     86       1.1     pooka 
     87       1.1     pooka 	cookie = rumpuser_component_unschedule();
     88       1.1     pooka 	do {
     89       1.1     pooka 		rv = kevent(kq, NULL, 0, &kev, 1, NULL);
     90       1.1     pooka 	} while (rv == -1 && errno == EINTR);
     91       1.1     pooka 	if (rv == -1) {
     92       1.1     pooka 		rv = errno;
     93       1.1     pooka 	} else {
     94       1.1     pooka 		rv = 0;
     95       1.1     pooka 	}
     96       1.1     pooka 	rumpuser_component_schedule(cookie);
     97       1.1     pooka 
     98       1.1     pooka 	return rumpuser_component_errtrans(rv);
     99       1.1     pooka }
    100       1.1     pooka 
    101       1.1     pooka #elif defined(__linux__)
    102       1.1     pooka #include <sys/inotify.h>
    103       1.1     pooka 
    104       1.1     pooka #include <limits.h>
    105       1.1     pooka #include <stdio.h>
    106       1.1     pooka 
    107       1.1     pooka int
    108       1.1     pooka rumpcomp_shmif_watchsetup(int *inotifyp, int fd)
    109       1.1     pooka {
    110       1.1     pooka 	char procbuf[PATH_MAX], linkbuf[PATH_MAX];
    111       1.1     pooka 	ssize_t nn;
    112       1.1     pooka 	int inotify, rv;
    113       1.1     pooka 
    114       1.1     pooka 	inotify = *inotifyp;
    115       1.1     pooka 	if (inotify == -1) {
    116       1.1     pooka 		inotify = inotify_init();
    117       1.1     pooka 		if (inotify == -1) {
    118       1.1     pooka 			rv = errno;
    119       1.1     pooka 			goto out;
    120       1.1     pooka 		}
    121       1.1     pooka 	}
    122       1.1     pooka 
    123       1.1     pooka 	/* ok, need to map fd into path for inotify */
    124       1.1     pooka 	snprintf(procbuf, sizeof(procbuf), "/proc/self/fd/%d", fd);
    125       1.1     pooka 	nn = readlink(procbuf, linkbuf, sizeof(linkbuf)-1);
    126       1.1     pooka 	if (nn >= (ssize_t)sizeof(linkbuf)-1) {
    127       1.1     pooka 		nn = -1;
    128       1.1     pooka 		errno = E2BIG; /* pick something */
    129       1.1     pooka 	}
    130       1.1     pooka 	if (nn == -1) {
    131       1.1     pooka 		rv = errno;
    132       1.1     pooka 		close(inotify);
    133       1.1     pooka 		goto out;
    134       1.1     pooka 	}
    135       1.1     pooka 
    136       1.1     pooka 	linkbuf[nn] = '\0';
    137       1.1     pooka 	if (inotify_add_watch(inotify, linkbuf, IN_MODIFY) == -1) {
    138       1.1     pooka 		rv = errno;
    139       1.1     pooka 		close(inotify);
    140       1.1     pooka 		goto out;
    141       1.1     pooka 	}
    142       1.1     pooka 	rv = 0;
    143       1.1     pooka 	*inotifyp = inotify;
    144       1.1     pooka 
    145       1.1     pooka  out:
    146       1.1     pooka 	return rumpuser_component_errtrans(rv);
    147       1.1     pooka }
    148       1.1     pooka 
    149       1.1     pooka int
    150       1.1     pooka rumpcomp_shmif_watchwait(int kq)
    151       1.1     pooka {
    152       1.1     pooka 	struct inotify_event iev;
    153       1.1     pooka 	void *cookie;
    154       1.1     pooka 	ssize_t nn;
    155       1.1     pooka 	int rv;
    156       1.1     pooka 
    157       1.1     pooka 	cookie = rumpuser_component_unschedule();
    158       1.1     pooka 	do {
    159       1.1     pooka 		nn = read(kq, &iev, sizeof(iev));
    160       1.1     pooka 	} while (nn == -1 && errno == EINTR);
    161       1.1     pooka 	if (nn == -1) {
    162       1.1     pooka 		rv = errno;
    163       1.1     pooka 	} else {
    164       1.1     pooka 		rv = 0;
    165       1.1     pooka 	}
    166       1.1     pooka 
    167       1.1     pooka 	rumpuser_component_schedule(cookie);
    168       1.1     pooka 
    169       1.1     pooka 	return rumpuser_component_errtrans(rv);
    170       1.1     pooka }
    171       1.1     pooka 
    172       1.1     pooka #else
    173       1.1     pooka #include <stdio.h>
    174       1.1     pooka 
    175       1.1     pooka /* a polling default implementation */
    176       1.1     pooka int
    177       1.1     pooka rumpcomp_shmif_watchsetup(int *nono, int fd)
    178       1.1     pooka {
    179       1.1     pooka 	static int warned = 0;
    180       1.1     pooka 
    181       1.1     pooka 	if (!warned) {
    182       1.1     pooka 		fprintf(stderr, "WARNING: rumpuser writewatchfile routines are "
    183       1.1     pooka 		    "polling-only on this platform\n");
    184       1.1     pooka 		warned = 1;
    185       1.1     pooka 	}
    186       1.1     pooka 
    187       1.1     pooka 	return 0;
    188       1.1     pooka }
    189       1.1     pooka 
    190       1.1     pooka int
    191       1.1     pooka rumpcomp_shmif_watchwait(int kq)
    192       1.1     pooka {
    193       1.1     pooka 	void *cookie;
    194       1.1     pooka 
    195       1.1     pooka 	cookie = rumpuser_component_unschedule();
    196       1.1     pooka 	usleep(10000);
    197       1.1     pooka 	rumpuser_component_schedule(cookie);
    198       1.1     pooka 
    199       1.1     pooka 	return 0;
    200       1.1     pooka }
    201       1.1     pooka #endif
    202       1.1     pooka 
    203       1.1     pooka int
    204       1.1     pooka rumpcomp_shmif_mmap(int fd, size_t len, void **memp)
    205       1.1     pooka {
    206       1.1     pooka 	void *mem;
    207       1.1     pooka 	int rv;
    208       1.1     pooka 
    209       1.1     pooka 	if (ftruncate(fd, len) == -1) {
    210       1.1     pooka 		rv = errno;
    211       1.1     pooka 		goto out;
    212       1.1     pooka 	}
    213       1.1     pooka 
    214       1.1     pooka #if defined(__sun__) && !defined(MAP_FILE)
    215       1.1     pooka #define MAP_FILE 0
    216       1.1     pooka #endif
    217       1.1     pooka 
    218       1.1     pooka 	mem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
    219       1.1     pooka 	if (mem == MAP_FAILED) {
    220       1.1     pooka 		rv = errno;
    221       1.1     pooka 	} else {
    222       1.1     pooka 		rv = 0;
    223       1.1     pooka 		*memp = mem;
    224       1.1     pooka 	}
    225       1.1     pooka 
    226       1.1     pooka  out:
    227       1.1     pooka 	return rumpuser_component_errtrans(rv);
    228       1.1     pooka }
    229       1.1     pooka #endif
    230