User-space scheduling for system processes
This commit is contained in:
parent
b17e3adb60
commit
23284ee7bd
40 changed files with 490 additions and 1166 deletions
|
@ -31,7 +31,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
||||||
telnetd term termcap tget time tinyhalt top touch tr \
|
telnetd term termcap tget time tinyhalt top touch tr \
|
||||||
truncate tsort ttt tty udpstat umount uname unexpand \
|
truncate tsort ttt tty udpstat umount uname unexpand \
|
||||||
uniq unstack update urlget uud uue version vol wc \
|
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
|
xargs yacc yes zdump zic zmodem
|
||||||
|
|
||||||
.if ${ARCH} == "i386"
|
.if ${ARCH} == "i386"
|
||||||
|
|
|
@ -102,7 +102,7 @@ then echo -n "Update package list from network? (Y/n) "
|
||||||
y=`myread`
|
y=`myread`
|
||||||
if [ "$y" != n -a "$y" != N ]
|
if [ "$y" != n -a "$y" != N ]
|
||||||
then echo "Fetching package list from $LISTURL."
|
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
|
fi
|
||||||
netpackages=$LISTFILE
|
netpackages=$LISTFILE
|
||||||
if [ ! -f "$netpackages" -o ! `cat "$netpackages" 2>/dev/null | wc -l | awk '{ print $1 }'` -gt 1 ]
|
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
|
case $source in
|
||||||
net*) echo "Retrieving $packno ($packagename) from primary location into $TMPDIR .."
|
net*) echo "Retrieving $packno ($packagename) from primary location into $TMPDIR .."
|
||||||
srcurl=""
|
srcurl=""
|
||||||
if fetch -o $file $URL1/$file
|
if urlget $URL1/$file >$file
|
||||||
then echo "Retrieved ok. Installing .."
|
then echo "Retrieved ok. Installing .."
|
||||||
packit $file && echo Installed ok.
|
packit $file && echo Installed ok.
|
||||||
srcurl=$SRCURL1/$file
|
srcurl=$SRCURL1/$file
|
||||||
|
@ -225,7 +225,7 @@ do cd $TMPDIR
|
||||||
then ( cd $SRC || myexit 2
|
then ( cd $SRC || myexit 2
|
||||||
srcfile=${packagename}-src.tar.bz2
|
srcfile=${packagename}-src.tar.bz2
|
||||||
echo "Retrieving source from $srcurl .."
|
echo "Retrieving source from $srcurl .."
|
||||||
fetch -o $srcfile $srcurl || myexit 3
|
urlget $srcurl >$srcfile || myexit 3
|
||||||
echo "Source retrieved in $SRC/$srcfile."
|
echo "Source retrieved in $SRC/$srcfile."
|
||||||
$BUNZIP2 -dc $srcfile | tar xf - >/dev/null || myexit 3
|
$BUNZIP2 -dc $srcfile | tar xf - >/dev/null || myexit 3
|
||||||
echo "Source unpacked in $SRC."
|
echo "Source unpacked in $SRC."
|
||||||
|
|
|
@ -4,4 +4,6 @@ PROG= service
|
||||||
BINDIR= /bin
|
BINDIR= /bin
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
|
CPPFLAGS+= -I${MINIXSRCDIR}
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <configfile.h>
|
#include <configfile.h>
|
||||||
|
|
||||||
|
#include <machine/archtypes.h>
|
||||||
|
#include <timers.h>
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
|
||||||
|
|
||||||
/* This array defines all known requests. */
|
/* This array defines all known requests. */
|
||||||
PRIVATE char *known_requests[] = {
|
PRIVATE char *known_requests[] = {
|
||||||
|
@ -386,7 +390,9 @@ PRIVATE void fatal(char *fmt, ...)
|
||||||
|
|
||||||
#define KW_SERVICE "service"
|
#define KW_SERVICE "service"
|
||||||
#define KW_UID "uid"
|
#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_IRQ "irq"
|
||||||
#define KW_IO "io"
|
#define KW_IO "io"
|
||||||
#define KW_PCI "pci"
|
#define KW_PCI "pci"
|
||||||
|
@ -509,38 +515,119 @@ PRIVATE void do_uid(config_t *cpe)
|
||||||
rs_start.rss_uid= uid;
|
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;
|
char *check;
|
||||||
|
|
||||||
/* Process a nice value */
|
/* Process a scheduler value */
|
||||||
if (cpe->next != NULL)
|
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);
|
cpe->file, cpe->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (cpe->flags & CFG_SUBLIST)
|
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);
|
cpe->file, cpe->line);
|
||||||
}
|
}
|
||||||
if (cpe->flags & CFG_STRING)
|
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);
|
cpe->file, cpe->line);
|
||||||
}
|
}
|
||||||
nice_val= strtol(cpe->word, &check, 0);
|
scheduler_val= strtol(cpe->word, &check, 0);
|
||||||
if (check[0] != '\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);
|
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)
|
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);
|
do_uid(cpe->next);
|
||||||
continue;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(cpe->word, KW_IRQ) == 0)
|
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);
|
fatal("no passwd file entry for '%s'", SERVICE_LOGIN);
|
||||||
rs_start.rss_uid= pw->pw_uid;
|
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) {
|
if (req_config) {
|
||||||
assert(progname);
|
assert(progname);
|
||||||
do_config(progname, req_config);
|
do_config(progname, req_config);
|
||||||
|
@ -1120,6 +1221,8 @@ PUBLIC int main(int argc, char **argv)
|
||||||
rs_start.rss_ipclen= 0;
|
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;
|
m.RS_CMD_ADDR = (char *) &rs_start;
|
||||||
break;
|
break;
|
||||||
case RS_DOWN:
|
case RS_DOWN:
|
||||||
|
|
|
@ -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:
|
20100625:
|
||||||
/etc/mk has been moved to /usr/share/mk. You will need to
|
/etc/mk has been moved to /usr/share/mk. You will need to
|
||||||
create /usr/share/mk manually.
|
create /usr/share/mk manually.
|
||||||
|
|
|
@ -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 \
|
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 \
|
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 \
|
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+= arpa/inet.h
|
||||||
INCS+= minix/a.out.h minix/bitmap.h minix/callnr.h minix/cdrom.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 \
|
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/keymap.h minix/minlib.h minix/mq.h \
|
||||||
minix/netdriver.h minix/partition.h minix/paths.h \
|
minix/netdriver.h minix/partition.h minix/paths.h \
|
||||||
minix/portio.h minix/profile.h minix/queryparam.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/sys_config.h minix/sysinfo.h minix/syslib.h \
|
||||||
minix/sysutil.h minix/tty.h minix/type.h minix/types.h \
|
minix/sysutil.h minix/tty.h minix/type.h minix/types.h \
|
||||||
minix/u64.h minix/vfsif.h minix/vm.h \
|
minix/u64.h minix/vfsif.h minix/vm.h \
|
||||||
|
|
187
include/fetch.h
187
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 <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
|
|
|
@ -656,6 +656,14 @@
|
||||||
/* Subfunctions for SYS_STATECTL */
|
/* Subfunctions for SYS_STATECTL */
|
||||||
#define SYS_STATE_CLEAR_IPC_REFS 1 /* clear IPC references */
|
#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 *
|
* Messages for the Reincarnation Server *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -1104,12 +1112,15 @@
|
||||||
#define SCHEDULING_START (SCHEDULING_BASE+2)
|
#define SCHEDULING_START (SCHEDULING_BASE+2)
|
||||||
# define SCHEDULING_SCHEDULER m9_l1 /* Overrides _ENDPOINT on return*/
|
# define SCHEDULING_SCHEDULER m9_l1 /* Overrides _ENDPOINT on return*/
|
||||||
# define SCHEDULING_PARENT m9_l3
|
# define SCHEDULING_PARENT m9_l3
|
||||||
# define SCHEDULING_NICE m9_l4
|
# define SCHEDULING_MAXPRIO m9_l4
|
||||||
|
|
||||||
#define SCHEDULING_STOP (SCHEDULING_BASE+3)
|
#define SCHEDULING_STOP (SCHEDULING_BASE+3)
|
||||||
|
|
||||||
#define SCHEDULING_SET_NICE (SCHEDULING_BASE+4)
|
#define SCHEDULING_SET_NICE (SCHEDULING_BASE+4)
|
||||||
|
|
||||||
|
/* SCHEDULING_INHERIT is like SCHEDULING_START, but without _QUANTUM field */
|
||||||
|
#define SCHEDULING_INHERIT (SCHEDULING_BASE+5)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* _MINIX_COM_H */
|
/* _MINIX_COM_H */
|
||||||
|
|
|
@ -41,7 +41,9 @@ struct rs_start
|
||||||
char *rss_cmd;
|
char *rss_cmd;
|
||||||
size_t rss_cmdlen;
|
size_t rss_cmdlen;
|
||||||
uid_t rss_uid;
|
uid_t rss_uid;
|
||||||
int rss_nice;
|
endpoint_t rss_scheduler;
|
||||||
|
unsigned rss_priority;
|
||||||
|
unsigned rss_quantum;
|
||||||
int rss_major;
|
int rss_major;
|
||||||
int rss_dev_style;
|
int rss_dev_style;
|
||||||
long rss_period;
|
long rss_period;
|
||||||
|
|
|
@ -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_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_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. */
|
/* Shorthands for sys_runctl() system call. */
|
||||||
#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0)
|
#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0)
|
||||||
|
|
|
@ -68,7 +68,6 @@ struct stat {
|
||||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* is a socket */
|
#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 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. */
|
/* Function Prototypes. */
|
||||||
_PROTOTYPE( int chmod, (const char *_path, mode_t _mode) );
|
_PROTOTYPE( int chmod, (const char *_path, mode_t _mode) );
|
||||||
|
|
|
@ -137,7 +137,7 @@ PUBLIC void main(void)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Don't let the process run for now. */
|
/* 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? */
|
if (iskerneln(proc_nr)) { /* part of the kernel? */
|
||||||
|
|
|
@ -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 RSYS_SM ROOT_SYS_PROC_NR /* root system proc */
|
||||||
#define DEF_SYS_SM ROOT_SYS_PROC_NR /* default sys 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 */
|
#endif /* PRIV_H */
|
||||||
|
|
|
@ -236,6 +236,10 @@ struct proc {
|
||||||
(should correspond to nice 0) */
|
(should correspond to nice 0) */
|
||||||
#define MIN_USER_Q (NR_SCHED_QUEUES - 1) /* minimum priority for user
|
#define MIN_USER_Q (NR_SCHED_QUEUES - 1) /* minimum priority for user
|
||||||
processes */
|
processes */
|
||||||
|
/* default scheduling quanta */
|
||||||
|
#define USER_QUANTUM 200
|
||||||
|
#define DRIV_QUANTUM 50
|
||||||
|
#define SERV_QUANTUM 500
|
||||||
|
|
||||||
/* Magic process table addresses. */
|
/* Magic process table addresses. */
|
||||||
#define BEG_PROC_ADDR (&proc[0])
|
#define BEG_PROC_ADDR (&proc[0])
|
||||||
|
|
|
@ -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_virt_left = 0; /* disable, clear the process-virtual timers */
|
||||||
rpc->p_prof_left = 0;
|
rpc->p_prof_left = 0;
|
||||||
|
|
||||||
/*
|
/* the child process is not runnable until it's scheduled. */
|
||||||
* if the child process inherited a scheduler, the child process is not
|
RTS_SET(rpc, RTS_NO_QUANTUM);
|
||||||
* 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);
|
|
||||||
|
|
||||||
make_zero64(rpc->p_cpu_time_left);
|
make_zero64(rpc->p_cpu_time_left);
|
||||||
make_zero64(rpc->p_cycles);
|
make_zero64(rpc->p_cycles);
|
||||||
|
|
|
@ -7,17 +7,37 @@
|
||||||
PUBLIC int do_schedctl(struct proc * caller, message * m_ptr)
|
PUBLIC int do_schedctl(struct proc * caller, message * m_ptr)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
|
unsigned flags;
|
||||||
int proc_nr;
|
int proc_nr;
|
||||||
|
|
||||||
/* Only system processes can change process schedulers */
|
/* Only system processes can change process schedulers */
|
||||||
if (! (priv(caller)->s_flags & SYS_PROC))
|
if (! (priv(caller)->s_flags & SYS_PROC))
|
||||||
return(EPERM);
|
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;
|
return EINVAL;
|
||||||
|
|
||||||
p = proc_addr(proc_nr);
|
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);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,25 +69,25 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PUBLIC struct boot_image image[] = {
|
PUBLIC struct boot_image image[] = {
|
||||||
/* process nr, flags, ms, queue, stack, name */
|
/* process nr, flags, ms, queue, stack, name */
|
||||||
{IDLE, 0, 0, 0, IDL_S, "idle" },
|
{IDLE, 0, 0, 0, IDL_S, "idle" },
|
||||||
{CLOCK, 0, 0, 0, IDL_S, "clock" },
|
{CLOCK, 0, 0, 0, IDL_S, "clock" },
|
||||||
{SYSTEM, 0, 0, 0, IDL_S, "system"},
|
{SYSTEM, 0, 0, 0, IDL_S, "system"},
|
||||||
{HARDWARE, 0, 0, 0, HRD_S, "kernel"},
|
{HARDWARE, 0, 0, 0, HRD_S, "kernel"},
|
||||||
|
|
||||||
{DS_PROC_NR, BVM_F, 50, 4, 0, "ds" },
|
{DS_PROC_NR, BVM_F, DRIV_QUANTUM, 4, 0, "ds" },
|
||||||
{RS_PROC_NR, 0, 50, 4, 0, "rs" },
|
{RS_PROC_NR, 0, DRIV_QUANTUM, 4, 0, "rs" },
|
||||||
|
|
||||||
{PM_PROC_NR, OVM_F,500, 4, 0, "pm" },
|
{PM_PROC_NR, OVM_F, SERV_QUANTUM, 4, 0, "pm" },
|
||||||
{SCHED_PROC_NR,OVM_F,500, 4, 0, "sched" },
|
{SCHED_PROC_NR,OVM_F, SERV_QUANTUM, 4, 0, "sched" },
|
||||||
{VFS_PROC_NR, OVM_F,500, 5, 0, "vfs" },
|
{VFS_PROC_NR, OVM_F, SERV_QUANTUM, 5, 0, "vfs" },
|
||||||
{MEM_PROC_NR, BVM_F, 50, 3, 0, "memory"},
|
{MEM_PROC_NR, BVM_F, DRIV_QUANTUM, 3, 0, "memory"},
|
||||||
{LOG_PROC_NR, BVM_F, 50, 2, 0, "log" },
|
{LOG_PROC_NR, BVM_F, DRIV_QUANTUM, 2, 0, "log" },
|
||||||
{TTY_PROC_NR, BVM_F, 50, 1, 0, "tty" },
|
{TTY_PROC_NR, BVM_F, DRIV_QUANTUM, 1, 0, "tty" },
|
||||||
{MFS_PROC_NR, BVM_F,500, 5, 0, "mfs" },
|
{MFS_PROC_NR, BVM_F, SERV_QUANTUM, 5, 0, "mfs" },
|
||||||
{VM_PROC_NR, 0,500, 2, 0, "vm" },
|
{VM_PROC_NR, 0, SERV_QUANTUM, 2, 0, "vm" },
|
||||||
{PFS_PROC_NR, BVM_F,500, 5, 0, "pfs" },
|
{PFS_PROC_NR, BVM_F, SERV_QUANTUM, 5, 0, "pfs" },
|
||||||
{INIT_PROC_NR, BVM_F,200, USER_Q, 0, "init" },
|
{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
|
/* Verify the size of the system image table at compile time. Also verify that
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.include <bsd.own.mk>
|
.include <bsd.own.mk>
|
||||||
|
|
||||||
SUBDIR= csu libc libcurses libdriver libnetdriver libend libedit libm libsys \
|
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"
|
.if ${COMPILER_TYPE} == "ack"
|
||||||
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby
|
||||||
|
|
|
@ -16,9 +16,6 @@ static char elsieid[] = "@(#)localtime.c 7.99";
|
||||||
|
|
||||||
/*LINTLIBRARY*/
|
/*LINTLIBRARY*/
|
||||||
|
|
||||||
/* Gives us offtime, timegm and a few other functions */
|
|
||||||
#define STD_INSPIRED
|
|
||||||
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "tzfile.h"
|
#include "tzfile.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
|
|
|
@ -26,6 +26,8 @@ SRCS= \
|
||||||
pci_set_acl.c \
|
pci_set_acl.c \
|
||||||
pci_slot_name.c \
|
pci_slot_name.c \
|
||||||
safecopies.c \
|
safecopies.c \
|
||||||
|
sched_start.c \
|
||||||
|
sched_stop.c \
|
||||||
sef.c \
|
sef.c \
|
||||||
sef_init.c \
|
sef_init.c \
|
||||||
sef_liveupdate.c \
|
sef_liveupdate.c \
|
||||||
|
@ -119,4 +121,6 @@ SRCS= \
|
||||||
profile.c \
|
profile.c \
|
||||||
vprintf.c
|
vprintf.c
|
||||||
|
|
||||||
|
CPPFLAGS.sched_start.c+= -I${MINIXSRCDIR}
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "syslib.h"
|
#include "syslib.h"
|
||||||
|
|
||||||
PUBLIC int sys_schedctl(endpoint_t proc_ep)
|
PUBLIC int sys_schedctl(unsigned flags, endpoint_t proc_ep)
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
|
|
||||||
m.SCHEDULING_ENDPOINT = proc_ep;
|
m.SCHEDCTL_FLAGS = (int) flags;
|
||||||
|
m.SCHEDCTL_ENDPOINT = proc_ep;
|
||||||
return(_kernel_call(SYS_SCHEDCTL, &m));
|
return(_kernel_call(SYS_SCHEDCTL, &m));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 \
|
readv.3 realpath.3 regex.3 remainder.3 resolver.3 scanf.3 \
|
||||||
servxcheck.3 setbuf.3 setjmp.3 sigset.3 sleep.3 stdarg.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 \
|
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.man.mk>
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
|
781
man/man3/fetch.3
781
man/man3/fetch.3
|
@ -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.
|
|
|
@ -18,8 +18,10 @@
|
||||||
|
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
#include <minix/sched.h>
|
||||||
#include <minix/vm.h>
|
#include <minix/vm.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
@ -91,6 +93,15 @@ PUBLIC int do_fork()
|
||||||
rmc->mp_trace_flags = 0;
|
rmc->mp_trace_flags = 0;
|
||||||
sigemptyset(&rmc->mp_sigtrace);
|
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. */
|
/* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */
|
||||||
rmc->mp_flags &= (IN_USE|DELAY_CALL);
|
rmc->mp_flags &= (IN_USE|DELAY_CALL);
|
||||||
rmc->mp_child_utime = 0; /* reset administration */
|
rmc->mp_child_utime = 0; /* reset administration */
|
||||||
|
@ -364,7 +375,7 @@ int dump_core; /* flag indicating whether to dump core */
|
||||||
*/
|
*/
|
||||||
int r;
|
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
|
/* If the scheduler refuses to give up scheduling, there is
|
||||||
* little we can do, except report it. This may cause problems
|
* little we can do, except report it. This may cause problems
|
||||||
* later on, if this scheduler is asked to schedule another proc
|
* 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);
|
"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. */
|
/* For core dumps, now is the right time to try to contact the parent. */
|
||||||
if (dump_core)
|
if (dump_core)
|
||||||
zombify(rmp);
|
zombify(rmp);
|
||||||
|
|
|
@ -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_parent = INIT_PROC_NR;
|
||||||
rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
|
rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
|
||||||
rmp->mp_flags |= IN_USE;
|
rmp->mp_flags |= IN_USE;
|
||||||
|
|
||||||
|
/* Set scheduling info */
|
||||||
|
rmp->mp_scheduler = KERNEL;
|
||||||
}
|
}
|
||||||
else { /* system process */
|
else { /* system process */
|
||||||
if(ip->proc_nr == RS_PROC_NR) {
|
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_pid = get_free_pid();
|
||||||
rmp->mp_flags |= IN_USE | PRIV_PROC;
|
rmp->mp_flags |= IN_USE | PRIV_PROC;
|
||||||
|
|
||||||
|
/* RS schedules this process */
|
||||||
|
rmp->mp_scheduler = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get kernel endpoint identifier. */
|
/* Get kernel endpoint identifier. */
|
||||||
rmp->mp_endpoint = ip->endpoint;
|
rmp->mp_endpoint = ip->endpoint;
|
||||||
|
|
||||||
/* Set scheduling info */
|
|
||||||
rmp->mp_scheduler = KERNEL;
|
|
||||||
|
|
||||||
/* Tell VFS about this system process. */
|
/* Tell VFS about this system process. */
|
||||||
mess.m_type = PM_INIT;
|
mess.m_type = PM_INIT;
|
||||||
mess.PM_SLOT = ip->proc_nr;
|
mess.PM_SLOT = ip->proc_nr;
|
||||||
|
@ -493,7 +496,7 @@ PRIVATE void handle_vfs_reply()
|
||||||
/* Schedule the newly created process ... */
|
/* Schedule the newly created process ... */
|
||||||
r = (OK);
|
r = (OK);
|
||||||
if (rmp->mp_scheduler != KERNEL && rmp->mp_scheduler != NONE) {
|
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
|
/* If scheduling the process failed, we want to tear down the process
|
||||||
|
|
|
@ -63,8 +63,7 @@ _PROTOTYPE( int do_getsetpriority, (void) );
|
||||||
|
|
||||||
/* schedule.c */
|
/* schedule.c */
|
||||||
_PROTOTYPE( void sched_init, (void) );
|
_PROTOTYPE( void sched_init, (void) );
|
||||||
_PROTOTYPE( int sched_start, (endpoint_t ep, struct mproc *rmp, int flags) );
|
_PROTOTYPE( int sched_start_user, (endpoint_t ep, struct mproc *rmp) );
|
||||||
_PROTOTYPE( int sched_stop, (struct mproc *rmp) );
|
|
||||||
_PROTOTYPE( int sched_nice, (struct mproc *rmp, int nice) );
|
_PROTOTYPE( int sched_nice, (struct mproc *rmp, int nice) );
|
||||||
|
|
||||||
/* profile.c */
|
/* profile.c */
|
||||||
|
@ -108,5 +107,6 @@ _PROTOTYPE( pid_t get_free_pid, (void) );
|
||||||
_PROTOTYPE( int no_sys, (void) );
|
_PROTOTYPE( int no_sys, (void) );
|
||||||
_PROTOTYPE( char *find_param, (const char *key) );
|
_PROTOTYPE( char *find_param, (const char *key) );
|
||||||
_PROTOTYPE( struct mproc *find_proc, (pid_t lpid) );
|
_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( int pm_isokendpt, (int ep, int *proc) );
|
||||||
_PROTOTYPE( void tell_vfs, (struct mproc *rmp, message *m_ptr) );
|
_PROTOTYPE( void tell_vfs, (struct mproc *rmp, message *m_ptr) );
|
||||||
|
|
|
@ -1,86 +1,72 @@
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <minix/config.h>
|
#include <minix/config.h>
|
||||||
|
#include <minix/sched.h>
|
||||||
#include <minix/sysinfo.h>
|
#include <minix/sysinfo.h>
|
||||||
#include <minix/type.h>
|
#include <minix/type.h>
|
||||||
#include <machine/archtypes.h>
|
#include <machine/archtypes.h>
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#include "mproc.h"
|
#include "mproc.h"
|
||||||
|
|
||||||
|
#include <machine/archtypes.h>
|
||||||
|
#include <timers.h>
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* init_scheduling *
|
* init_scheduling *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void sched_init(void)
|
PUBLIC void sched_init(void)
|
||||||
{
|
{
|
||||||
struct mproc *trmp;
|
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++) {
|
for (proc_nr=0, trmp=mproc; proc_nr < NR_PROCS; proc_nr++, trmp++) {
|
||||||
/* Don't take over system processes. When the system starts,
|
/* Don't take over system processes. When the system starts,
|
||||||
* this will typically only take over init, from which other
|
* init is blocked on RTS_NO_QUANTUM until PM assigns a
|
||||||
* user space processes will inherit. */
|
* 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 (trmp->mp_flags & IN_USE && !(trmp->mp_flags & PRIV_PROC)) {
|
||||||
if (sched_start(SCHED_PROC_NR, trmp,
|
assert(_ENDPOINT_P(trmp->mp_endpoint) == INIT_PROC_NR);
|
||||||
(SEND_PRIORITY | SEND_TIME_SLICE))) {
|
parent_e = mproc[trmp->mp_parent].mp_endpoint;
|
||||||
printf("PM: SCHED denied taking over scheduling of %s\n",
|
assert(parent_e == trmp->mp_endpoint);
|
||||||
trmp->mp_name);
|
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;
|
int rv;
|
||||||
message m;
|
|
||||||
|
|
||||||
m.SCHEDULING_ENDPOINT = rmp->mp_endpoint;
|
/* convert nice to priority */
|
||||||
m.SCHEDULING_PARENT = mproc[rmp->mp_parent].mp_endpoint;
|
if ((rv = nice_to_priority(rmp->mp_nice, &maxprio)) != OK) {
|
||||||
m.SCHEDULING_NICE = rmp->mp_nice;
|
|
||||||
|
|
||||||
/* Send the request to the scheduler */
|
|
||||||
if ((rv = _taskcall(ep, SCHEDULING_START, &m))) {
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the process' scheduler. Note that this might not be the
|
/* inherit quantum */
|
||||||
* scheduler we sent the SCHEDULING_START message to. That scheduler
|
return sched_inherit(ep, /* scheduler_e */
|
||||||
* might have forwarded the scheduling message on to another scheduler
|
rmp->mp_endpoint, /* schedulee_e */
|
||||||
* before returning the message.
|
mproc[rmp->mp_parent].mp_endpoint, /* parent_e */
|
||||||
*/
|
maxprio, /* maxprio */
|
||||||
rmp->mp_scheduler = m.SCHEDULING_SCHEDULER;
|
&rmp->mp_scheduler); /* *newsched_e */
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -90,6 +76,7 @@ PUBLIC int sched_nice(struct mproc *rmp, int nice)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
message m;
|
message m;
|
||||||
|
unsigned maxprio;
|
||||||
|
|
||||||
/* If the kernel is the scheduler, we don't allow messing with the
|
/* If the kernel is the scheduler, we don't allow messing with the
|
||||||
* priority. If you want to control process priority, assign the process
|
* 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)
|
if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
if ((rv = nice_to_priority(nice, &maxprio)) != OK) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
m.SCHEDULING_ENDPOINT = rmp->mp_endpoint;
|
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))) {
|
if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_SET_NICE, &m))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
* no_sys: called for invalid system call numbers
|
* no_sys: called for invalid system call numbers
|
||||||
* find_param: look up a boot monitor parameter
|
* find_param: look up a boot monitor parameter
|
||||||
* find_proc: return process pointer from pid number
|
* 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
|
* pm_isokendpt: check the validity of an endpoint
|
||||||
* tell_vfs: send a request to VFS on behalf of a process
|
* tell_vfs: send a request to VFS on behalf of a process
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
@ -102,6 +104,21 @@ pid_t lpid;
|
||||||
return(NULL);
|
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 *
|
* pm_isokendpt *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -156,7 +156,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
||||||
{
|
{
|
||||||
/* Initialize the reincarnation server. */
|
/* Initialize the reincarnation server. */
|
||||||
struct boot_image *ip;
|
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;
|
int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
|
||||||
struct rproc *rp;
|
struct rproc *rp;
|
||||||
struct rproc *replica_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);
|
rpub->vm_call_mask, VM_RQ_BASE, TRUE);
|
||||||
|
|
||||||
/* Get some settings from the boot image table. */
|
/* 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;
|
rpub->endpoint = ip->endpoint;
|
||||||
|
|
||||||
/* Set some defaults. */
|
/* 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.
|
/* - 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;
|
nr_uncaught_init_srvs = 0;
|
||||||
|
for (usersched=0; usersched <= 1; usersched++) {
|
||||||
for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
|
for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
|
||||||
boot_image_priv = &boot_image_priv_table[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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kernel-scheduled processes first */
|
||||||
|
if ((boot_image_priv->sched == KERNEL) ? usersched : !usersched) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Lookup the corresponding slot in the system process table. */
|
/* Lookup the corresponding slot in the system process table. */
|
||||||
rp = &rproc[boot_image_priv - boot_image_priv_table];
|
rp = &rproc[boot_image_priv - boot_image_priv_table];
|
||||||
rpub = rp->r_pub;
|
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);
|
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
|
/* Initialize service. We assume every service will always get
|
||||||
* back to us here at boot time.
|
* 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);
|
catch_boot_init_ready(ANY);
|
||||||
nr_uncaught_init_srvs--;
|
nr_uncaught_init_srvs--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* - Step 4: all the system services in the boot image are now running.
|
/* - Step 4: all the system services in the boot image are now running.
|
||||||
* Complete the initialization of the system process table in collaboration
|
* 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) {
|
if(s != OK) {
|
||||||
panic("unable to let the new RS instance run: %d", s);
|
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. */
|
/* Synchronize with the new instance and go to sleep. */
|
||||||
m.m_type = RS_INIT;
|
m.m_type = RS_INIT;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* caller_is_root *
|
* caller_is_root *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -370,8 +372,8 @@ char *file;
|
||||||
int line;
|
int line;
|
||||||
struct rproc *rp;
|
struct rproc *rp;
|
||||||
{
|
{
|
||||||
/* Ask PM to exit the service and free slot. */
|
|
||||||
struct rprocpub *rpub;
|
struct rprocpub *rpub;
|
||||||
|
int s;
|
||||||
|
|
||||||
rpub = rp->r_pub;
|
rpub = rp->r_pub;
|
||||||
|
|
||||||
|
@ -379,6 +381,12 @@ struct rproc *rp;
|
||||||
printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
|
printf("RS: %s cleaned up at %s:%d\n", srv_to_string(rp),
|
||||||
file, line);
|
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) {
|
if(rp->r_pid == -1) {
|
||||||
printf("RS: warning: attempt to kill pid -1!\n");
|
printf("RS: warning: attempt to kill pid -1!\n");
|
||||||
}
|
}
|
||||||
|
@ -386,6 +394,7 @@ struct rproc *rp;
|
||||||
srv_kill(rp->r_pid, SIGKILL);
|
srv_kill(rp->r_pid, SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free slot */
|
||||||
free_slot(rp);
|
free_slot(rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,6 +470,13 @@ struct rproc *rp;
|
||||||
return ENOMEM;
|
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
|
/* 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
|
* 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.
|
* 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_script[rs_start->rss_scriptlen] = '\0';
|
||||||
}
|
}
|
||||||
rp->r_uid= rs_start->rss_uid;
|
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)
|
if (rs_start->rss_flags & RSS_IPC_VALID)
|
||||||
{
|
{
|
||||||
|
|
|
@ -92,6 +92,7 @@ _PROTOTYPE( char* srv_to_string, (struct rproc *rp));
|
||||||
_PROTOTYPE( void reply, (endpoint_t who, message *m_ptr));
|
_PROTOTYPE( void reply, (endpoint_t who, message *m_ptr));
|
||||||
_PROTOTYPE( void late_reply, (struct rproc *rp, int code));
|
_PROTOTYPE( void late_reply, (struct rproc *rp, int code));
|
||||||
_PROTOTYPE( int rs_isokendpt, (endpoint_t endpoint, int *proc));
|
_PROTOTYPE( int rs_isokendpt, (endpoint_t endpoint, int *proc));
|
||||||
|
_PROTOTYPE( int sched_init_proc, (struct rproc *rp));
|
||||||
|
|
||||||
/* memory.c */
|
/* memory.c */
|
||||||
_PROTOTYPE( void* rs_startup_sbrk, (size_t size));
|
_PROTOTYPE( void* rs_startup_sbrk, (size_t size));
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
|
||||||
|
FORWARD int check_request(struct rs_start *rs_start);
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_up *
|
* do_up *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -35,6 +39,10 @@ message *m_ptr; /* request message pointer */
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
r = check_request(&rs_start);
|
||||||
|
if (r != OK) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
noblock = (rs_start.rss_flags & RSS_NOBLOCK);
|
noblock = (rs_start.rss_flags & RSS_NOBLOCK);
|
||||||
|
|
||||||
/* Initialize the slot as requested. */
|
/* Initialize the slot as requested. */
|
||||||
|
@ -385,6 +393,10 @@ PUBLIC int do_update(message *m_ptr)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
noblock = (rs_start.rss_flags & RSS_NOBLOCK);
|
noblock = (rs_start.rss_flags & RSS_NOBLOCK);
|
||||||
|
s = check_request(&rs_start);
|
||||||
|
if (s != OK) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy label. */
|
/* Copy label. */
|
||||||
s = copy_label(m_ptr->m_source, rs_start.rss_label.l_addr,
|
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.
|
* check and, if so request the system service's status.
|
||||||
*/
|
*/
|
||||||
else if (now - rp->r_check_tm > rpub->period) {
|
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 */
|
rp->r_check_tm = now; /* mark time */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -739,3 +751,30 @@ message *m_ptr;
|
||||||
return OK;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,23 +58,24 @@ PRIVATE int
|
||||||
|
|
||||||
/* Definition of the boot image priv table. The order of entries in this table
|
/* 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
|
* 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[] = {
|
PUBLIC struct boot_image_priv boot_image_priv_table[] = {
|
||||||
/*endpoint, label, flags, traps, ipcto, sigmgr, kcalls, vmcalls, T */
|
/*endpoint, label, flags, traps, ipcto, sigmgr, sched, kcalls, vmcalls, T */
|
||||||
{RS_PROC_NR, "rs", RSYS_F, RSYS_T, RSYS_M, RSYS_SM, rs_kc, rs_vmc, 0 },
|
{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, vm_kc, vm_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, pm_kc, pm_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, sched_kc, sched_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, vfs_kc, vfs_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, ds_kc, ds_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, tty_kc, tty_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, mem_kc, mem_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, log_kc, log_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, mfs_kc, mfs_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, pfs_kc, pfs_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, rusr_kc, rusr_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, no_kc, no_vmc, 0 }
|
{NULL_BOOT_NR, "", 0, 0, 0, 0, 0, no_kc, no_vmc, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Definition of the boot image sys table. */
|
/* Definition of the boot image sys table. */
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct boot_image_priv {
|
||||||
short trap_mask; /* allowed system call traps */
|
short trap_mask; /* allowed system call traps */
|
||||||
int ipc_to; /* send mask protection */
|
int ipc_to; /* send mask protection */
|
||||||
endpoint_t sig_mgr; /* signal manager */
|
endpoint_t sig_mgr; /* signal manager */
|
||||||
|
endpoint_t sched; /* scheduler */
|
||||||
int *k_calls; /* allowed kernel calls */
|
int *k_calls; /* allowed kernel calls */
|
||||||
int *vm_calls; /* allowed vm calls */
|
int *vm_calls; /* allowed vm calls */
|
||||||
long period; /* heartbeat period (or zero) */
|
long period; /* heartbeat period (or zero) */
|
||||||
|
@ -67,7 +68,9 @@ struct rproc {
|
||||||
* kernel.
|
* kernel.
|
||||||
*/
|
*/
|
||||||
uid_t r_uid;
|
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];
|
char r_ipc_list[MAX_IPC_LIST];
|
||||||
int r_nr_control;
|
int r_nr_control;
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <minix/sched.h>
|
||||||
|
#include "kernel/proc.h"
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* init_service *
|
* init_service *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -172,3 +176,39 @@ PUBLIC int rs_isokendpt(endpoint_t endpoint, int *proc)
|
||||||
return OK;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ PUBLIC int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(call_nr) {
|
switch(call_nr) {
|
||||||
|
case SCHEDULING_INHERIT:
|
||||||
case SCHEDULING_START:
|
case SCHEDULING_START:
|
||||||
result = do_start_scheduling(&m_in);
|
result = do_start_scheduling(&m_in);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,8 +19,7 @@ _PROTOTYPE( void init_scheduling, (void) );
|
||||||
_PROTOTYPE( int no_sys, (int who_e, int call_nr) );
|
_PROTOTYPE( int no_sys, (int who_e, int call_nr) );
|
||||||
_PROTOTYPE( int sched_isokendpt, (int ep, int *proc) );
|
_PROTOTYPE( int sched_isokendpt, (int ep, int *proc) );
|
||||||
_PROTOTYPE( int sched_isemtyendpt, (int ep, int *proc) );
|
_PROTOTYPE( int sched_isemtyendpt, (int ep, int *proc) );
|
||||||
_PROTOTYPE( int is_from_pm, (message *m_ptr) );
|
_PROTOTYPE( int accept_message, (message *m_ptr) );
|
||||||
_PROTOTYPE( int nice_to_priority, (int nice, unsigned *new_q) );
|
|
||||||
|
|
||||||
/* timers.c */
|
/* timers.c */
|
||||||
_PROTOTYPE( void sched_set_timer, (timer_t *tp, int delta,
|
_PROTOTYPE( void sched_set_timer, (timer_t *tp, int delta,
|
||||||
|
|
|
@ -19,9 +19,6 @@ EXTERN struct schedproc {
|
||||||
endpoint_t parent; /* parent endpoint id */
|
endpoint_t parent; /* parent endpoint id */
|
||||||
unsigned flags; /* flag bits */
|
unsigned flags; /* flag bits */
|
||||||
|
|
||||||
/* Scheduling priority. */
|
|
||||||
signed int nice; /* nice is PRIO_MIN..PRIO_MAX, standard 0. */
|
|
||||||
|
|
||||||
/* User space scheduling */
|
/* User space scheduling */
|
||||||
unsigned max_priority; /* this process' highest allowed priority */
|
unsigned max_priority; /* this process' highest allowed priority */
|
||||||
unsigned priority; /* the process' current priority */
|
unsigned priority; /* the process' current priority */
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
#include "schedproc.h"
|
#include "schedproc.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <machine/archtypes.h>
|
#include <machine/archtypes.h>
|
||||||
#include "kernel/proc.h" /* for queue constants */
|
#include "kernel/proc.h" /* for queue constants */
|
||||||
|
@ -58,7 +59,7 @@ PUBLIC int do_stop_scheduling(message *m_ptr)
|
||||||
int rv, proc_nr_n;
|
int rv, proc_nr_n;
|
||||||
|
|
||||||
/* Only accept stop messages from PM */
|
/* Only accept stop messages from PM */
|
||||||
if (!is_from_pm(m_ptr))
|
if (!accept_message(m_ptr))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
if (sched_isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n) != OK) {
|
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)
|
PUBLIC int do_start_scheduling(message *m_ptr)
|
||||||
{
|
{
|
||||||
register struct schedproc *rmp;
|
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 */
|
/* Only accept start messages from PM */
|
||||||
if (!is_from_pm(m_ptr))
|
if (!accept_message(m_ptr))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
/* Resolve endpoint to proc slot. */
|
/* Resolve endpoint to proc slot. */
|
||||||
|
@ -95,36 +100,42 @@ PUBLIC int do_start_scheduling(message *m_ptr)
|
||||||
/* Populate process slot */
|
/* Populate process slot */
|
||||||
rmp->endpoint = m_ptr->SCHEDULING_ENDPOINT;
|
rmp->endpoint = m_ptr->SCHEDULING_ENDPOINT;
|
||||||
rmp->parent = m_ptr->SCHEDULING_PARENT;
|
rmp->parent = m_ptr->SCHEDULING_PARENT;
|
||||||
rmp->nice = m_ptr->SCHEDULING_NICE;
|
rmp->max_priority = (unsigned) m_ptr->SCHEDULING_MAXPRIO;
|
||||||
|
if (rmp->max_priority >= NR_SCHED_QUEUES) {
|
||||||
/* Find maximum priority from nice value */
|
return EINVAL;
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
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,
|
if ((rv = sched_isokendpt(m_ptr->SCHEDULING_PARENT,
|
||||||
&parent_nr_n)) != OK)
|
&parent_nr_n)) != OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
rmp->priority = schedproc[parent_nr_n].priority;
|
rmp->priority = schedproc[parent_nr_n].priority;
|
||||||
rmp->time_slice = schedproc[parent_nr_n].time_slice;
|
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
|
/* Take over scheduling the process. The kernel reply message populates
|
||||||
* the processes current priority and its time slice */
|
* the processes current priority and its time slice */
|
||||||
if ((rv = sys_schedctl(rmp->endpoint)) != OK) {
|
if ((rv = sys_schedctl(0, rmp->endpoint)) != OK) {
|
||||||
printf("Sched: Error overtaking scheduling for %d, kernel said %d\n",
|
printf("Sched: Error taking over scheduling for %d, kernel said %d\n",
|
||||||
rmp->endpoint, rv);
|
rmp->endpoint, rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -157,12 +168,10 @@ PUBLIC int do_nice(message *m_ptr)
|
||||||
struct schedproc *rmp;
|
struct schedproc *rmp;
|
||||||
int rv;
|
int rv;
|
||||||
int proc_nr_n;
|
int proc_nr_n;
|
||||||
int nice;
|
|
||||||
unsigned new_q, old_q, old_max_q;
|
unsigned new_q, old_q, old_max_q;
|
||||||
int old_nice;
|
|
||||||
|
|
||||||
/* Only accept nice messages from PM */
|
/* Only accept nice messages from PM */
|
||||||
if (!is_from_pm(m_ptr))
|
if (!accept_message(m_ptr))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
if (sched_isokendpt(m_ptr->SCHEDULING_ENDPOINT, &proc_nr_n) != OK) {
|
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];
|
rmp = &schedproc[proc_nr_n];
|
||||||
nice = m_ptr->SCHEDULING_NICE;
|
new_q = (unsigned) m_ptr->SCHEDULING_MAXPRIO;
|
||||||
|
if (new_q >= NR_SCHED_QUEUES) {
|
||||||
if ((rv = nice_to_priority(nice, &new_q)) != OK)
|
return EINVAL;
|
||||||
return rv;
|
}
|
||||||
|
|
||||||
/* Store old values, in case we need to roll back the changes */
|
/* Store old values, in case we need to roll back the changes */
|
||||||
old_q = rmp->priority;
|
old_q = rmp->priority;
|
||||||
old_max_q = rmp->max_priority;
|
old_max_q = rmp->max_priority;
|
||||||
old_nice = rmp->nice;
|
|
||||||
|
|
||||||
/* Update the proc entry and reschedule the process */
|
/* Update the proc entry and reschedule the process */
|
||||||
rmp->max_priority = rmp->priority = new_q;
|
rmp->max_priority = rmp->priority = new_q;
|
||||||
rmp->nice = nice;
|
|
||||||
|
|
||||||
if ((rv = schedule_process(rmp)) != OK) {
|
if ((rv = schedule_process(rmp)) != OK) {
|
||||||
/* Something went wrong when rescheduling the process, roll
|
/* Something went wrong when rescheduling the process, roll
|
||||||
* back the changes to proc struct */
|
* back the changes to proc struct */
|
||||||
rmp->priority = old_q;
|
rmp->priority = old_q;
|
||||||
rmp->max_priority = old_max_q;
|
rmp->max_priority = old_max_q;
|
||||||
rmp->nice = old_nice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
* no_sys: called for invalid system call numbers
|
* no_sys: called for invalid system call numbers
|
||||||
* sched_isokendpt: check the validity of an endpoint
|
* sched_isokendpt: check the validity of an endpoint
|
||||||
* sched_isemtyendpt check for validity and availability of endpoint slot
|
* sched_isemtyendpt check for validity and availability of endpoint slot
|
||||||
* is_from_pm check whether message is originated from PM
|
* accept_message check whether message is allowed
|
||||||
* nice_to_priority convert nice level to priority queue
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sched.h"
|
#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) {
|
/* accept all messages from PM and RS */
|
||||||
return 1;
|
switch (m_ptr->m_source) {
|
||||||
|
|
||||||
|
case PM_PROC_NR:
|
||||||
|
case RS_PROC_NR:
|
||||||
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* no other messages are allowable */
|
||||||
return 0;
|
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);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue