User-space scheduling for system processes

This commit is contained in:
Erik van der Kouwe 2010-07-01 08:32:33 +00:00
parent b17e3adb60
commit 23284ee7bd
40 changed files with 490 additions and 1166 deletions

View file

@ -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"

View file

@ -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."

View file

@ -4,4 +4,6 @@ PROG= service
BINDIR= /bin
MAN=
CPPFLAGS+= -I${MINIXSRCDIR}
.include <bsd.prog.mk>

View file

@ -32,6 +32,10 @@
#include <sys/stat.h>
#include <configfile.h>
#include <machine/archtypes.h>
#include <timers.h>
#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:

View file

@ -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.

View file

@ -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 \

View file

@ -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 <sys/types.h>
#include <limits.h>
#include <stdio.h>
#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

View file

@ -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 */

View file

@ -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;

View file

@ -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)

View file

@ -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) );

View file

@ -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? */

View file

@ -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 */

View file

@ -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])

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -1,7 +1,7 @@
.include <bsd.own.mk>
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

View file

@ -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"

View file

@ -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 <bsd.lib.mk>

View file

@ -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));
}

View file

@ -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 <bsd.man.mk>
.include <bsd.subdir.mk>

View file

@ -1,781 +0,0 @@
.\"-
.\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
.\" Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org>
.\" 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.

View file

@ -18,8 +18,10 @@
#include "pm.h"
#include <sys/wait.h>
#include <assert.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/sched.h>
#include <minix/vm.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
@ -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);

View file

@ -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

View file

@ -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) );

View file

@ -1,86 +1,72 @@
#include "pm.h"
#include <assert.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>
#include <minix/sched.h>
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <machine/archtypes.h>
#include <lib.h>
#include "mproc.h"
#include <machine/archtypes.h>
#include <timers.h>
#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;
}

View file

@ -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 <sys/resource.h>
#include <sys/stat.h>
#include <minix/callnr.h>
#include <minix/com.h>
@ -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 *
*===========================================================================*/

View file

@ -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;

View file

@ -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)
{

View file

@ -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));

View file

@ -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;
}

View file

@ -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. */

View file

@ -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;

View file

@ -6,6 +6,10 @@
#include "inc.h"
#include <assert.h>
#include <minix/sched.h>
#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;
}

View file

@ -55,6 +55,7 @@ PUBLIC int main(void)
}
switch(call_nr) {
case SCHEDULING_INHERIT:
case SCHEDULING_START:
result = do_start_scheduling(&m_in);
break;

View file

@ -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,

View file

@ -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 */

View file

@ -9,6 +9,7 @@
*/
#include "sched.h"
#include "schedproc.h"
#include <assert.h>
#include <minix/com.h>
#include <machine/archtypes.h>
#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;

View file

@ -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);
}