Home | History | Annotate | Line # | Download | only in librumpuser
rumpuser.c revision 1.64
      1  1.64   pooka /*	$NetBSD: rumpuser.c,v 1.64 2014/11/05 00:43:55 pooka Exp $	*/
      2   1.1   pooka 
      3   1.1   pooka /*
      4   1.1   pooka  * Copyright (c) 2007-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 
     28  1.18   pooka #include "rumpuser_port.h"
     29  1.18   pooka 
     30   1.1   pooka #if !defined(lint)
     31  1.64   pooka __RCSID("$NetBSD: rumpuser.c,v 1.64 2014/11/05 00:43:55 pooka Exp $");
     32   1.1   pooka #endif /* !lint */
     33   1.1   pooka 
     34  1.18   pooka #include <sys/stat.h>
     35  1.18   pooka #include <sys/time.h>
     36  1.60  justin #include <sys/types.h>
     37   1.1   pooka 
     38   1.1   pooka #include <assert.h>
     39   1.1   pooka #include <errno.h>
     40   1.1   pooka #include <fcntl.h>
     41  1.61  justin #include <netdb.h>
     42   1.2   pooka #include <signal.h>
     43   1.1   pooka #include <stdarg.h>
     44   1.1   pooka #include <stdint.h>
     45   1.1   pooka #include <stdio.h>
     46   1.1   pooka #include <stdlib.h>
     47   1.1   pooka #include <string.h>
     48   1.1   pooka #include <time.h>
     49   1.1   pooka #include <unistd.h>
     50   1.1   pooka 
     51   1.1   pooka #include <rump/rumpuser.h>
     52   1.1   pooka 
     53   1.1   pooka #include "rumpuser_int.h"
     54   1.1   pooka 
     55  1.41   pooka struct rumpuser_hyperup rumpuser__hyp;
     56  1.30   pooka 
     57   1.1   pooka int
     58  1.41   pooka rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
     59   1.8   pooka {
     60  1.63  justin 	int rv;
     61   1.8   pooka 
     62  1.30   pooka 	if (version != RUMPUSER_VERSION) {
     63  1.30   pooka 		fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
     64  1.30   pooka 		    version, RUMPUSER_VERSION);
     65  1.63  justin 		abort();
     66  1.30   pooka 	}
     67  1.30   pooka 
     68  1.63  justin 	rv = rumpuser__random_init();
     69  1.63  justin 	if (rv != 0) {
     70  1.63  justin 		ET(rv);
     71  1.30   pooka 	}
     72  1.30   pooka 
     73  1.30   pooka 	rumpuser__thrinit();
     74  1.41   pooka 	rumpuser__hyp = *hyp;
     75  1.30   pooka 
     76  1.30   pooka 	return 0;
     77   1.8   pooka }
     78   1.8   pooka 
     79   1.8   pooka int
     80  1.51   pooka rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
     81   1.1   pooka {
     82  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
     83  1.36   pooka 	struct timespec ts;
     84  1.36   pooka 	clockid_t clk;
     85   1.1   pooka 	int rv;
     86   1.1   pooka 
     87  1.36   pooka 	switch (rclk) {
     88  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
     89  1.36   pooka 		clk = CLOCK_REALTIME;
     90  1.36   pooka 		break;
     91  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
     92  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
     93  1.36   pooka 		clk = CLOCK_MONOTONIC;
     94  1.36   pooka #else
     95  1.36   pooka 		clk = CLOCK_REALTIME;
     96  1.36   pooka #endif
     97  1.36   pooka 		break;
     98  1.36   pooka 	default:
     99  1.36   pooka 		abort();
    100  1.36   pooka 	}
    101  1.36   pooka 
    102  1.47   pooka 	if (clock_gettime(clk, &ts) == -1) {
    103  1.45   pooka 		rv = errno;
    104  1.45   pooka 	} else {
    105  1.45   pooka 		*sec = ts.tv_sec;
    106  1.45   pooka 		*nsec = ts.tv_nsec;
    107  1.45   pooka 		rv = 0;
    108   1.1   pooka 	}
    109   1.1   pooka 
    110  1.47   pooka 	ET(rv);
    111  1.36   pooka }
    112  1.36   pooka 
    113  1.36   pooka int
    114  1.51   pooka rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
    115  1.36   pooka {
    116  1.51   pooka 	enum rumpclock rclk = enum_rumpclock;
    117  1.36   pooka 	struct timespec rqt, rmt;
    118  1.36   pooka 	int nlocks;
    119  1.36   pooka 	int rv;
    120  1.36   pooka 
    121  1.41   pooka 	rumpkern_unsched(&nlocks, NULL);
    122  1.36   pooka 
    123  1.36   pooka 	/*LINTED*/
    124  1.36   pooka 	rqt.tv_sec = sec;
    125  1.36   pooka 	/*LINTED*/
    126  1.36   pooka 	rqt.tv_nsec = nsec;
    127   1.1   pooka 
    128  1.51   pooka 	switch (rclk) {
    129  1.36   pooka 	case RUMPUSER_CLOCK_RELWALL:
    130  1.36   pooka 		do {
    131  1.36   pooka 			rv = nanosleep(&rqt, &rmt);
    132  1.36   pooka 			rqt = rmt;
    133  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    134  1.36   pooka 		if (rv == -1) {
    135  1.36   pooka 			rv = errno;
    136  1.36   pooka 		}
    137  1.36   pooka 		break;
    138  1.36   pooka 	case RUMPUSER_CLOCK_ABSMONO:
    139  1.36   pooka 		do {
    140  1.36   pooka #ifdef HAVE_CLOCK_NANOSLEEP
    141  1.36   pooka 			rv = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
    142  1.36   pooka 			    &rqt, NULL);
    143  1.36   pooka #else
    144  1.36   pooka 			/* le/la/der/die/das sigh. timevalspec tailspin */
    145  1.36   pooka 			struct timespec ts, tsr;
    146  1.64   pooka 			if ((rv = clock_gettime(CLOCK_REALTIME, &ts)) == -1)
    147  1.64   pooka 				continue;
    148  1.36   pooka 			if (ts.tv_sec == rqt.tv_sec ?
    149  1.36   pooka 			    ts.tv_nsec > rqt.tv_nsec : ts.tv_sec > rqt.tv_sec) {
    150  1.36   pooka 				rv = 0;
    151  1.36   pooka 			} else {
    152  1.36   pooka 				tsr.tv_sec = rqt.tv_sec - ts.tv_sec;
    153  1.36   pooka 				tsr.tv_nsec = rqt.tv_nsec - ts.tv_nsec;
    154  1.36   pooka 				if (tsr.tv_nsec < 0) {
    155  1.36   pooka 					tsr.tv_sec--;
    156  1.36   pooka 					tsr.tv_nsec += 1000*1000*1000;
    157  1.36   pooka 				}
    158  1.36   pooka 				rv = nanosleep(&tsr, NULL);
    159  1.36   pooka 			}
    160  1.36   pooka #endif
    161  1.36   pooka 		} while (rv == -1 && errno == EINTR);
    162  1.36   pooka 		if (rv == -1) {
    163  1.36   pooka 			rv = errno;
    164  1.36   pooka 		}
    165  1.36   pooka 		break;
    166  1.36   pooka 	default:
    167  1.36   pooka 		abort();
    168  1.36   pooka 	}
    169  1.36   pooka 
    170  1.41   pooka 	rumpkern_sched(nlocks, NULL);
    171  1.47   pooka 
    172  1.47   pooka 	ET(rv);
    173   1.1   pooka }
    174   1.1   pooka 
    175  1.43   pooka static int
    176  1.43   pooka gethostncpu(void)
    177   1.1   pooka {
    178  1.59   pooka 	int ncpu = 1; /* unknown, really */
    179  1.43   pooka 
    180  1.59   pooka #ifdef _SC_NPROCESSORS_ONLN
    181  1.43   pooka 	ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    182  1.43   pooka #endif
    183  1.43   pooka 
    184  1.43   pooka 	return ncpu;
    185   1.1   pooka }
    186   1.1   pooka 
    187   1.1   pooka int
    188  1.43   pooka rumpuser_getparam(const char *name, void *buf, size_t blen)
    189   1.1   pooka {
    190  1.45   pooka 	int rv;
    191   1.1   pooka 
    192  1.43   pooka 	if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
    193  1.43   pooka 		int ncpu;
    194  1.43   pooka 
    195  1.43   pooka 		if (getenv_r("RUMP_NCPU", buf, blen) == -1) {
    196  1.54   pooka 			sprintf(buf, "2"); /* default */
    197  1.54   pooka 		} else if (strcmp(buf, "host") == 0) {
    198  1.43   pooka 			ncpu = gethostncpu();
    199  1.43   pooka 			snprintf(buf, blen, "%d", ncpu);
    200  1.43   pooka 		}
    201  1.45   pooka 		rv = 0;
    202  1.43   pooka 	} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
    203  1.43   pooka 		char tmp[MAXHOSTNAMELEN];
    204  1.43   pooka 
    205  1.43   pooka 		if (gethostname(tmp, sizeof(tmp)) == -1) {
    206  1.43   pooka 			snprintf(buf, blen, "rump-%05d", (int)getpid());
    207  1.43   pooka 		} else {
    208  1.43   pooka 			snprintf(buf, blen, "rump-%05d.%s",
    209  1.43   pooka 			    (int)getpid(), tmp);
    210  1.43   pooka 		}
    211  1.45   pooka 		rv = 0;
    212  1.43   pooka 	} else if (*name == '_') {
    213  1.45   pooka 		rv = EINVAL;
    214  1.13   pooka 	} else {
    215  1.43   pooka 		if (getenv_r(name, buf, blen) == -1)
    216  1.45   pooka 			rv = errno;
    217  1.43   pooka 		else
    218  1.45   pooka 			rv = 0;
    219  1.13   pooka 	}
    220  1.45   pooka 
    221  1.47   pooka 	ET(rv);
    222   1.1   pooka }
    223   1.1   pooka 
    224  1.45   pooka void
    225  1.45   pooka rumpuser_putchar(int c)
    226   1.1   pooka {
    227   1.1   pooka 
    228  1.45   pooka 	putchar(c);
    229   1.1   pooka }
    230   1.1   pooka 
    231  1.55   rmind __dead void
    232   1.1   pooka rumpuser_exit(int rv)
    233   1.1   pooka {
    234   1.1   pooka 
    235   1.1   pooka 	if (rv == RUMPUSER_PANIC)
    236   1.1   pooka 		abort();
    237   1.1   pooka 	else
    238   1.1   pooka 		exit(rv);
    239   1.1   pooka }
    240   1.1   pooka 
    241   1.1   pooka void
    242   1.1   pooka rumpuser_seterrno(int error)
    243   1.1   pooka {
    244   1.1   pooka 
    245   1.1   pooka 	errno = error;
    246   1.1   pooka }
    247   1.1   pooka 
    248  1.21   pooka /*
    249   1.1   pooka  * This is meant for safe debugging prints from the kernel.
    250   1.1   pooka  */
    251  1.45   pooka void
    252   1.1   pooka rumpuser_dprintf(const char *format, ...)
    253   1.1   pooka {
    254   1.1   pooka 	va_list ap;
    255   1.1   pooka 
    256   1.1   pooka 	va_start(ap, format);
    257  1.45   pooka 	vfprintf(stderr, format, ap);
    258   1.1   pooka 	va_end(ap);
    259   1.1   pooka }
    260   1.2   pooka 
    261   1.2   pooka int
    262  1.56   pooka rumpuser_kill(int64_t pid, int rumpsig)
    263   1.2   pooka {
    264  1.57   pooka 	int sig;
    265  1.49   pooka 
    266  1.56   pooka 	sig = rumpuser__sig_rump2host(rumpsig);
    267  1.57   pooka 	if (sig > 0)
    268  1.57   pooka 		raise(sig);
    269  1.57   pooka 	return 0;
    270   1.2   pooka }
    271