From 23284ee7bd3371d1cea13c3a907699bddd1c2345 Mon Sep 17 00:00:00 2001 From: Erik van der Kouwe Date: Thu, 1 Jul 2010 08:32:33 +0000 Subject: [PATCH] User-space scheduling for system processes --- commands/Makefile | 2 +- commands/packman/packman.sh | 6 +- commands/service/Makefile | 2 + commands/service/service.c | 129 +++++- docs/UPDATING | 6 + include/Makefile | 4 +- include/fetch.h | 187 --------- include/minix/com.h | 13 +- include/minix/rs.h | 4 +- include/minix/syslib.h | 2 +- include/sys/stat.h | 1 - kernel/main.c | 2 +- kernel/priv.h | 4 + kernel/proc.h | 4 + kernel/system/do_fork.c | 10 +- kernel/system/do_schedctl.c | 24 +- kernel/table.c | 34 +- lib/Makefile | 2 +- lib/libc/stdtime/localtime.c | 3 - lib/libsys/Makefile | 4 + lib/libsys/sys_schedctl.c | 5 +- man/man3/Makefile | 2 +- man/man3/fetch.3 | 781 ----------------------------------- servers/pm/forkexit.c | 20 +- servers/pm/main.c | 11 +- servers/pm/proto.h | 4 +- servers/pm/schedule.c | 99 ++--- servers/pm/utility.c | 17 + servers/rs/main.c | 23 +- servers/rs/manager.c | 23 +- servers/rs/proto.h | 1 + servers/rs/request.c | 41 +- servers/rs/table.c | 31 +- servers/rs/type.h | 5 +- servers/rs/utility.c | 40 ++ servers/sched/main.c | 1 + servers/sched/proto.h | 3 +- servers/sched/schedproc.h | 3 - servers/sched/schedule.c | 70 ++-- servers/sched/utility.c | 33 +- 40 files changed, 490 insertions(+), 1166 deletions(-) diff --git a/commands/Makefile b/commands/Makefile index 8b1e0b72f..689f55ee2 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -31,7 +31,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \ telnetd term termcap tget time tinyhalt top touch tr \ truncate tsort ttt tty udpstat umount uname unexpand \ uniq unstack update urlget uud uue version vol wc \ - whereis which who write writeisofs fetch \ + whereis which who write writeisofs \ xargs yacc yes zdump zic zmodem .if ${ARCH} == "i386" diff --git a/commands/packman/packman.sh b/commands/packman/packman.sh index fe4d4eafd..f7914da90 100644 --- a/commands/packman/packman.sh +++ b/commands/packman/packman.sh @@ -102,7 +102,7 @@ then echo -n "Update package list from network? (Y/n) " y=`myread` if [ "$y" != n -a "$y" != N ] then echo "Fetching package list from $LISTURL." - fetch -o $TMPF $LISTURL && mv $TMPF $LISTFILE || echo "Update not successful." + urlget $LISTURL >$TMPF && mv $TMPF $LISTFILE || echo "Update not successful." fi netpackages=$LISTFILE if [ ! -f "$netpackages" -o ! `cat "$netpackages" 2>/dev/null | wc -l | awk '{ print $1 }'` -gt 1 ] @@ -215,7 +215,7 @@ do cd $TMPDIR case $source in net*) echo "Retrieving $packno ($packagename) from primary location into $TMPDIR .." srcurl="" - if fetch -o $file $URL1/$file + if urlget $URL1/$file >$file then echo "Retrieved ok. Installing .." packit $file && echo Installed ok. srcurl=$SRCURL1/$file @@ -225,7 +225,7 @@ do cd $TMPDIR then ( cd $SRC || myexit 2 srcfile=${packagename}-src.tar.bz2 echo "Retrieving source from $srcurl .." - fetch -o $srcfile $srcurl || myexit 3 + urlget $srcurl >$srcfile || myexit 3 echo "Source retrieved in $SRC/$srcfile." $BUNZIP2 -dc $srcfile | tar xf - >/dev/null || myexit 3 echo "Source unpacked in $SRC." diff --git a/commands/service/Makefile b/commands/service/Makefile index 5227220fc..3669beeb8 100644 --- a/commands/service/Makefile +++ b/commands/service/Makefile @@ -4,4 +4,6 @@ PROG= service BINDIR= /bin MAN= +CPPFLAGS+= -I${MINIXSRCDIR} + .include diff --git a/commands/service/service.c b/commands/service/service.c index b885df961..077da6fb0 100644 --- a/commands/service/service.c +++ b/commands/service/service.c @@ -32,6 +32,10 @@ #include #include +#include +#include +#include "kernel/proc.h" + /* This array defines all known requests. */ PRIVATE char *known_requests[] = { @@ -386,7 +390,9 @@ PRIVATE void fatal(char *fmt, ...) #define KW_SERVICE "service" #define KW_UID "uid" -#define KW_NICE "nice" +#define KW_SCHEDULER "scheduler" +#define KW_PRIORITY "priority" +#define KW_QUANTUM "quantum" #define KW_IRQ "irq" #define KW_IO "io" #define KW_PCI "pci" @@ -509,38 +515,119 @@ PRIVATE void do_uid(config_t *cpe) rs_start.rss_uid= uid; } -PRIVATE void do_nice(config_t *cpe) +PRIVATE void do_scheduler(config_t *cpe) { - int nice_val; + int scheduler_val; char *check; - /* Process a nice value */ + /* Process a scheduler value */ if (cpe->next != NULL) { - fatal("do_nice: just one nice value expected at %s:%d", + fatal("do_scheduler: just one scheduler value expected at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_SUBLIST) { - fatal("do_nice: unexpected sublist at %s:%d", + fatal("do_scheduler: unexpected sublist at %s:%d", cpe->file, cpe->line); } if (cpe->flags & CFG_STRING) { - fatal("do_nice: unexpected string at %s:%d", + fatal("do_scheduler: unexpected string at %s:%d", cpe->file, cpe->line); } - nice_val= strtol(cpe->word, &check, 0); + scheduler_val= strtol(cpe->word, &check, 0); if (check[0] != '\0') { - fatal("do_nice: bad nice value '%s' at %s:%d", + fatal("do_scheduler: bad scheduler value '%s' at %s:%d", cpe->word, cpe->file, cpe->line); } - /* Check range? */ - rs_start.rss_nice= nice_val; + if (scheduler_val != KERNEL && + (scheduler_val < 0 || scheduler_val > LAST_SPECIAL_PROC_NR)) + { + fatal("do_scheduler: scheduler %d out of range at %s:%d", + scheduler_val, cpe->file, cpe->line); + } + rs_start.rss_scheduler= (endpoint_t) scheduler_val; +} + +PRIVATE void do_priority(config_t *cpe) +{ + int priority_val; + char *check; + + /* Process a priority value */ + if (cpe->next != NULL) + { + fatal("do_priority: just one priority value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_priority: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_priority: unexpected string at %s:%d", + cpe->file, cpe->line); + } + priority_val= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_priority: bad priority value '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (priority_val < 0 || priority_val >= NR_SCHED_QUEUES) + { + fatal("do_priority: priority %d out of range at %s:%d", + priority_val, cpe->file, cpe->line); + } + rs_start.rss_priority= (unsigned) priority_val; +} + +PRIVATE void do_quantum(config_t *cpe) +{ + int quantum_val; + char *check; + + /* Process a quantum value */ + if (cpe->next != NULL) + { + fatal("do_quantum: just one quantum value expected at %s:%d", + cpe->file, cpe->line); + } + + + if (cpe->flags & CFG_SUBLIST) + { + fatal("do_quantum: unexpected sublist at %s:%d", + cpe->file, cpe->line); + } + if (cpe->flags & CFG_STRING) + { + fatal("do_quantum: unexpected string at %s:%d", + cpe->file, cpe->line); + } + quantum_val= strtol(cpe->word, &check, 0); + if (check[0] != '\0') + { + fatal("do_quantum: bad quantum value '%s' at %s:%d", + cpe->word, cpe->file, cpe->line); + } + + if (quantum_val <= 0) + { + fatal("do_quantum: quantum %d out of range at %s:%d", + quantum_val, cpe->file, cpe->line); + } + rs_start.rss_quantum= (unsigned) quantum_val; } PRIVATE void do_irq(config_t *cpe) @@ -948,9 +1035,19 @@ PRIVATE void do_service(config_t *cpe, config_t *config) do_uid(cpe->next); continue; } - if (strcmp(cpe->word, KW_NICE) == 0) + if (strcmp(cpe->word, KW_SCHEDULER) == 0) { - do_nice(cpe->next); + do_scheduler(cpe->next); + continue; + } + if (strcmp(cpe->word, KW_PRIORITY) == 0) + { + do_priority(cpe->next); + continue; + } + if (strcmp(cpe->word, KW_QUANTUM) == 0) + { + do_quantum(cpe->next); continue; } if (strcmp(cpe->word, KW_IRQ) == 0) @@ -1104,6 +1201,10 @@ PUBLIC int main(int argc, char **argv) fatal("no passwd file entry for '%s'", SERVICE_LOGIN); rs_start.rss_uid= pw->pw_uid; + rs_start.rss_scheduler= SCHED_PROC_NR; + rs_start.rss_priority= USER_Q; + rs_start.rss_quantum= 200; + if (req_config) { assert(progname); do_config(progname, req_config); @@ -1120,6 +1221,8 @@ PUBLIC int main(int argc, char **argv) rs_start.rss_ipclen= 0; } + assert(rs_start.rss_priority < NR_SCHED_QUEUES); + assert(rs_start.rss_quantum > 0); m.RS_CMD_ADDR = (char *) &rs_start; break; case RS_DOWN: diff --git a/docs/UPDATING b/docs/UPDATING index da64e79cf..e9971d219 100644 --- a/docs/UPDATING +++ b/docs/UPDATING @@ -1,3 +1,9 @@ +20100630: + protocol change between service and rs: be sure to compile commands + together with the system image and don't use the new userspace with + an old image (or vice versa); it is recommended to replace + /boot/image_big with the newly compiled image to keep option 1 in the + boot menu working. 20100625: /etc/mk has been moved to /usr/share/mk. You will need to create /usr/share/mk manually. diff --git a/include/Makefile b/include/Makefile index 18f23aae4..9e71de0cc 100644 --- a/include/Makefile +++ b/include/Makefile @@ -9,7 +9,7 @@ INCS= alloca.h ansi.h a.out.h ar.h assert.h configfile.h ctype.h \ stdint.h stdbool.h stdio.h stdlib.h string.h strings.h sysexits.h \ syslog.h tar.h termcap.h termios.h time.h timers.h tools.h \ ttyent.h ucontext.h unistd.h utime.h utmp.h wchar.h wctype.h \ - hgfs.h tzfile.h util.h fetch.h + hgfs.h tzfile.h util.h INCS+= arpa/inet.h INCS+= minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.h \ minix/com.h minix/config.h minix/const.h minix/cpufeature.h \ @@ -21,7 +21,7 @@ INCS+= minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.h \ minix/keymap.h minix/minlib.h minix/mq.h \ minix/netdriver.h minix/partition.h minix/paths.h \ minix/portio.h minix/profile.h minix/queryparam.h \ - minix/rs.h minix/safecopies.h minix/sef.h minix/sound.h \ + minix/rs.h minix/safecopies.h minix/sched.h minix/sef.h minix/sound.h \ minix/sys_config.h minix/sysinfo.h minix/syslib.h \ minix/sysutil.h minix/tty.h minix/type.h minix/types.h \ minix/u64.h minix/vfsif.h minix/vm.h \ diff --git a/include/fetch.h b/include/fetch.h index 307548643..e69de29bb 100644 --- a/include/fetch.h +++ b/include/fetch.h @@ -1,187 +0,0 @@ -/* $NetBSD: fetch.h,v 1.16 2010/01/22 13:21:09 joerg Exp $ */ -/*- - * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav - * All rights reserved. - * - * 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 - * in this position and unchanged. - * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD: fetch.h,v 1.26 2004/09/21 18:35:20 des Exp $ - */ - -#ifndef _FETCH_H_INCLUDED -#define _FETCH_H_INCLUDED - -#include -#include -#include - -#define _LIBFETCH_VER "libfetch/2.0" - -#define URL_HOSTLEN 255 -#define URL_SCHEMELEN 16 -#define URL_USERLEN 256 -#define URL_PWDLEN 256 - -typedef struct fetchIO fetchIO; - -struct url { - char scheme[URL_SCHEMELEN + 1]; - char user[URL_USERLEN + 1]; - char pwd[URL_PWDLEN + 1]; - char host[URL_HOSTLEN + 1]; - int port; - char *doc; - off_t offset; - size_t length; - time_t last_modified; -}; - -struct url_stat { - off_t size; - time_t atime; - time_t mtime; -}; - -struct url_list { - size_t length; - size_t alloc_size; - struct url *urls; -}; - -/* Recognized schemes */ -#define SCHEME_FTP "ftp" -#define SCHEME_HTTP "http" -#define SCHEME_HTTPS "https" -#define SCHEME_FILE "file" - -/* Error codes */ -#define FETCH_ABORT 1 -#define FETCH_AUTH 2 -#define FETCH_DOWN 3 -#define FETCH_EXISTS 4 -#define FETCH_FULL 5 -#define FETCH_INFO 6 -#define FETCH_MEMORY 7 -#define FETCH_MOVED 8 -#define FETCH_NETWORK 9 -#define FETCH_OK 10 -#define FETCH_PROTO 11 -#define FETCH_RESOLV 12 -#define FETCH_SERVER 13 -#define FETCH_TEMP 14 -#define FETCH_TIMEOUT 15 -#define FETCH_UNAVAIL 16 -#define FETCH_UNKNOWN 17 -#define FETCH_URL 18 -#define FETCH_VERBOSE 19 -#define FETCH_UNCHANGED 20 - -#if defined(__cplusplus) -extern "C" { -#endif - -void fetchIO_close(fetchIO *); -ssize_t fetchIO_read(fetchIO *, void *, size_t); -ssize_t fetchIO_write(fetchIO *, const void *, size_t); - -/* fetchIO-specific functions */ -fetchIO *fetchXGetFile(struct url *, struct url_stat *, const char *); -fetchIO *fetchGetFile(struct url *, const char *); -fetchIO *fetchPutFile(struct url *, const char *); -int fetchStatFile(struct url *, struct url_stat *, const char *); -int fetchListFile(struct url_list *, struct url *, const char *, - const char *); - -/* HTTP-specific functions */ -fetchIO *fetchXGetHTTP(struct url *, struct url_stat *, const char *); -fetchIO *fetchGetHTTP(struct url *, const char *); -fetchIO *fetchPutHTTP(struct url *, const char *); -int fetchStatHTTP(struct url *, struct url_stat *, const char *); -int fetchListHTTP(struct url_list *, struct url *, const char *, - const char *); - -/* FTP-specific functions */ -fetchIO *fetchXGetFTP(struct url *, struct url_stat *, const char *); -fetchIO *fetchGetFTP(struct url *, const char *); -fetchIO *fetchPutFTP(struct url *, const char *); -int fetchStatFTP(struct url *, struct url_stat *, const char *); -int fetchListFTP(struct url_list *, struct url *, const char *, - const char *); - -/* Generic functions */ -fetchIO *fetchXGetURL(const char *, struct url_stat *, const char *); -fetchIO *fetchGetURL(const char *, const char *); -fetchIO *fetchPutURL(const char *, const char *); -int fetchStatURL(const char *, struct url_stat *, const char *); -int fetchListURL(struct url_list *, const char *, const char *, - const char *); -fetchIO *fetchXGet(struct url *, struct url_stat *, const char *); -fetchIO *fetchGet(struct url *, const char *); -fetchIO *fetchPut(struct url *, const char *); -int fetchStat(struct url *, struct url_stat *, const char *); -int fetchList(struct url_list *, struct url *, const char *, - const char *); - -/* URL parsing */ -struct url *fetchMakeURL(const char *, const char *, int, - const char *, const char *, const char *); -struct url *fetchParseURL(const char *); -struct url *fetchCopyURL(const struct url *); -char *fetchStringifyURL(const struct url *); -void fetchFreeURL(struct url *); - -/* URL listening */ -void fetchInitURLList(struct url_list *); -int fetchAppendURLList(struct url_list *, const struct url_list *); -void fetchFreeURLList(struct url_list *); -char *fetchUnquotePath(struct url *); -char *fetchUnquoteFilename(struct url *); - -/* Connection caching */ -void fetchConnectionCacheInit(int, int); -void fetchConnectionCacheClose(void); - -/* Authentication */ -typedef int (*auth_t)(struct url *); -extern auth_t fetchAuthMethod; - -/* Last error code */ -extern int fetchLastErrCode; -#define MAXERRSTRING 256 -extern char fetchLastErrString[MAXERRSTRING]; - -/* I/O timeout */ -extern int fetchTimeout; - -/* Restart interrupted syscalls */ -extern volatile int fetchRestartCalls; - -/* Extra verbosity */ -extern int fetchDebug; - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/include/minix/com.h b/include/minix/com.h index b8efd12c1..5a184f4a5 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -656,6 +656,14 @@ /* Subfunctions for SYS_STATECTL */ #define SYS_STATE_CLEAR_IPC_REFS 1 /* clear IPC references */ +/* Subfunctions for SYS_SCHEDCTL */ +#define SCHEDCTL_FLAGS m1_i1 /* flags for setting the scheduler */ +# define SCHEDCTL_FLAG_KERNEL 1 /* mark kernel scheduler and remove + * RTS_NO_QUANTUM; otherwise caller is + * marked scheduler + */ +#define SCHEDCTL_ENDPOINT m1_i2 /* endpt of process to be scheduled */ + /*===========================================================================* * Messages for the Reincarnation Server * *===========================================================================*/ @@ -1104,12 +1112,15 @@ #define SCHEDULING_START (SCHEDULING_BASE+2) # define SCHEDULING_SCHEDULER m9_l1 /* Overrides _ENDPOINT on return*/ # define SCHEDULING_PARENT m9_l3 -# define SCHEDULING_NICE m9_l4 +# define SCHEDULING_MAXPRIO m9_l4 #define SCHEDULING_STOP (SCHEDULING_BASE+3) #define SCHEDULING_SET_NICE (SCHEDULING_BASE+4) +/* SCHEDULING_INHERIT is like SCHEDULING_START, but without _QUANTUM field */ +#define SCHEDULING_INHERIT (SCHEDULING_BASE+5) + #endif /* _MINIX_COM_H */ diff --git a/include/minix/rs.h b/include/minix/rs.h index 2c4bd8235..06a87005f 100644 --- a/include/minix/rs.h +++ b/include/minix/rs.h @@ -41,7 +41,9 @@ struct rs_start char *rss_cmd; size_t rss_cmdlen; uid_t rss_uid; - int rss_nice; + endpoint_t rss_scheduler; + unsigned rss_priority; + unsigned rss_quantum; int rss_major; int rss_dev_style; long rss_period; diff --git a/include/minix/syslib.h b/include/minix/syslib.h index f15e08978..9b5131f55 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -45,7 +45,7 @@ _PROTOTYPE( int sys_exit, (void)); _PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p)); _PROTOTYPE( int sys_schedule, (endpoint_t proc_ep, unsigned priority, unsigned quantum)); -_PROTOTYPE( int sys_schedctl, (endpoint_t proc_ep)); +_PROTOTYPE( int sys_schedctl, (unsigned flags, endpoint_t proc_ep)); /* Shorthands for sys_runctl() system call. */ #define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0) diff --git a/include/sys/stat.h b/include/sys/stat.h index 6402bbacf..e67580b46 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -68,7 +68,6 @@ struct stat { #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* is a socket */ #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) -#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) /* Function Prototypes. */ _PROTOTYPE( int chmod, (const char *_path, mode_t _mode) ); diff --git a/kernel/main.c b/kernel/main.c index 1ec39736d..a5801bda3 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -137,7 +137,7 @@ PUBLIC void main(void) } else { /* Don't let the process run for now. */ - RTS_SET(rp, RTS_NO_PRIV); + RTS_SET(rp, RTS_NO_PRIV | RTS_NO_QUANTUM); } if (iskerneln(proc_nr)) { /* part of the kernel? */ diff --git a/kernel/priv.h b/kernel/priv.h index 75c09de5e..1a8c1e9c4 100644 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -155,4 +155,8 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */ #define RSYS_SM ROOT_SYS_PROC_NR /* root system proc */ #define DEF_SYS_SM ROOT_SYS_PROC_NR /* default sys proc */ +/* scheduler */ +#define KERN_SCH KERNEL /* scheduled by kernel */ +#define USER_SCH SCHED_PROC_NR /* scheduled in userland */ + #endif /* PRIV_H */ diff --git a/kernel/proc.h b/kernel/proc.h index 696d01003..115bf01ac 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -236,6 +236,10 @@ struct proc { (should correspond to nice 0) */ #define MIN_USER_Q (NR_SCHED_QUEUES - 1) /* minimum priority for user processes */ +/* default scheduling quanta */ +#define USER_QUANTUM 200 +#define DRIV_QUANTUM 50 +#define SERV_QUANTUM 500 /* Magic process table addresses. */ #define BEG_PROC_ADDR (&proc[0]) diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index 248d18f7c..9f25c893d 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -86,14 +86,8 @@ PUBLIC int do_fork(struct proc * caller, message * m_ptr) rpc->p_virt_left = 0; /* disable, clear the process-virtual timers */ rpc->p_prof_left = 0; - /* - * if the child process inherited a scheduler, the child process is not - * runnable until it's scheduled. Otherwise the default kernel policy applies. - * This is only the case of system servers, drivers and similar sensitive - * processes - */ - if (rpc->p_scheduler) - RTS_SET(rpc, RTS_NO_QUANTUM); + /* the child process is not runnable until it's scheduled. */ + RTS_SET(rpc, RTS_NO_QUANTUM); make_zero64(rpc->p_cpu_time_left); make_zero64(rpc->p_cycles); diff --git a/kernel/system/do_schedctl.c b/kernel/system/do_schedctl.c index 600f4ba43..5dfe9c25a 100644 --- a/kernel/system/do_schedctl.c +++ b/kernel/system/do_schedctl.c @@ -7,17 +7,37 @@ PUBLIC int do_schedctl(struct proc * caller, message * m_ptr) { struct proc *p; + unsigned flags; int proc_nr; /* Only system processes can change process schedulers */ if (! (priv(caller)->s_flags & SYS_PROC)) return(EPERM); - if (!isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr)) + /* check parameter validity */ + flags = (unsigned) m_ptr->SCHEDCTL_FLAGS; + if (flags & ~SCHEDCTL_FLAG_KERNEL) { + printf("do_schedctl: flags 0x%x invalid, caller=%d\n", + flags, caller - proc); + return EINVAL; + } + + if (!isokendpt(m_ptr->SCHEDCTL_ENDPOINT, &proc_nr)) return EINVAL; p = proc_addr(proc_nr); - p->p_scheduler = caller; + + if ((flags & SCHEDCTL_FLAG_KERNEL) == SCHEDCTL_FLAG_KERNEL) { + /* the kernel becomes the scheduler and starts + * scheduling the process; RTS_NO_QUANTUM which was + * previously set by sys_fork is removed + */ + p->p_scheduler = NULL; + RTS_UNSET(p, RTS_NO_QUANTUM); + } else { + /* the caller becomes the scheduler */ + p->p_scheduler = caller; + } return(OK); } diff --git a/kernel/table.c b/kernel/table.c index 708214dce..86b297368 100644 --- a/kernel/table.c +++ b/kernel/table.c @@ -69,25 +69,25 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; */ PUBLIC struct boot_image image[] = { -/* process nr, flags, ms, queue, stack, name */ -{IDLE, 0, 0, 0, IDL_S, "idle" }, -{CLOCK, 0, 0, 0, IDL_S, "clock" }, -{SYSTEM, 0, 0, 0, IDL_S, "system"}, -{HARDWARE, 0, 0, 0, HRD_S, "kernel"}, +/* process nr, flags, ms, queue, stack, name */ +{IDLE, 0, 0, 0, IDL_S, "idle" }, +{CLOCK, 0, 0, 0, IDL_S, "clock" }, +{SYSTEM, 0, 0, 0, IDL_S, "system"}, +{HARDWARE, 0, 0, 0, HRD_S, "kernel"}, -{DS_PROC_NR, BVM_F, 50, 4, 0, "ds" }, -{RS_PROC_NR, 0, 50, 4, 0, "rs" }, +{DS_PROC_NR, BVM_F, DRIV_QUANTUM, 4, 0, "ds" }, +{RS_PROC_NR, 0, DRIV_QUANTUM, 4, 0, "rs" }, -{PM_PROC_NR, OVM_F,500, 4, 0, "pm" }, -{SCHED_PROC_NR,OVM_F,500, 4, 0, "sched" }, -{VFS_PROC_NR, OVM_F,500, 5, 0, "vfs" }, -{MEM_PROC_NR, BVM_F, 50, 3, 0, "memory"}, -{LOG_PROC_NR, BVM_F, 50, 2, 0, "log" }, -{TTY_PROC_NR, BVM_F, 50, 1, 0, "tty" }, -{MFS_PROC_NR, BVM_F,500, 5, 0, "mfs" }, -{VM_PROC_NR, 0,500, 2, 0, "vm" }, -{PFS_PROC_NR, BVM_F,500, 5, 0, "pfs" }, -{INIT_PROC_NR, BVM_F,200, USER_Q, 0, "init" }, +{PM_PROC_NR, OVM_F, SERV_QUANTUM, 4, 0, "pm" }, +{SCHED_PROC_NR,OVM_F, SERV_QUANTUM, 4, 0, "sched" }, +{VFS_PROC_NR, OVM_F, SERV_QUANTUM, 5, 0, "vfs" }, +{MEM_PROC_NR, BVM_F, DRIV_QUANTUM, 3, 0, "memory"}, +{LOG_PROC_NR, BVM_F, DRIV_QUANTUM, 2, 0, "log" }, +{TTY_PROC_NR, BVM_F, DRIV_QUANTUM, 1, 0, "tty" }, +{MFS_PROC_NR, BVM_F, SERV_QUANTUM, 5, 0, "mfs" }, +{VM_PROC_NR, 0, SERV_QUANTUM, 2, 0, "vm" }, +{PFS_PROC_NR, BVM_F, SERV_QUANTUM, 5, 0, "pfs" }, +{INIT_PROC_NR, BVM_F, USER_QUANTUM, USER_Q, 0, "init" }, }; /* Verify the size of the system image table at compile time. Also verify that diff --git a/lib/Makefile b/lib/Makefile index 620ea1123..5f7ad6681 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,7 +1,7 @@ .include SUBDIR= csu libc libcurses libdriver libnetdriver libend libedit libm libsys \ - libtimers libutil libbz2 libl libhgfs libz libfetch + libtimers libutil libbz2 libl libhgfs libz .if ${COMPILER_TYPE} == "ack" SUBDIR+= ack/libd ack/libe ack/libfp ack/liby diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c index 465fc5f23..c059d0140 100644 --- a/lib/libc/stdtime/localtime.c +++ b/lib/libc/stdtime/localtime.c @@ -16,9 +16,6 @@ static char elsieid[] = "@(#)localtime.c 7.99"; /*LINTLIBRARY*/ -/* Gives us offtime, timegm and a few other functions */ -#define STD_INSPIRED - #include "private.h" #include "tzfile.h" #include "fcntl.h" diff --git a/lib/libsys/Makefile b/lib/libsys/Makefile index c228fcf77..1a80971b8 100644 --- a/lib/libsys/Makefile +++ b/lib/libsys/Makefile @@ -26,6 +26,8 @@ SRCS= \ pci_set_acl.c \ pci_slot_name.c \ safecopies.c \ + sched_start.c \ + sched_stop.c \ sef.c \ sef_init.c \ sef_liveupdate.c \ @@ -119,4 +121,6 @@ SRCS= \ profile.c \ vprintf.c +CPPFLAGS.sched_start.c+= -I${MINIXSRCDIR} + .include diff --git a/lib/libsys/sys_schedctl.c b/lib/libsys/sys_schedctl.c index f552b885a..59f013d71 100644 --- a/lib/libsys/sys_schedctl.c +++ b/lib/libsys/sys_schedctl.c @@ -1,9 +1,10 @@ #include "syslib.h" -PUBLIC int sys_schedctl(endpoint_t proc_ep) +PUBLIC int sys_schedctl(unsigned flags, endpoint_t proc_ep) { message m; - m.SCHEDULING_ENDPOINT = proc_ep; + m.SCHEDCTL_FLAGS = (int) flags; + m.SCHEDCTL_ENDPOINT = proc_ep; return(_kernel_call(SYS_SCHEDCTL, &m)); } diff --git a/man/man3/Makefile b/man/man3/Makefile index 456b48bb8..2c9ac6b7b 100644 --- a/man/man3/Makefile +++ b/man/man3/Makefile @@ -12,7 +12,7 @@ MAN= abort.3 abs.3 assert.3 atof.3 bstring.3 configfile.3 \ readv.3 realpath.3 regex.3 remainder.3 resolver.3 scanf.3 \ servxcheck.3 setbuf.3 setjmp.3 sigset.3 sleep.3 stdarg.3 \ stdio.3 string.3 strtol.3 syslog.3 system.3 termcap.3 \ - termios.3 time2posix.3 ttyname.3 ttyslot.3 ungetc.3 fetch.3 + termios.3 time2posix.3 ttyname.3 ttyslot.3 ungetc.3 .include .include diff --git a/man/man3/fetch.3 b/man/man3/fetch.3 index 9b9d95502..e69de29bb 100644 --- a/man/man3/fetch.3 +++ b/man/man3/fetch.3 @@ -1,781 +0,0 @@ -.\"- -.\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav -.\" Copyright (c) 2010 Joerg Sonnenberger -.\" All rights reserved. -.\" -.\" 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. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. -.\" -.\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $ -.\" $NetBSD: fetch.3,v 1.15 2010/01/22 13:56:45 wiz Exp $ -.\" -.Dd January 22, 2010 -.Dt FETCH 3 -.Os -.Sh NAME -.Nm fetchMakeURL , -.Nm fetchParseURL , -.Nm fetchCopyURL , -.Nm fetchFreeURL , -.Nm fetchXGetURL , -.Nm fetchGetURL , -.Nm fetchPutURL , -.Nm fetchStatURL , -.Nm fetchListURL , -.Nm fetchXGet , -.Nm fetchGet , -.Nm fetchPut , -.Nm fetchStat , -.Nm fetchList , -.Nm fetchXGetFile , -.Nm fetchGetFile , -.Nm fetchPutFile , -.Nm fetchStatFile , -.Nm fetchListFile , -.Nm fetchXGetHTTP , -.Nm fetchGetHTTP , -.Nm fetchPutHTTP , -.Nm fetchStatHTTP , -.Nm fetchListHTTP , -.Nm fetchXGetFTP , -.Nm fetchGetFTP , -.Nm fetchPutFTP , -.Nm fetchStatFTP , -.Nm fetchListFTP -.Nm fetchInitURLList , -.Nm fetchFreeURLList , -.Nm fetchUnquotePath , -.Nm fetchUnquoteFilename , -.Nm fetchStringifyURL , -.Nm fetchConnectionCacheInit , -.Nm fetchConnectionCacheClose , -.Nm fetch -.Nd file transfer functions -.Sh LIBRARY -.Lb libfetch -.Sh SYNOPSIS -.In stdio.h -.In fetch.h -.Ft struct url * -.Fn fetchMakeURL "const char *scheme" "const char *host" "int port" "const char *doc" "const char *user" "const char *pwd" -.Ft struct url * -.Fn fetchParseURL "const char *URL" -.Ft struct url * -.Fn fetchCopyURL "const struct url *u" -.Ft void -.Fn fetchFreeURL "struct url *u" -.Ft fetchIO * -.Fn fetchXGetURL "const char *URL" "struct url_stat *us" "const char *flags" -.Ft fetchIO * -.Fn fetchGetURL "const char *URL" "const char *flags" -.Ft fetchIO * -.Fn fetchPutURL "const char *URL" "const char *flags" -.Ft int -.Fn fetchStatURL "const char *URL" "struct url_stat *us" "const char *flags" -.Ft int -.Fn fetchListURL "struct url_list *list" "const char *URL" "const char *flags" -.Ft fetchIO * -.Fn fetchXGet "struct url *u" "struct url_stat *us" "const char *flags" -.Ft fetchIO * -.Fn fetchGet "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchPut "struct url *u" "const char *flags" -.Ft int -.Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" -.Ft int -.Fn fetchList "struct url_list *list" "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" -.Ft fetchIO * -.Fn fetchGetFile "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchPutFile "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatFile "struct url *u" "struct url_stat *us" "const char *flags" -.Ft int -.Fn fetchListFile "struct url_list *list" "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchXGetHTTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft fetchIO * -.Fn fetchGetHTTP "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchPutHTTP "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatHTTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft int -.Fn fetchListHTTP "struct url_list *list" "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft fetchIO * -.Fn fetchGetFTP "struct url *u" "const char *flags" -.Ft fetchIO * -.Fn fetchPutFTP "struct url *u" "const char *flags" -.Ft int -.Fn fetchStatFTP "struct url *u" "struct url_stat *us" "const char *flags" -.Ft int -.Fn fetchListFTP "struct url_list *list" "struct url *u" "const char *flags" -.Ft void -.Fn fetchInitURLList "struct url_list *ul" -.Ft int -.Fn fetchAppendURLList "struct url_list *dst" "const struct url_list *src" -.Ft void -.Fn fetchFreeURLList "struct url_list *ul" -.Ft char * -.Fn fetchUnquotePath "struct url *u" -.Ft char * -.Fn fetchUnquoteFilename "struct url *u" -.Ft char * -.Fn fetchStringifyURL "const struct url *u" -.Ft void -.Fn fetchConnectionCacheInit "int global" "int per_host" -.Ft void -.Fn fetchConnectionCacheClose "void" -.Sh DESCRIPTION -These functions implement a high-level library for retrieving and -uploading files using Uniform Resource Locators (URLs). -.Pp -.Fn fetchParseURL -takes a URL in the form of a null-terminated string and splits it into -its components function according to the Common Internet Scheme Syntax -detailed in RFC 1738. -A regular expression which produces this syntax is: -.Bd -literal -offset indent -\*[Lt]scheme\*[Gt]:(//(\*[Lt]user\*[Gt](:\*[Lt]pwd\*[Gt])?@)?\*[Lt]host\*[Gt](:\*[Lt]port\*[Gt])?)?/(\*[Lt]document\*[Gt])? -.Ed -.Pp -If the URL does not seem to begin with a scheme name, it is assumed to be a local path. -Only absolute path names are accepted. -.Pp -Note that some components of the URL are not necessarily relevant to -all URL schemes. -For instance, the file scheme only needs the -.Aq scheme -and -.Aq document -components. -.Fn fetchParseURL -quotes any unsafe character in the URL automatically. -This is not done by -.Fn fetchMakeURL . -.Fn fetchCopyURL -copies an existing -.Vt url -structure. -.Pp -.Fn fetchMakeURL , -.Fn fetchParseURL , -and -.Fn fetchCopyURL -return a pointer to a -.Vt url -structure, which is defined as follows in -.In fetch.h : -.Bd -literal -#define URL_SCHEMELEN 16 -#define URL_USERLEN 256 -#define URL_PWDLEN 256 -#define URL_HOSTLEN 255 - -struct url { - char scheme[URL_SCHEMELEN + 1]; - char user[URL_USERLEN + 1]; - char pwd[URL_PWDLEN + 1]; - char host[URL_HOSTLEN + 1]; - int port; - char *doc; - off_t offset; - size_t length; - time_t last_modified; -}; -.Ed -.Pp -The pointer returned by -.Fn fetchMakeURL , -.Fn fetchCopyURL , -and -.Fn fetchParseURL -should be freed using -.Fn fetchFreeURL . -The size of -.Vt struct URL -is not part of the ABI. -.Pp -.Fn fetchXGetURL , -.Fn fetchGetURL , -and -.Fn fetchPutURL -constitute the recommended interface to the -.Nm fetch -library. -They examine the URL passed to them to determine the transfer -method, and call the appropriate lower-level functions to perform the -actual transfer. -.Fn fetchXGetURL -also returns the remote document's metadata in the -.Vt url_stat -structure pointed to by the -.Fa us -argument. -.Pp -The -.Fa flags -argument is a string of characters which specify transfer options. -The -meaning of the individual flags is scheme-dependent, and is detailed -in the appropriate section below. -.Pp -.Fn fetchStatURL -attempts to obtain the requested document's metadata and fill in the -structure pointed to by its second argument. -The -.Vt url_stat -structure is defined as follows in -.In fetch.h : -.Bd -literal -struct url_stat { - off_t size; - time_t atime; - time_t mtime; -}; -.Ed -.Pp -If the size could not be obtained from the server, the -.Fa size -field is set to \-1. -If the modification time could not be obtained from the server, the -.Fa mtime -field is set to the epoch. -If the access time could not be obtained from the server, the -.Fa atime -field is set to the modification time. -.Pp -.Fn fetchListURL -attempts to list the contents of the directory pointed to by the URL provided. -The pattern can be a simple glob-like expression as hint. -Callers should not depend on the server to filter names. -If successful, it appends the list of entries to the -.Vt url_list -structure. -The -.Vt url_list -structure is defined as follows in -.In fetch.h : -.Bd -literal -struct url_list { - size_t length; - size_t alloc_size; - struct url *urls; -}; -.Ed -.Pp -The list should be initialized by calling -.Fn fetchInitURLList -and the entries be freed by calling -.Fn fetchFreeURLList . -The function -.Fn fetchAppendURLList -can be used to append one URL lists to another. -If the -.Ql c -(cache result) flag is specified, the library is allowed to internally -cache the result. -.Pp -.Fn fetchStringifyURL -returns the URL as string. -.Fn fetchUnquotePath -returns the path name part of the URL with any quoting undone. -Query arguments and fragment identifiers are not included. -.Fn fetchUnquoteFilename -returns the last component of the path name as returned by -.Fn fetchUnquotePath . -.Fn fetchStringifyURL , -.Fn fetchUnquotePath , -and -.Fn fetchUnquoteFilename -return a string that should be deallocated with -.Fn free -after use. -.Pp -.Fn fetchConnectionCacheInit -enables the connection cache. -The first argument specifies the global limit on cached connections. -The second argument specifies the host limit. -Entries are considered to specify the same host, if the host name -from the URL is identical, indepent of the address or address family. -.Fn fetchConnectionCacheClose -flushed the connection cache and closes all cached connections. -.Pp -.Fn fetchXGet , -.Fn fetchGet , -.Fn fetchPut , -and -.Fn fetchStat -are similar to -.Fn fetchXGetURL , -.Fn fetchGetURL , -.Fn fetchPutURL , -and -.Fn fetchStatURL , -except that they expect a pre-parsed URL in the form of a pointer to -a -.Vt struct url -rather than a string. -.Pp -All of the -.Fn fetchXGetXXX , -.Fn fetchGetXXX , -and -.Fn fetchPutXXX -functions return a pointer to a stream which can be used to read or -write data from or to the requested document, respectively. -Note that -although the implementation details of the individual access methods -vary, it can generally be assumed that a stream returned by one of the -.Fn fetchXGetXXX -or -.Fn fetchGetXXX -functions is read-only, and that a stream returned by one of the -.Fn fetchPutXXX -functions is write-only. -.Sh PROTOCOL INDEPENDENT FLAGS -If the -.Ql i -(if-modified-since) flag is specified, the library will try to fetch -the content only if it is newer than -.Va last_modified . -For HTTP an -.Li If-Modified-Since -HTTP header is sent. -For FTP a -.Li MTDM -command is sent first and compared locally. -For FILE the source file is compared. -.Sh FILE SCHEME -.Fn fetchXGetFile , -.Fn fetchGetFile , -and -.Fn fetchPutFile -provide access to documents which are files in a locally mounted file -system. -Only the -.Aq document -component of the URL is used. -.Pp -.Fn fetchXGetFile -and -.Fn fetchGetFile -do not accept any flags. -.Pp -.Fn fetchPutFile -accepts the -.Ql a -(append to file) flag. -If that flag is specified, the data written to -the stream returned by -.Fn fetchPutFile -will be appended to the previous contents of the file, instead of -replacing them. -.Sh FTP SCHEME -.Fn fetchXGetFTP , -.Fn fetchGetFTP , -and -.Fn fetchPutFTP -implement the FTP protocol as described in RFC 959. -.Pp -By default -.Nm libfetch -will attempt to use passive mode first and only fallback to active mode -if the server reports a syntax error. -If the -.Ql a -(active) flag is specified, a passive connection is not tried and active mode -is used directly. -.Pp -If the -.Ql l -(low) flag is specified, data sockets will be allocated in the low (or -default) port range instead of the high port range (see -.Xr ip 4 ) . -.Pp -If the -.Ql d -(direct) flag is specified, -.Fn fetchXGetFTP , -.Fn fetchGetFTP , -and -.Fn fetchPutFTP -will use a direct connection even if a proxy server is defined. -.Pp -If no user name or password is given, the -.Nm fetch -library will attempt an anonymous login, with user name "anonymous" -and password "anonymous@\*[Lt]hostname\*[Gt]". -.Sh HTTP SCHEME -The -.Fn fetchXGetHTTP , -.Fn fetchGetHTTP , -and -.Fn fetchPutHTTP -functions implement the HTTP/1.1 protocol. -With a little luck, there is -even a chance that they comply with RFC 2616 and RFC 2617. -.Pp -If the -.Ql d -(direct) flag is specified, -.Fn fetchXGetHTTP , -.Fn fetchGetHTTP , -and -.Fn fetchPutHTTP -will use a direct connection even if a proxy server is defined. -.Pp -Since there seems to be no good way of implementing the HTTP PUT -method in a manner consistent with the rest of the -.Nm fetch -library, -.Fn fetchPutHTTP -is currently unimplemented. -.Sh AUTHENTICATION -Apart from setting the appropriate environment variables and -specifying the user name and password in the URL or the -.Vt struct url , -the calling program has the option of defining an authentication -function with the following prototype: -.Pp -.Ft int -.Fn myAuthMethod "struct url *u" -.Pp -The callback function should fill in the -.Fa user -and -.Fa pwd -fields in the provided -.Vt struct url -and return 0 on success, or any other value to indicate failure. -.Pp -To register the authentication callback, simply set -.Va fetchAuthMethod -to point at it. -The callback will be used whenever a site requires authentication and -the appropriate environment variables are not set. -.Pp -This interface is experimental and may be subject to change. -.Sh RETURN VALUES -.Fn fetchParseURL -returns a pointer to a -.Vt struct url -containing the individual components of the URL. -If it is -unable to allocate memory, or the URL is syntactically incorrect, -.Fn fetchParseURL -returns a -.Dv NULL -pointer. -.Pp -The -.Fn fetchStat -functions return 0 on success and \-1 on failure. -.Pp -All other functions return a stream pointer which may be used to -access the requested document, or -.Dv NULL -if an error occurred. -.Pp -The following error codes are defined in -.In fetch.h : -.Bl -tag -width 18n -.It Bq Er FETCH_ABORT -Operation aborted -.It Bq Er FETCH_AUTH -Authentication failed -.It Bq Er FETCH_DOWN -Service unavailable -.It Bq Er FETCH_EXISTS -File exists -.It Bq Er FETCH_FULL -File system full -.It Bq Er FETCH_INFO -Informational response -.It Bq Er FETCH_MEMORY -Insufficient memory -.It Bq Er FETCH_MOVED -File has moved -.It Bq Er FETCH_NETWORK -Network error -.It Bq Er FETCH_OK -No error -.It Bq Er FETCH_PROTO -Protocol error -.It Bq Er FETCH_RESOLV -Resolver error -.It Bq Er FETCH_SERVER -Server error -.It Bq Er FETCH_TEMP -Temporary error -.It Bq Er FETCH_TIMEOUT -Operation timed out -.It Bq Er FETCH_UNAVAIL -File is not available -.It Bq Er FETCH_UNKNOWN -Unknown error -.It Bq Er FETCH_URL -Invalid URL -.El -.Pp -The accompanying error message includes a protocol-specific error code -and message, e.g.\& "File is not available (404 Not Found)" -.Sh ENVIRONMENT -.Bl -tag -width ".Ev FETCH_BIND_ADDRESS" -.It Ev FETCH_BIND_ADDRESS -Specifies a host name or IP address to which sockets used for outgoing -connections will be bound. -.It Ev FTP_LOGIN -Default FTP login if none was provided in the URL. -.It Ev FTP_PASSIVE_MODE -If set to anything but -.Ql no , -forces the FTP code to use passive mode. -.It Ev FTP_PASSWORD -Default FTP password if the remote server requests one and none was -provided in the URL. -.It Ev FTP_PROXY -URL of the proxy to use for FTP requests. -The document part is ignored. -FTP and HTTP proxies are supported; if no scheme is specified, FTP is -assumed. -If the proxy is an FTP proxy, -.Nm libfetch -will send -.Ql user@host -as user name to the proxy, where -.Ql user -is the real user name, and -.Ql host -is the name of the FTP server. -.Pp -If this variable is set to an empty string, no proxy will be used for -FTP requests, even if the -.Ev HTTP_PROXY -variable is set. -.It Ev ftp_proxy -Same as -.Ev FTP_PROXY , -for compatibility. -.It Ev HTTP_AUTH -Specifies HTTP authorization parameters as a colon-separated list of -items. -The first and second item are the authorization scheme and realm -respectively; further items are scheme-dependent. -Currently, only basic authorization is supported. -.Pp -Basic authorization requires two parameters: the user name and -password, in that order. -.Pp -This variable is only used if the server requires authorization and -no user name or password was specified in the URL. -.It Ev HTTP_PROXY -URL of the proxy to use for HTTP requests. -The document part is ignored. -Only HTTP proxies are supported for HTTP requests. -If no port number is specified, the default is 3128. -.Pp -Note that this proxy will also be used for FTP documents, unless the -.Ev FTP_PROXY -variable is set. -.It Ev http_proxy -Same as -.Ev HTTP_PROXY , -for compatibility. -.It Ev HTTP_PROXY_AUTH -Specifies authorization parameters for the HTTP proxy in the same -format as the -.Ev HTTP_AUTH -variable. -.Pp -This variable is used if and only if connected to an HTTP proxy, and -is ignored if a user and/or a password were specified in the proxy -URL. -.It Ev HTTP_REFERER -Specifies the referrer URL to use for HTTP requests. -If set to -.Dq auto , -the document URL will be used as referrer URL. -.It Ev HTTP_USER_AGENT -Specifies the User-Agent string to use for HTTP requests. -This can be useful when working with HTTP origin or proxy servers that -differentiate between user agents. -.It Ev NETRC -Specifies a file to use instead of -.Pa ~/.netrc -to look up login names and passwords for FTP sites. -See -.Xr ftp 1 -for a description of the file format. -This feature is experimental. -.It Ev NO_PROXY -Either a single asterisk, which disables the use of proxies -altogether, or a comma- or whitespace-separated list of hosts for -which proxies should not be used. -.It Ev no_proxy -Same as -.Ev NO_PROXY , -for compatibility. -.El -.Sh EXAMPLES -To access a proxy server on -.Pa proxy.example.com -port 8080, set the -.Ev HTTP_PROXY -environment variable in a manner similar to this: -.Pp -.Dl HTTP_PROXY=http://proxy.example.com:8080 -.Pp -If the proxy server requires authentication, there are -two options available for passing the authentication data. -The first method is by using the proxy URL: -.Pp -.Dl HTTP_PROXY=http://\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt]@proxy.example.com:8080 -.Pp -The second method is by using the -.Ev HTTP_PROXY_AUTH -environment variable: -.Bd -literal -offset indent -HTTP_PROXY=http://proxy.example.com:8080 -HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt] -.Ed -.Pp -To disable the use of a proxy for an HTTP server running on the local -host, define -.Ev NO_PROXY -as follows: -.Bd -literal -offset indent -NO_PROXY=localhost,127.0.0.1 -.Ed -.Sh SEE ALSO -.\" .Xr fetch 1 , -.\" .Xr ftpio 3 , -.Xr ftp 1 , -.Xr ip 4 -.Rs -.%A J. Postel -.%A J. K. Reynolds -.%D October 1985 -.%B File Transfer Protocol -.%O RFC 959 -.Re -.Rs -.%A P. Deutsch -.%A A. Emtage -.%A A. Marine -.%D May 1994 -.%T How to Use Anonymous FTP -.%O RFC 1635 -.Re -.Rs -.%A T. Berners-Lee -.%A L. Masinter -.%A M. McCahill -.%D December 1994 -.%T Uniform Resource Locators (URL) -.%O RFC 1738 -.Re -.Rs -.%A R. Fielding -.%A J. Gettys -.%A J. Mogul -.%A H. Frystyk -.%A L. Masinter -.%A P. Leach -.%A T. Berners-Lee -.%D January 1999 -.%B Hypertext Transfer Protocol -- HTTP/1.1 -.%O RFC 2616 -.Re -.Rs -.%A J. Franks -.%A P. Hallam-Baker -.%A J. Hostetler -.%A S. Lawrence -.%A P. Leach -.%A A. Luotonen -.%A L. Stewart -.%D June 1999 -.%B HTTP Authentication: Basic and Digest Access Authentication -.%O RFC 2617 -.Re -.Sh HISTORY -The -.Nm fetch -library first appeared in -.Fx 3.0 . -.Sh AUTHORS -.An -nosplit -The -.Nm fetch -library was mostly written by -.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org -with numerous suggestions from -.An Jordan K. Hubbard Aq jkh@FreeBSD.org , -.An Eugene Skepner Aq eu@qub.com -and other -.Fx -developers. -It replaces the older -.Nm ftpio -library written by -.An Poul-Henning Kamp Aq phk@FreeBSD.org -and -.An Jordan K. Hubbard Aq jkh@FreeBSD.org . -.Pp -This manual page was written by -.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org . -.Sh BUGS -Some parts of the library are not yet implemented. -The most notable -examples of this are -.Fn fetchPutHTTP -and FTP proxy support. -.Pp -There is no way to select a proxy at run-time other than setting the -.Ev HTTP_PROXY -or -.Ev FTP_PROXY -environment variables as appropriate. -.Pp -.Nm libfetch -does not understand or obey 305 (Use Proxy) replies. -.Pp -Error numbers are unique only within a certain context; the error -codes used for FTP and HTTP overlap, as do those used for resolver and -system errors. -For instance, error code 202 means "Command not -implemented, superfluous at this site" in an FTP context and -"Accepted" in an HTTP context. -.Pp -.Fn fetchStatFTP -does not check that the result of an MDTM command is a valid date. -.Pp -The man page is incomplete, poorly written and produces badly -formatted text. -.Pp -The error reporting mechanism is unsatisfactory. -.Pp -Some parts of the code are not fully reentrant. diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index 3e5ad4570..0ea6f51bb 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -18,8 +18,10 @@ #include "pm.h" #include +#include #include #include +#include #include #include #include @@ -91,6 +93,15 @@ PUBLIC int do_fork() rmc->mp_trace_flags = 0; sigemptyset(&rmc->mp_sigtrace); } + + /* Some system servers like to call regular fork, such as RS spawning + * recovery scripts; in this case PM will take care of their scheduling + * because RS cannot do so for non-system processes */ + if (rmc->mp_flags & PRIV_PROC) { + assert(rmc->mp_scheduler == NONE); + rmc->mp_scheduler = SCHED_PROC_NR; + } + /* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */ rmc->mp_flags &= (IN_USE|DELAY_CALL); rmc->mp_child_utime = 0; /* reset administration */ @@ -364,7 +375,7 @@ int dump_core; /* flag indicating whether to dump core */ */ int r; - if((r = sched_stop(rmp)) != OK) { + if((r = sched_stop(rmp->mp_scheduler, rmp->mp_endpoint)) != OK) { /* If the scheduler refuses to give up scheduling, there is * little we can do, except report it. This may cause problems * later on, if this scheduler is asked to schedule another proc @@ -375,6 +386,13 @@ int dump_core; /* flag indicating whether to dump core */ "scheduling %s, ret=%d.\n", rmp->mp_name, r); } + /* sched_stop is either called when the process is exiting or it is + * being moved between schedulers. If it is being moved between + * schedulers, we need to set the mp_scheduler to NONE so that PM + * doesn't forward messages to the process' scheduler while being moved + * (such as sched_nice). */ + rmp->mp_scheduler = NONE; + /* For core dumps, now is the right time to try to contact the parent. */ if (dump_core) zombify(rmp); diff --git a/servers/pm/main.c b/servers/pm/main.c index 20d65f7b5..17a9732e3 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -252,6 +252,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) rmp->mp_parent = INIT_PROC_NR; rmp->mp_procgrp = rmp->mp_pid = INIT_PID; rmp->mp_flags |= IN_USE; + + /* Set scheduling info */ + rmp->mp_scheduler = KERNEL; } else { /* system process */ if(ip->proc_nr == RS_PROC_NR) { @@ -262,14 +265,14 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) } rmp->mp_pid = get_free_pid(); rmp->mp_flags |= IN_USE | PRIV_PROC; + + /* RS schedules this process */ + rmp->mp_scheduler = NONE; } /* Get kernel endpoint identifier. */ rmp->mp_endpoint = ip->endpoint; - /* Set scheduling info */ - rmp->mp_scheduler = KERNEL; - /* Tell VFS about this system process. */ mess.m_type = PM_INIT; mess.PM_SLOT = ip->proc_nr; @@ -493,7 +496,7 @@ PRIVATE void handle_vfs_reply() /* Schedule the newly created process ... */ r = (OK); if (rmp->mp_scheduler != KERNEL && rmp->mp_scheduler != NONE) { - r = sched_start(rmp->mp_scheduler, rmp, 0); + r = sched_start_user(rmp->mp_scheduler, rmp); } /* If scheduling the process failed, we want to tear down the process diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 48ce66389..4a216ba84 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -63,8 +63,7 @@ _PROTOTYPE( int do_getsetpriority, (void) ); /* schedule.c */ _PROTOTYPE( void sched_init, (void) ); -_PROTOTYPE( int sched_start, (endpoint_t ep, struct mproc *rmp, int flags) ); -_PROTOTYPE( int sched_stop, (struct mproc *rmp) ); +_PROTOTYPE( int sched_start_user, (endpoint_t ep, struct mproc *rmp) ); _PROTOTYPE( int sched_nice, (struct mproc *rmp, int nice) ); /* profile.c */ @@ -108,5 +107,6 @@ _PROTOTYPE( pid_t get_free_pid, (void) ); _PROTOTYPE( int no_sys, (void) ); _PROTOTYPE( char *find_param, (const char *key) ); _PROTOTYPE( struct mproc *find_proc, (pid_t lpid) ); +_PROTOTYPE( int nice_to_priority, (int nice, unsigned *new_q) ); _PROTOTYPE( int pm_isokendpt, (int ep, int *proc) ); _PROTOTYPE( void tell_vfs, (struct mproc *rmp, message *m_ptr) ); diff --git a/servers/pm/schedule.c b/servers/pm/schedule.c index 0ddd56bf4..107e1c13a 100644 --- a/servers/pm/schedule.c +++ b/servers/pm/schedule.c @@ -1,86 +1,72 @@ #include "pm.h" +#include #include #include #include +#include #include #include #include #include #include "mproc.h" +#include +#include +#include "kernel/proc.h" + /*===========================================================================* * init_scheduling * *===========================================================================*/ PUBLIC void sched_init(void) { struct mproc *trmp; - int proc_nr; - + endpoint_t parent_e; + int proc_nr, s; + for (proc_nr=0, trmp=mproc; proc_nr < NR_PROCS; proc_nr++, trmp++) { /* Don't take over system processes. When the system starts, - * this will typically only take over init, from which other - * user space processes will inherit. */ + * init is blocked on RTS_NO_QUANTUM until PM assigns a + * scheduler, from which other. Given that all other user + * processes are forked from init and system processes are + * managed by RS, there should be no other process that needs + * to be assigned a scheduler here */ if (trmp->mp_flags & IN_USE && !(trmp->mp_flags & PRIV_PROC)) { - if (sched_start(SCHED_PROC_NR, trmp, - (SEND_PRIORITY | SEND_TIME_SLICE))) { - printf("PM: SCHED denied taking over scheduling of %s\n", - trmp->mp_name); + assert(_ENDPOINT_P(trmp->mp_endpoint) == INIT_PROC_NR); + parent_e = mproc[trmp->mp_parent].mp_endpoint; + assert(parent_e == trmp->mp_endpoint); + s = sched_start(SCHED_PROC_NR, /* scheduler_e */ + trmp->mp_endpoint, /* schedulee_e */ + parent_e, /* parent_e */ + USER_Q, /* maxprio */ + USER_QUANTUM, /* quantum */ + &trmp->mp_scheduler); /* *newsched_e */ + if (s != OK) { + printf("PM: SCHED denied taking over scheduling of %s: %d\n", + trmp->mp_name, s); } } - } + } } /*===========================================================================* - * sched_start * + * sched_start_user * *===========================================================================*/ -PUBLIC int sched_start(endpoint_t ep, struct mproc *rmp, int flags) +PUBLIC int sched_start_user(endpoint_t ep, struct mproc *rmp) { + unsigned maxprio; int rv; - message m; - m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; - m.SCHEDULING_PARENT = mproc[rmp->mp_parent].mp_endpoint; - m.SCHEDULING_NICE = rmp->mp_nice; - - /* Send the request to the scheduler */ - if ((rv = _taskcall(ep, SCHEDULING_START, &m))) { + /* convert nice to priority */ + if ((rv = nice_to_priority(rmp->mp_nice, &maxprio)) != OK) { return rv; } - - /* Store the process' scheduler. Note that this might not be the - * scheduler we sent the SCHEDULING_START message to. That scheduler - * might have forwarded the scheduling message on to another scheduler - * before returning the message. - */ - rmp->mp_scheduler = m.SCHEDULING_SCHEDULER; - return (OK); -} - -/*===========================================================================* - * sched_stop * - *===========================================================================*/ -PUBLIC int sched_stop(struct mproc *rmp) -{ - int rv; - message m; - - /* If the kernel is the scheduler, it will implicitly stop scheduling - * once another process takes over or the process terminates */ - if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE) - return(OK); - - m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; - if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_STOP, &m))) { - return rv; - } - - /* sched_stop is either called when the process is exiting or it is - * being moved between schedulers. If it is being moved between - * schedulers, we need to set the mp_scheduler to NONE so that PM - * doesn't forward messages to the process' scheduler while being moved - * (such as sched_nice). */ - rmp->mp_scheduler = NONE; - return (OK); + + /* inherit quantum */ + return sched_inherit(ep, /* scheduler_e */ + rmp->mp_endpoint, /* schedulee_e */ + mproc[rmp->mp_parent].mp_endpoint, /* parent_e */ + maxprio, /* maxprio */ + &rmp->mp_scheduler); /* *newsched_e */ } /*===========================================================================* @@ -90,6 +76,7 @@ PUBLIC int sched_nice(struct mproc *rmp, int nice) { int rv; message m; + unsigned maxprio; /* If the kernel is the scheduler, we don't allow messing with the * priority. If you want to control process priority, assign the process @@ -97,8 +84,12 @@ PUBLIC int sched_nice(struct mproc *rmp, int nice) if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE) return (EINVAL); + if ((rv = nice_to_priority(nice, &maxprio)) != OK) { + return rv; + } + m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; - m.SCHEDULING_NICE = nice; + m.SCHEDULING_MAXPRIO = (int) maxprio; if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_SET_NICE, &m))) { return rv; } diff --git a/servers/pm/utility.c b/servers/pm/utility.c index 2dd6e73f3..b76ab396c 100644 --- a/servers/pm/utility.c +++ b/servers/pm/utility.c @@ -5,11 +5,13 @@ * no_sys: called for invalid system call numbers * find_param: look up a boot monitor parameter * find_proc: return process pointer from pid number + * nice_to_priority convert nice level to priority queue * pm_isokendpt: check the validity of an endpoint * tell_vfs: send a request to VFS on behalf of a process */ #include "pm.h" +#include #include #include #include @@ -102,6 +104,21 @@ pid_t lpid; return(NULL); } +/*===========================================================================* + * nice_to_priority * + *===========================================================================*/ +PUBLIC int nice_to_priority(int nice, unsigned* new_q) +{ + if (nice < PRIO_MIN || nice > PRIO_MAX) return(EINVAL); + + *new_q = MAX_USER_Q + (nice-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / + (PRIO_MAX-PRIO_MIN+1); + if (*new_q < MAX_USER_Q) *new_q = MAX_USER_Q; /* shouldn't happen */ + if (*new_q > MIN_USER_Q) *new_q = MIN_USER_Q; /* shouldn't happen */ + + return (OK); +} + /*===========================================================================* * pm_isokendpt * *===========================================================================*/ diff --git a/servers/rs/main.c b/servers/rs/main.c index 27723f003..68f92382b 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -156,7 +156,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the reincarnation server. */ struct boot_image *ip; - int s,i,j; + int s,i,j, usersched; int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs; struct rproc *rp; struct rproc *replica_rp; @@ -351,7 +351,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) rpub->vm_call_mask, VM_RQ_BASE, TRUE); /* Get some settings from the boot image table. */ - rp->r_nice = ip->priority; + rp->r_scheduler = boot_image_priv->sched; + rp->r_priority = ip->priority; + rp->r_quantum = ip->quantum; rpub->endpoint = ip->endpoint; /* Set some defaults. */ @@ -373,8 +375,12 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) } /* - Step 2: allow every system service in the boot image to run. + * first start kernel-scheduled servers, including the PM and the + * scheduler which are needed to be able to start the + * user-space-scheduled processes */ nr_uncaught_init_srvs = 0; + for (usersched=0; usersched <= 1; usersched++) { for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) { boot_image_priv = &boot_image_priv_table[i]; @@ -388,6 +394,11 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) continue; } + /* Kernel-scheduled processes first */ + if ((boot_image_priv->sched == KERNEL) ? usersched : !usersched) { + continue; + } + /* Lookup the corresponding slot in the system process table. */ rp = &rproc[boot_image_priv - boot_image_priv_table]; rpub = rp->r_pub; @@ -397,6 +408,10 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) panic("unable to initialize privileges: %d", s); } + if ((s = sched_init_proc(rp)) != OK) { + panic("unable to initialize scheduling: %d", s); + } + /* Initialize service. We assume every service will always get * back to us here at boot time. */ @@ -422,6 +437,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) catch_boot_init_ready(ANY); nr_uncaught_init_srvs--; } + } /* - Step 4: all the system services in the boot image are now running. * Complete the initialization of the system process table in collaboration @@ -538,6 +554,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) if(s != OK) { panic("unable to let the new RS instance run: %d", s); } + if ((s = sched_init_proc(replica_rp)) != OK) { + panic("unable to initialize RS replica scheduling: %d", s); + } /* Synchronize with the new instance and go to sleep. */ m.m_type = RS_INIT; diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 6aa0684c7..33ab8af9b 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -7,6 +7,8 @@ #include "inc.h" +#include "kernel/proc.h" + /*===========================================================================* * caller_is_root * *===========================================================================*/ @@ -370,8 +372,8 @@ char *file; int line; struct rproc *rp; { -/* Ask PM to exit the service and free slot. */ struct rprocpub *rpub; + int s; rpub = rp->r_pub; @@ -379,6 +381,12 @@ struct rproc *rp; printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp), file, line); + /* Tell scheduler this process is finished */ + if ((s = sched_stop(rp->r_scheduler, rpub->endpoint)) != OK) { + printf("RS: warning: scheduler won't give up process: %d\n", s); + } + + /* Ask PM to exit the service */ if(rp->r_pid == -1) { printf("RS: warning: attempt to kill pid -1!\n"); } @@ -386,6 +394,7 @@ struct rproc *rp; srv_kill(rp->r_pid, SIGKILL); } + /* Free slot */ free_slot(rp); } @@ -461,6 +470,13 @@ struct rproc *rp; return ENOMEM; } + /* Set the scheduler for this process */ + if ((s = sched_init_proc(rp)) != OK) { + printf("unable to start scheduling: %d\n", s); + cleanup_service(rp); + return s; + } + /* Copy the executable image into the child process. If this call * fails, the child process may or may not be killed already. If it is * not killed, it's blocked because of NO_PRIV. Kill it now either way. @@ -1252,7 +1268,10 @@ endpoint_t source; rp->r_script[rs_start->rss_scriptlen] = '\0'; } rp->r_uid= rs_start->rss_uid; - rp->r_nice= rs_start->rss_nice; + + rp->r_scheduler= rs_start->rss_scheduler; + rp->r_priority= rs_start->rss_priority; + rp->r_quantum= rs_start->rss_quantum; if (rs_start->rss_flags & RSS_IPC_VALID) { diff --git a/servers/rs/proto.h b/servers/rs/proto.h index 03d075ac6..932c66402 100644 --- a/servers/rs/proto.h +++ b/servers/rs/proto.h @@ -92,6 +92,7 @@ _PROTOTYPE( char* srv_to_string, (struct rproc *rp)); _PROTOTYPE( void reply, (endpoint_t who, message *m_ptr)); _PROTOTYPE( void late_reply, (struct rproc *rp, int code)); _PROTOTYPE( int rs_isokendpt, (endpoint_t endpoint, int *proc)); +_PROTOTYPE( int sched_init_proc, (struct rproc *rp)); /* memory.c */ _PROTOTYPE( void* rs_startup_sbrk, (size_t size)); diff --git a/servers/rs/request.c b/servers/rs/request.c index ad3de02dd..105c90027 100755 --- a/servers/rs/request.c +++ b/servers/rs/request.c @@ -5,6 +5,10 @@ #include "inc.h" +#include "kernel/proc.h" + +FORWARD int check_request(struct rs_start *rs_start); + /*===========================================================================* * do_up * *===========================================================================*/ @@ -35,6 +39,10 @@ message *m_ptr; /* request message pointer */ if (r != OK) { return r; } + r = check_request(&rs_start); + if (r != OK) { + return r; + } noblock = (rs_start.rss_flags & RSS_NOBLOCK); /* Initialize the slot as requested. */ @@ -385,6 +393,10 @@ PUBLIC int do_update(message *m_ptr) return s; } noblock = (rs_start.rss_flags & RSS_NOBLOCK); + s = check_request(&rs_start); + if (s != OK) { + return s; + } /* Copy label. */ s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr, @@ -614,7 +626,7 @@ message *m_ptr; * check and, if so request the system service's status. */ else if (now - rp->r_check_tm > rpub->period) { - notify(rpub->endpoint); /* request status */ + notify(rpub->endpoint); /* request status */ rp->r_check_tm = now; /* mark time */ } } @@ -739,3 +751,30 @@ message *m_ptr; return OK; } +/*===========================================================================* + * check_request * + *===========================================================================*/ +PRIVATE int check_request(struct rs_start *rs_start) +{ + /* Verify scheduling parameters */ + if (rs_start->rss_scheduler != KERNEL && + (rs_start->rss_scheduler < 0 || + rs_start->rss_scheduler > LAST_SPECIAL_PROC_NR)) { + printf("RS: check_request: invalid scheduler %d\n", + rs_start->rss_scheduler); + return EINVAL; + } + if (rs_start->rss_priority >= NR_SCHED_QUEUES) { + printf("RS: check_request: priority %u out of range\n", + rs_start->rss_priority); + return EINVAL; + } + if (rs_start->rss_quantum <= 0) { + printf("RS: check_request: quantum %u out of range\n", + rs_start->rss_quantum); + return EINVAL; + } + + return OK; +} + diff --git a/servers/rs/table.c b/servers/rs/table.c index 9a5650f34..1246fa435 100644 --- a/servers/rs/table.c +++ b/servers/rs/table.c @@ -58,23 +58,24 @@ PRIVATE int /* Definition of the boot image priv table. The order of entries in this table * reflects the order boot system services are made runnable and initialized - * at boot time. + * at boot time, except for the fact that kernel-scheduled services are + * handled before user-scheduled ones. */ PUBLIC struct boot_image_priv boot_image_priv_table[] = { -/*endpoint, label, flags, traps, ipcto, sigmgr, kcalls, vmcalls, T */ -{RS_PROC_NR, "rs", RSYS_F, RSYS_T, RSYS_M, RSYS_SM, rs_kc, rs_vmc, 0 }, -{VM_PROC_NR, "vm", VM_F, SRV_T, SRV_M, SRV_SM, vm_kc, vm_vmc, 0 }, -{PM_PROC_NR, "pm", SRV_F, SRV_T, SRV_M, SRV_SM, pm_kc, pm_vmc, 0 }, -{SCHED_PROC_NR,"sched", SRV_F, SRV_T, SRV_M, SRV_SM, sched_kc, sched_vmc, 0 }, -{VFS_PROC_NR, "vfs", SRV_F, SRV_T, SRV_M, SRV_SM, vfs_kc, vfs_vmc, 0 }, -{DS_PROC_NR, "ds", SRV_F, SRV_T, SRV_M, SRV_SM, ds_kc, ds_vmc, 0 }, -{TTY_PROC_NR, "tty", SRV_F, SRV_T, SRV_M, SRV_SM, tty_kc, tty_vmc, 0 }, -{MEM_PROC_NR, "memory", SRV_F, SRV_T, SRV_M, SRV_SM, mem_kc, mem_vmc, 0 }, -{LOG_PROC_NR, "log", SRV_F, SRV_T, SRV_M, SRV_SM, log_kc, log_vmc, 0 }, -{MFS_PROC_NR,"fs_imgrd", SRV_F, SRV_T, SRV_M, SRV_SM, mfs_kc, mfs_vmc, 0 }, -{PFS_PROC_NR, "pfs", SRV_F, SRV_T, SRV_M, SRV_SM, pfs_kc, pfs_vmc, 0 }, -{INIT_PROC_NR, "init", RUSR_F, RUSR_T, RUSR_M, RUSR_SM, rusr_kc, rusr_vmc,0 }, -{NULL_BOOT_NR, "", 0, 0, 0, 0, no_kc, no_vmc, 0 } +/*endpoint, label, flags, traps, ipcto, sigmgr, sched, kcalls, vmcalls, T */ +{RS_PROC_NR, "rs", RSYS_F, RSYS_T, RSYS_M, RSYS_SM, KERN_SCH, rs_kc, rs_vmc, 0 }, +{VM_PROC_NR, "vm", VM_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, vm_kc, vm_vmc, 0 }, +{PM_PROC_NR, "pm", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, pm_kc, pm_vmc, 0 }, +{SCHED_PROC_NR,"sched", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, sched_kc, sched_vmc, 0 }, +{VFS_PROC_NR, "vfs", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, vfs_kc, vfs_vmc, 0 }, +{DS_PROC_NR, "ds", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, ds_kc, ds_vmc, 0 }, +{TTY_PROC_NR, "tty", SRV_F, SRV_T, SRV_M, SRV_SM, USER_SCH, tty_kc, tty_vmc, 0 }, +{MEM_PROC_NR, "memory", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, mem_kc, mem_vmc, 0 }, +{LOG_PROC_NR, "log", SRV_F, SRV_T, SRV_M, SRV_SM, USER_SCH, log_kc, log_vmc, 0 }, +{MFS_PROC_NR,"fs_imgrd", SRV_F, SRV_T, SRV_M, SRV_SM, KERN_SCH, mfs_kc, mfs_vmc, 0 }, +{PFS_PROC_NR, "pfs", SRV_F, SRV_T, SRV_M, SRV_SM, USER_SCH, pfs_kc, pfs_vmc, 0 }, +{INIT_PROC_NR, "init", RUSR_F, RUSR_T, RUSR_M, RUSR_SM, NONE, rusr_kc, rusr_vmc,0 }, +{NULL_BOOT_NR, "", 0, 0, 0, 0, 0, no_kc, no_vmc, 0 } }; /* Definition of the boot image sys table. */ diff --git a/servers/rs/type.h b/servers/rs/type.h index d61f698bf..0180c175e 100644 --- a/servers/rs/type.h +++ b/servers/rs/type.h @@ -12,6 +12,7 @@ struct boot_image_priv { short trap_mask; /* allowed system call traps */ int ipc_to; /* send mask protection */ endpoint_t sig_mgr; /* signal manager */ + endpoint_t sched; /* scheduler */ int *k_calls; /* allowed kernel calls */ int *vm_calls; /* allowed vm calls */ long period; /* heartbeat period (or zero) */ @@ -67,7 +68,9 @@ struct rproc { * kernel. */ uid_t r_uid; - int r_nice; + endpoint_t r_scheduler; /* scheduler */ + unsigned r_priority; + unsigned r_quantum; char r_ipc_list[MAX_IPC_LIST]; int r_nr_control; diff --git a/servers/rs/utility.c b/servers/rs/utility.c index 8deff09de..cf5e46e56 100644 --- a/servers/rs/utility.c +++ b/servers/rs/utility.c @@ -6,6 +6,10 @@ #include "inc.h" +#include +#include +#include "kernel/proc.h" + /*===========================================================================* * init_service * *===========================================================================*/ @@ -172,3 +176,39 @@ PUBLIC int rs_isokendpt(endpoint_t endpoint, int *proc) return OK; } +/*===========================================================================* + * sched_init_proc * + *===========================================================================*/ +PUBLIC int sched_init_proc(struct rproc *rp) +{ + int s; + + switch (rp->r_scheduler) { + + case NONE: + /* don't touch user processes, PM deals with them */ + assert(!(rp->r_priv.s_flags & SYS_PROC)); + break; + + case KERNEL: + /* Confirm kernel scheduler to remove RTS_NO_QUANTUM */ + assert(rp->r_priv.s_flags & SYS_PROC); + if ((s = sys_schedctl(SCHEDCTL_FLAG_KERNEL, + rp->r_pub->endpoint)) != OK) { + panic("unable to kernel-schedule service: %d", s); + } + break; + + default: + /* tell scheduler to schedule this one */ + assert(rp->r_priv.s_flags & SYS_PROC); + if ((s = sched_start(rp->r_scheduler, rp->r_pub->endpoint, + RS_PROC_NR, rp->r_priority, rp->r_quantum, + &rp->r_scheduler)) != OK) { + return s; + } + break; + } + + return OK; +} diff --git a/servers/sched/main.c b/servers/sched/main.c index fd9604036..5a51da7b9 100644 --- a/servers/sched/main.c +++ b/servers/sched/main.c @@ -55,6 +55,7 @@ PUBLIC int main(void) } switch(call_nr) { + case SCHEDULING_INHERIT: case SCHEDULING_START: result = do_start_scheduling(&m_in); break; diff --git a/servers/sched/proto.h b/servers/sched/proto.h index 8c1bb3893..e6312f23e 100644 --- a/servers/sched/proto.h +++ b/servers/sched/proto.h @@ -19,8 +19,7 @@ _PROTOTYPE( void init_scheduling, (void) ); _PROTOTYPE( int no_sys, (int who_e, int call_nr) ); _PROTOTYPE( int sched_isokendpt, (int ep, int *proc) ); _PROTOTYPE( int sched_isemtyendpt, (int ep, int *proc) ); -_PROTOTYPE( int is_from_pm, (message *m_ptr) ); -_PROTOTYPE( int nice_to_priority, (int nice, unsigned *new_q) ); +_PROTOTYPE( int accept_message, (message *m_ptr) ); /* timers.c */ _PROTOTYPE( void sched_set_timer, (timer_t *tp, int delta, diff --git a/servers/sched/schedproc.h b/servers/sched/schedproc.h index d2d131a05..508a7515d 100644 --- a/servers/sched/schedproc.h +++ b/servers/sched/schedproc.h @@ -19,9 +19,6 @@ EXTERN struct schedproc { endpoint_t parent; /* parent endpoint id */ unsigned flags; /* flag bits */ - /* Scheduling priority. */ - signed int nice; /* nice is PRIO_MIN..PRIO_MAX, standard 0. */ - /* User space scheduling */ unsigned max_priority; /* this process' highest allowed priority */ unsigned priority; /* the process' current priority */ diff --git a/servers/sched/schedule.c b/servers/sched/schedule.c index ddaafff48..b3e56486e 100644 --- a/servers/sched/schedule.c +++ b/servers/sched/schedule.c @@ -9,6 +9,7 @@ */ #include "sched.h" #include "schedproc.h" +#include #include #include #include "kernel/proc.h" /* for queue constants */ @@ -58,7 +59,7 @@ PUBLIC int do_stop_scheduling(message *m_ptr) int rv, proc_nr_n; /* Only accept stop messages from PM */ - if (!is_from_pm(m_ptr)) + if (!accept_message(m_ptr)) return EPERM; if (sched_isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n) != OK) { @@ -79,10 +80,14 @@ PUBLIC int do_stop_scheduling(message *m_ptr) PUBLIC int do_start_scheduling(message *m_ptr) { register struct schedproc *rmp; - int rv, proc_nr_n, parent_nr_n; + int rv, proc_nr_n, parent_nr_n, nice; + + /* we can handle two kinds of messages here */ + assert(m_ptr->m_type == SCHEDULING_START || + m_ptr->m_type == SCHEDULING_INHERIT); /* Only accept start messages from PM */ - if (!is_from_pm(m_ptr)) + if (!accept_message(m_ptr)) return EPERM; /* Resolve endpoint to proc slot. */ @@ -95,36 +100,42 @@ PUBLIC int do_start_scheduling(message *m_ptr) /* Populate process slot */ rmp->endpoint = m_ptr->SCHEDULING_ENDPOINT; rmp->parent = m_ptr->SCHEDULING_PARENT; - rmp->nice = m_ptr->SCHEDULING_NICE; - - /* Find maximum priority from nice value */ - rv = nice_to_priority(rmp->nice, &rmp->max_priority); - if (rv != OK) - return rv; - - /* Inherit current priority and time slice from parent. Since there - * is currently only one scheduler scheduling the whole system, this - * value is local and we assert that the parent endpoint is valid */ - if (rmp->endpoint == rmp->parent) { - /* We have a special case here for init, which is the first - process scheduled, and the parent of itself. */ - rmp->priority = USER_Q; - rmp->time_slice = DEFAULT_USER_TIME_SLICE; - + rmp->max_priority = (unsigned) m_ptr->SCHEDULING_MAXPRIO; + if (rmp->max_priority >= NR_SCHED_QUEUES) { + return EINVAL; } - else { + + switch (m_ptr->m_type) { + + case SCHEDULING_START: + /* We have a special case here for system processes, for which + * quanum and priority are set explicitly rather than inherited + * from the parent */ + rmp->priority = rmp->max_priority; + rmp->time_slice = (unsigned) m_ptr->SCHEDULING_QUANTUM; + break; + + case SCHEDULING_INHERIT: + /* Inherit current priority and time slice from parent. Since there + * is currently only one scheduler scheduling the whole system, this + * value is local and we assert that the parent endpoint is valid */ if ((rv = sched_isokendpt(m_ptr->SCHEDULING_PARENT, &parent_nr_n)) != OK) return rv; rmp->priority = schedproc[parent_nr_n].priority; rmp->time_slice = schedproc[parent_nr_n].time_slice; + break; + + default: + /* not reachable */ + assert(0); } /* Take over scheduling the process. The kernel reply message populates * the processes current priority and its time slice */ - if ((rv = sys_schedctl(rmp->endpoint)) != OK) { - printf("Sched: Error overtaking scheduling for %d, kernel said %d\n", + if ((rv = sys_schedctl(0, rmp->endpoint)) != OK) { + printf("Sched: Error taking over scheduling for %d, kernel said %d\n", rmp->endpoint, rv); return rv; } @@ -157,12 +168,10 @@ PUBLIC int do_nice(message *m_ptr) struct schedproc *rmp; int rv; int proc_nr_n; - int nice; unsigned new_q, old_q, old_max_q; - int old_nice; /* Only accept nice messages from PM */ - if (!is_from_pm(m_ptr)) + if (!accept_message(m_ptr)) return EPERM; if (sched_isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n) != OK) { @@ -172,26 +181,23 @@ PUBLIC int do_nice(message *m_ptr) } rmp = &schedproc[proc_nr_n]; - nice = m_ptr->SCHEDULING_NICE; - - if ((rv = nice_to_priority(nice, &new_q)) != OK) - return rv; + new_q = (unsigned) m_ptr->SCHEDULING_MAXPRIO; + if (new_q >= NR_SCHED_QUEUES) { + return EINVAL; + } /* Store old values, in case we need to roll back the changes */ old_q = rmp->priority; old_max_q = rmp->max_priority; - old_nice = rmp->nice; /* Update the proc entry and reschedule the process */ rmp->max_priority = rmp->priority = new_q; - rmp->nice = nice; if ((rv = schedule_process(rmp)) != OK) { /* Something went wrong when rescheduling the process, roll * back the changes to proc struct */ rmp->priority = old_q; rmp->max_priority = old_max_q; - rmp->nice = old_nice; } return rv; diff --git a/servers/sched/utility.c b/servers/sched/utility.c index db0ca27e4..6ffa6f8ec 100644 --- a/servers/sched/utility.c +++ b/servers/sched/utility.c @@ -4,8 +4,7 @@ * no_sys: called for invalid system call numbers * sched_isokendpt: check the validity of an endpoint * sched_isemtyendpt check for validity and availability of endpoint slot - * is_from_pm check whether message is originated from PM - * nice_to_priority convert nice level to priority queue + * accept_message check whether message is allowed */ #include "sched.h" @@ -58,27 +57,19 @@ PUBLIC int sched_isemtyendpt(int endpoint, int *proc) } /*===========================================================================* - * is_from_pm * + * accept_message * *===========================================================================*/ -PUBLIC int is_from_pm(message *m_ptr) +PUBLIC int accept_message(message *m_ptr) { - if (m_ptr->m_source == PM_PROC_NR) { - return 1; + /* accept all messages from PM and RS */ + switch (m_ptr->m_source) { + + case PM_PROC_NR: + case RS_PROC_NR: + return 1; + } + + /* no other messages are allowable */ return 0; } - -/*===========================================================================* - * nice_to_priority * - *===========================================================================*/ -PUBLIC int nice_to_priority(int nice, unsigned* new_q) -{ - if (nice < PRIO_MIN || nice > PRIO_MAX) return(EINVAL); - - *new_q = MAX_USER_Q + (nice-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / - (PRIO_MAX-PRIO_MIN+1); - if (*new_q < MAX_USER_Q) *new_q = MAX_USER_Q; /* shouldn't happen */ - if (*new_q > MIN_USER_Q) *new_q = MIN_USER_Q; /* shouldn't happen */ - - return (OK); -}