Commit 75bcc1d5 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.0

parent cd534a05
VERSION = 1 VERSION = 1
PATCHLEVEL = 0 PATCHLEVEL = 1
SUBLEVEL = 6 SUBLEVEL = 0
all: Version zImage all: Version zImage
...@@ -9,6 +9,7 @@ all: Version zImage ...@@ -9,6 +9,7 @@ all: Version zImage
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
else if [ -x /bin/bash ]; then echo /bin/bash; \ else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi ; fi) else echo sh; fi ; fi)
ROOT := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
# #
# Make "config" the default target if there is no configuration file or # Make "config" the default target if there is no configuration file or
...@@ -76,7 +77,7 @@ AS =as ...@@ -76,7 +77,7 @@ AS =as
LD =ld LD =ld
LDFLAGS =#-qmagic LDFLAGS =#-qmagic
HOSTCC =gcc HOSTCC =gcc
CC =gcc -D__KERNEL__ CC =gcc -D__KERNEL__ -I$(ROOT)/include
MAKE =make MAKE =make
CPP =$(CC) -E CPP =$(CC) -E
AR =ar AR =ar
......
...@@ -42,12 +42,9 @@ struct request { ...@@ -42,12 +42,9 @@ struct request {
* This is used in the elevator algorithm: Note that * This is used in the elevator algorithm: Note that
* reads always go before writes. This is natural: reads * reads always go before writes. This is natural: reads
* are much more time-critical than writes. * are much more time-critical than writes.
*
* Update: trying with writes being preferred due to test
* by Alessandro Rubini..
*/ */
#define IN_ORDER(s1,s2) \ #define IN_ORDER(s1,s2) \
((s1)->cmd > (s2)->cmd || ((s1)->cmd == (s2)->cmd && \ ((s1)->cmd < (s2)->cmd || ((s1)->cmd == (s2)->cmd && \
((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \ ((s1)->dev < (s2)->dev || (((s1)->dev == (s2)->dev && \
(s1)->sector < (s2)->sector))))) (s1)->sector < (s2)->sector)))))
......
...@@ -476,9 +476,23 @@ printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF); ...@@ -476,9 +476,23 @@ printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
#endif #endif
return 0; return 0;
case CDROMEJECT: /* Eject the drive - N/A */ case CDROMEJECT:
/* all drives can atleast stop! */
if (audioStatus == CDROM_AUDIO_PLAY) {
outb(MCMD_STOP, MCDPORT(0));
i = getMcdStatus(MCD_STATUS_DELAY);
}
audioStatus = CDROM_AUDIO_NO_STATUS;
outb(MCMD_EJECT, MCDPORT(0));
/*
* the status (i) shows failure on all but the FX drives.
* But nothing we can do about that in software!
* So just read the status and forget it. - Jon.
*/
i = getMcdStatus(MCD_STATUS_DELAY);
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
......
This diff is collapsed.
...@@ -39,6 +39,16 @@ extern __inline__ int clear_bit(int nr, void * addr) ...@@ -39,6 +39,16 @@ extern __inline__ int clear_bit(int nr, void * addr)
return oldbit; return oldbit;
} }
extern __inline__ int change_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"r" (nr));
return oldbit;
}
/* /*
* This routine doesn't need to be atomic, but it's faster to code it * This routine doesn't need to be atomic, but it's faster to code it
* this way. * this way.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
/* Structure defining a queue for a network interface. */ /* Structure defining a queue for a network interface. */
#ifdef not_yet_in_linux
struct ifnet { struct ifnet {
char *if_name; /* name, e.g. ``en'' or ``lo'' */ char *if_name; /* name, e.g. ``en'' or ``lo'' */
short if_unit; /* sub-unit for device driver */ short if_unit; /* sub-unit for device driver */
...@@ -33,13 +34,11 @@ struct ifnet { ...@@ -33,13 +34,11 @@ struct ifnet {
int if_metric; /* routing metric (not used) */ int if_metric; /* routing metric (not used) */
struct ifaddr *if_addrlist; /* linked list of addrs per if */ struct ifaddr *if_addrlist; /* linked list of addrs per if */
struct ifqueue { struct ifqueue {
#ifdef not_yet_in_linux
struct mbuf *ifq_head; struct mbuf *ifq_head;
struct mbuf *ifq_tail; struct mbuf *ifq_tail;
int ifq_len; int ifq_len;
int ifq_maxlen; int ifq_maxlen;
int ifq_drops; int ifq_drops;
#endif
} if_snd; /* output queue */ } if_snd; /* output queue */
/* Procedure handles. */ /* Procedure handles. */
...@@ -59,6 +58,7 @@ struct ifnet { ...@@ -59,6 +58,7 @@ struct ifnet {
/* Linked list: pointer to next interface. */ /* Linked list: pointer to next interface. */
struct ifnet *if_next; struct ifnet *if_next;
}; };
#endif
/* Standard interface flags. */ /* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */ #define IFF_UP 0x1 /* interface is up */
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define MCD_STATUS_DELAY 100 #define MCD_STATUS_DELAY 100
/* number of times to retry a command before giving up */ /* number of times to retry a command before giving up */
#define MCD_RETRY_ATTEMPTS 3 #define MCD_RETRY_ATTEMPTS 5
/* port access macro */ /* port access macro */
#define MCDPORT(x) (mcd_port + (x)) #define MCDPORT(x) (mcd_port + (x))
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#define MCMD_SET_VOLUME 0xAE /* set audio level */ #define MCMD_SET_VOLUME 0xAE /* set audio level */
#define MCMD_PLAY_READ 0xC0 /* play or read data */ #define MCMD_PLAY_READ 0xC0 /* play or read data */
#define MCMD_GET_VERSION 0xDC #define MCMD_GET_VERSION 0xDC
#define MCMD_EJECT 0xF6 /* eject (FX drive) */
/* borrowed from hd.c */ /* borrowed from hd.c */
......
...@@ -92,22 +92,31 @@ struct page_info { ...@@ -92,22 +92,31 @@ struct page_info {
}; };
/* end of planning stage */ /* end of planning stage */
extern volatile short free_page_ptr; /* used by malloc and tcp/ip. */ /*
* Free area management
*/
extern int nr_swap_pages; extern int nr_swap_pages;
extern int nr_free_pages; extern int nr_free_pages;
extern unsigned long free_page_list;
extern int nr_secondary_pages;
extern unsigned long secondary_page_list;
#define MAX_SECONDARY_PAGES 20 #define MAX_SECONDARY_PAGES 20
#define NR_MEM_LISTS 6
struct mem_list {
struct mem_list * next;
struct mem_list * prev;
};
extern struct mem_list free_area_list[NR_MEM_LISTS];
extern unsigned char * free_area_map[NR_MEM_LISTS];
/* /*
* This is timing-critical - most of the time in getting a new page * This is timing-critical - most of the time in getting a new page
* goes to clearing the page. If you want a page without the clearing * goes to clearing the page. If you want a page without the clearing
* overhead, just use __get_free_page() directly.. * overhead, just use __get_free_page() directly..
*/ */
extern unsigned long __get_free_page(int priority); #define __get_free_page(priority) __get_free_pages((priority),0)
extern unsigned long __get_free_pages(int priority, unsigned long gfporder);
extern inline unsigned long get_free_page(int priority) extern inline unsigned long get_free_page(int priority)
{ {
unsigned long page; unsigned long page;
...@@ -121,9 +130,12 @@ extern inline unsigned long get_free_page(int priority) ...@@ -121,9 +130,12 @@ extern inline unsigned long get_free_page(int priority)
return page; return page;
} }
/* memory.c */ /* memory.c & swap.c*/
#define free_page(addr) free_pages((addr),0)
extern void free_pages(unsigned long addr, unsigned long order);
extern void free_page(unsigned long addr); extern void show_free_areas(void);
extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page, extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
unsigned long address); unsigned long address);
extern void free_page_tables(struct task_struct * tsk); extern void free_page_tables(struct task_struct * tsk);
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#define NULL ((void *) 0) #define NULL ((void *) 0)
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
/* /*
* This string-include defines all string functions as inline * This string-include defines all string functions as inline
* functions. Use gcc. It also assumes ds=es=data space, this should be * functions. Use gcc. It also assumes ds=es=data space, this should be
...@@ -416,4 +420,8 @@ __asm__("cld\n\t" ...@@ -416,4 +420,8 @@ __asm__("cld\n\t"
return s; return s;
} }
#ifdef __cplusplus
}
#endif
#endif #endif
#ifndef _LINUX_SYS_H #ifndef _LINUX_SYS_H
#define _LINUX_SYS_H #define _LINUX_SYS_H
/* /*
* system call entry points * system call entry points ... but not all are defined
*/ */
#define NR_syscalls 256
#define sys_clone sys_fork /*
* These are system calls with the same entry-point
#ifdef __cplusplus */
extern "C" { #define _sys_clone _sys_fork
#endif
extern int sys_setup(); /* 0 */
extern int sys_exit();
extern int sys_fork();
extern int sys_read();
extern int sys_write();
extern int sys_open(); /* 5 */
extern int sys_close();
extern int sys_waitpid();
extern int sys_creat();
extern int sys_link();
extern int sys_unlink(); /* 10 */
extern int sys_execve();
extern int sys_chdir();
extern int sys_time();
extern int sys_mknod();
extern int sys_chmod(); /* 15 */
extern int sys_chown();
extern int sys_break();
extern int sys_stat();
extern int sys_lseek();
extern int sys_getpid(); /* 20 */
extern int sys_mount();
extern int sys_umount();
extern int sys_setuid();
extern int sys_getuid();
extern int sys_stime(); /* 25 */
extern int sys_ptrace();
extern int sys_alarm();
extern int sys_fstat();
extern int sys_pause();
extern int sys_utime(); /* 30 */
extern int sys_stty();
extern int sys_gtty();
extern int sys_access();
extern int sys_nice();
extern int sys_ftime(); /* 35 */
extern int sys_sync();
extern int sys_kill();
extern int sys_rename();
extern int sys_mkdir();
extern int sys_rmdir(); /* 40 */
extern int sys_dup();
extern int sys_pipe();
extern int sys_times();
extern int sys_prof();
extern int sys_brk(); /* 45 */
extern int sys_setgid();
extern int sys_getgid();
extern int sys_signal();
extern int sys_geteuid();
extern int sys_getegid(); /* 50 */
extern int sys_acct();
extern int sys_phys();
extern int sys_lock();
extern int sys_ioctl();
extern int sys_fcntl(); /* 55 */
extern int sys_mpx();
extern int sys_setpgid();
extern int sys_ulimit();
extern int sys_uname();
extern int sys_umask(); /* 60 */
extern int sys_chroot();
extern int sys_ustat();
extern int sys_dup2();
extern int sys_getppid();
extern int sys_getpgrp(); /* 65 */
extern int sys_setsid();
extern int sys_sigaction();
extern int sys_sgetmask();
extern int sys_ssetmask();
extern int sys_setreuid(); /* 70 */
extern int sys_setregid();
extern int sys_sigpending();
extern int sys_sigsuspend();
extern int sys_sethostname();
extern int sys_setrlimit(); /* 75 */
extern int sys_getrlimit();
extern int sys_getrusage();
extern int sys_gettimeofday();
extern int sys_settimeofday();
extern int sys_getgroups(); /* 80 */
extern int sys_setgroups();
extern int sys_select();
extern int sys_symlink();
extern int sys_lstat();
extern int sys_readlink(); /* 85 */
extern int sys_uselib();
extern int sys_swapon();
extern int sys_reboot();
extern int sys_readdir();
extern int sys_mmap(); /* 90 */
extern int sys_munmap();
extern int sys_truncate();
extern int sys_ftruncate();
extern int sys_fchmod();
extern int sys_fchown(); /* 95 */
extern int sys_getpriority();
extern int sys_setpriority();
extern int sys_profil();
extern int sys_statfs();
extern int sys_fstatfs(); /* 100 */
extern int sys_ioperm();
extern int sys_socketcall();
extern int sys_syslog();
extern int sys_getitimer();
extern int sys_setitimer(); /* 105 */
extern int sys_newstat();
extern int sys_newlstat();
extern int sys_newfstat();
extern int sys_newuname();
extern int sys_iopl(); /* 110 */
extern int sys_vhangup();
extern int sys_idle();
extern int sys_vm86();
extern int sys_wait4();
extern int sys_swapoff(); /* 115 */
extern int sys_sysinfo();
extern int sys_ipc();
extern int sys_fsync();
extern int sys_sigreturn();
extern int sys_setdomainname(); /* 120 */
extern int sys_olduname();
extern int sys_old_syscall();
extern int sys_modify_ldt();
extern int sys_adjtimex();
extern int sys_mprotect(); /* 125 */
extern int sys_sigprocmask();
extern int sys_create_module();
extern int sys_init_module();
extern int sys_delete_module();
extern int sys_get_kernel_syms(); /* 130 */
extern int sys_quotactl();
extern int sys_getpgid();
extern int sys_fchdir();
extern int sys_bdflush();
/* /*
* These are system calls that will be removed at some time * These are system calls that will be removed at some time
* due to newer versions existing.. * due to newer versions existing..
*/ */
#ifdef notdef #ifdef notdef
#define sys_waitpid sys_old_syscall /* sys_wait4 */ #define _sys_waitpid _sys_old_syscall /* _sys_wait4 */
#define sys_olduname sys_old_syscall /* sys_newuname */ #define _sys_olduname _sys_old_syscall /* _sys_newuname */
#define sys_uname sys_old_syscall /* sys_newuname */ #define _sys_uname _sys_old_syscall /* _sys_newuname */
#define sys_stat sys_old_syscall /* sys_newstat */ #define _sys_stat _sys_old_syscall /* _sys_newstat */
#define sys_fstat sys_old_syscall /* sys_newfstat */ #define _sys_fstat _sys_old_syscall /* _sys_newfstat */
#define sys_lstat sys_old_syscall /* sys_newlstat */ #define _sys_lstat _sys_old_syscall /* _sys_newlstat */
#define sys_signal sys_old_syscall /* sys_sigaction */ #define _sys_signal _sys_old_syscall /* _sys_sigaction */
#define sys_sgetmask sys_old_syscall /* sys_sigprocmask */ #define _sys_sgetmask _sys_old_syscall /* _sys_sigprocmask */
#define sys_ssetmask sys_old_syscall /* sig_sigprocmask */ #define _sys_ssetmask _sys_old_syscall /* _sys_sigprocmask */
#endif #endif
/* /*
* These are system calls that haven't been implemented yet * These are system calls that haven't been implemented yet
* but have an entry in the table for future expansion.. * but have an entry in the table for future expansion..
*/ */
#define _sys_quotactl _sys_ni_syscall
#define sys_quotactl sys_ni_syscall #define _sys_bdflush _sys_ni_syscall
#define sys_bdflush sys_ni_syscall
typedef int (*fn_ptr)();
#ifdef __cplusplus
}
#endif
#endif #endif
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* /*
* This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X). * This file contains the definitions for the IO ports and errors etc. for XT hard disk controllers (at least the DTC 5150X).
* *
* Author: Pat Mackinlay, smackinla@cc.curtin.edu.au * Author: Pat Mackinlay, pat@it.com.au
* Date: 29/09/92 * Date: 29/09/92
* *
* Revised: 01/01/93, ... * Revised: 01/01/93, ...
......
...@@ -78,7 +78,6 @@ extern void floppy_init(void); ...@@ -78,7 +78,6 @@ extern void floppy_init(void);
extern void sock_init(void); extern void sock_init(void);
extern long rd_init(long mem_start, int length); extern long rd_init(long mem_start, int length);
unsigned long net_dev_init(unsigned long, unsigned long); unsigned long net_dev_init(unsigned long, unsigned long);
extern unsigned long simple_strtoul(const char *,char **,unsigned int);
extern void hd_setup(char *str, int *ints); extern void hd_setup(char *str, int *ints);
extern void bmouse_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints);
...@@ -267,7 +266,7 @@ static void parse_options(char *line) ...@@ -267,7 +266,7 @@ static void parse_options(char *line)
{ {
char *next; char *next;
char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL }; char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
int devnums[] = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xC00, 0xC40, 0}; int devnums[] = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
int args, envs; int args, envs;
if (!*line) if (!*line)
......
...@@ -34,14 +34,6 @@ sys_call.o: sys_call.s ...@@ -34,14 +34,6 @@ sys_call.o: sys_call.s
sched.o: sched.c sched.o: sched.c
$(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $< $(CC) $(CFLAGS) $(PROFILING) -fno-omit-frame-pointer -c $<
ksyms.lst: ksyms.S ../include/linux/autoconf.h
$(CPP) $(CFLAGS) $< > $@
ksyms.s: ksyms.sh ksyms.lst
sh $< > $@
ksyms.o: ksyms.s
dep: dep:
$(CPP) -M *.c > .depend $(CPP) -M *.c > .depend
......
#include <linux/autoconf.h>
/*
* Herein lies all the functions/variables that are "exported" for linkage
* With dynamically loaded kernel modules. Could do with making this a bit
* cleaner!
*
* Jon.
*/
_register_chrdev
_unregister_chrdev
_register_blkdev
_unregister_blkdev
_wake_up_interruptible
_wp_works_ok
___verify_write
_current
_jiffies
_printk
_schedule
#ifdef CONFIG_FTAPE
#
# The next labels are needed for ftape driver.
#
_ftape_big_buffer
_do_floppy
#endif
/*
* Herein lies all the functions/variables that are "exported" for linkage
* with dynamically loaded kernel modules.
* Jon.
*/
#include <linux/autoconf.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#define X(name) { (void *) &name, #name }
struct {
void *addr;
const char *name;
} symbol_table[] = {
X(register_chrdev),
X(unregister_chrdev),
X(register_blkdev),
X(unregister_blkdev),
X(wake_up_interruptible),
X(wp_works_ok),
X(__verify_write),
X(current),
X(jiffies),
X(printk),
X(schedule),
#ifdef CONFIG_FTAPE
/* The next labels are needed for ftape driver. */
X(ftape_big_buffer),
X(do_floppy),
#endif
};
int symbol_table_size = sizeof (symbol_table) / sizeof (symbol_table[0]);
# This program will construct ksyms.s. Ksyms.s contains a symbol table
# for all the kernel symbols included in the file ksyms.lst. The following
# variables are defined in ksym.s:
#
# int symbol_table_size; /* number of symbols */
# struct {
# void *value; /* value of symbol */
# char *name; /* name of symbol */
# } symbol_table[];
#
#
trap "rm -f ksyms.tmp ksyms.lst ; exit 1" 1 2
sed -e '/^#/d' -e '/^[ ]*$/d' ksyms.lst | sort > ksyms.tmp
echo ' .data
.globl _symbol_table_size, _symbol_table
_symbol_table_size:'
echo " .long" `wc -l < ksyms.tmp`
echo '
_symbol_table:'
awk 'BEGIN {stringloc = 0}
{print " .long " $1; print " .long strings+" stringloc; \
stringloc += length($1) + 1;}' ksyms.tmp
echo '
strings:'
awk '{print " .ascii \"" $1 "\\0\""}' ksyms.tmp
rm -f ksyms.tmp
#
# Alternativly, if the kernel is c++ compiled:
# By using gsub() we can forse all function names to appear as extern "C".
# This allows linkable drivers written in C or C++ - Jon
# awk '{gsub(/__F.*/, "") ; print " .ascii \"" $0 "\\0\""}' ksyms.tmp
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/sys.h>
#include <linux/fdreg.h> #include <linux/fdreg.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/time.h> #include <linux/time.h>
...@@ -102,55 +101,7 @@ struct { ...@@ -102,55 +101,7 @@ struct {
short b; short b;
} stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS }; } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
struct kernel_stat kstat = struct kernel_stat kstat = { 0 };
{ 0, 0, 0, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*
* int 0x80 entry points.. Moved away from the header file, as
* iBCS2 may also want to use the '<linux/sys.h>' headers..
*/
#ifdef __cplusplus
extern "C" {
#endif
int sys_ni_syscall(void)
{
return -EINVAL;
}
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_olduname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_truncate,
sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
sys_newfstat, sys_uname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
sys_adjtimex, sys_mprotect, sys_sigprocmask, sys_create_module,
sys_init_module, sys_delete_module, sys_get_kernel_syms, sys_quotactl,
sys_getpgid, sys_fchdir, sys_bdflush };
/* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
#ifdef __cplusplus
}
#endif
/* /*
* 'math_state_restore()' saves the current math information in the * 'math_state_restore()' saves the current math information in the
......
...@@ -30,6 +30,11 @@ extern void adjust_clock(void); ...@@ -30,6 +30,11 @@ extern void adjust_clock(void);
#define PZERO 15 #define PZERO 15
asmlinkage int sys_ni_syscall(void)
{
return -EINVAL;
}
static int proc_sel(struct task_struct *p, int which, int who) static int proc_sel(struct task_struct *p, int which, int who)
{ {
switch (which) { switch (which) {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
*/ */
#include <linux/segment.h> #include <linux/segment.h>
#include <linux/sys.h>
EBX = 0x00 EBX = 0x00
ECX = 0x04 ECX = 0x04
...@@ -87,7 +88,7 @@ ENOSYS = 38 ...@@ -87,7 +88,7 @@ ENOSYS = 38
.globl _invalid_TSS,_segment_not_present,_stack_segment .globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_reserved .globl _general_protection,_reserved
.globl _alignment_check,_page_fault .globl _alignment_check,_page_fault
.globl ret_from_sys_call .globl ret_from_sys_call, _sys_call_table
#define SAVE_ALL \ #define SAVE_ALL \
cld; \ cld; \
...@@ -163,8 +164,11 @@ _system_call: ...@@ -163,8 +164,11 @@ _system_call:
pushl %eax # save orig_eax pushl %eax # save orig_eax
SAVE_ALL SAVE_ALL
movl $-ENOSYS,EAX(%esp) movl $-ENOSYS,EAX(%esp)
cmpl _NR_syscalls,%eax cmpl $(NR_syscalls),%eax
jae ret_from_sys_call jae ret_from_sys_call
movl _sys_call_table(,%eax,4),%eax
testl %eax,%eax
je ret_from_sys_call
movl _current,%ebx movl _current,%ebx
andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors
movl $0,errno(%ebx) movl $0,errno(%ebx)
...@@ -172,7 +176,7 @@ _system_call: ...@@ -172,7 +176,7 @@ _system_call:
movl %edx,dbgreg6(%ebx) # save current hardware debugging status movl %edx,dbgreg6(%ebx) # save current hardware debugging status
testb $0x20,flags(%ebx) # PF_TRACESYS testb $0x20,flags(%ebx) # PF_TRACESYS
jne 1f jne 1f
call _sys_call_table(,%eax,4) call *%eax
movl %eax,EAX(%esp) # save the return value movl %eax,EAX(%esp) # save the return value
movl errno(%ebx),%edx movl errno(%ebx),%edx
negl %edx negl %edx
...@@ -388,3 +392,144 @@ _alignment_check: ...@@ -388,3 +392,144 @@ _alignment_check:
_page_fault: _page_fault:
pushl $_do_page_fault pushl $_do_page_fault
jmp error_code jmp error_code
.data
.align 4
_sys_call_table:
.long _sys_setup /* 0 */
.long _sys_exit
.long _sys_fork
.long _sys_read
.long _sys_write
.long _sys_open /* 5 */
.long _sys_close
.long _sys_waitpid
.long _sys_creat
.long _sys_link
.long _sys_unlink /* 10 */
.long _sys_execve
.long _sys_chdir
.long _sys_time
.long _sys_mknod
.long _sys_chmod /* 15 */
.long _sys_chown
.long _sys_break
.long _sys_stat
.long _sys_lseek
.long _sys_getpid /* 20 */
.long _sys_mount
.long _sys_umount
.long _sys_setuid
.long _sys_getuid
.long _sys_stime /* 25 */
.long _sys_ptrace
.long _sys_alarm
.long _sys_fstat
.long _sys_pause
.long _sys_utime /* 30 */
.long _sys_stty
.long _sys_gtty
.long _sys_access
.long _sys_nice
.long _sys_ftime /* 35 */
.long _sys_sync
.long _sys_kill
.long _sys_rename
.long _sys_mkdir
.long _sys_rmdir /* 40 */
.long _sys_dup
.long _sys_pipe
.long _sys_times
.long _sys_prof
.long _sys_brk /* 45 */
.long _sys_setgid
.long _sys_getgid
.long _sys_signal
.long _sys_geteuid
.long _sys_getegid /* 50 */
.long _sys_acct
.long _sys_phys
.long _sys_lock
.long _sys_ioctl
.long _sys_fcntl /* 55 */
.long _sys_mpx
.long _sys_setpgid
.long _sys_ulimit
.long _sys_olduname
.long _sys_umask /* 60 */
.long _sys_chroot
.long _sys_ustat
.long _sys_dup2
.long _sys_getppid
.long _sys_getpgrp /* 65 */
.long _sys_setsid
.long _sys_sigaction
.long _sys_sgetmask
.long _sys_ssetmask
.long _sys_setreuid /* 70 */
.long _sys_setregid
.long _sys_sigsuspend
.long _sys_sigpending
.long _sys_sethostname
.long _sys_setrlimit /* 75 */
.long _sys_getrlimit
.long _sys_getrusage
.long _sys_gettimeofday
.long _sys_settimeofday
.long _sys_getgroups /* 80 */
.long _sys_setgroups
.long _sys_select
.long _sys_symlink
.long _sys_lstat
.long _sys_readlink /* 85 */
.long _sys_uselib
.long _sys_swapon
.long _sys_reboot
.long _sys_readdir
.long _sys_mmap /* 90 */
.long _sys_munmap
.long _sys_truncate
.long _sys_ftruncate
.long _sys_fchmod
.long _sys_fchown /* 95 */
.long _sys_getpriority
.long _sys_setpriority
.long _sys_profil
.long _sys_statfs
.long _sys_fstatfs /* 100 */
.long _sys_ioperm
.long _sys_socketcall
.long _sys_syslog
.long _sys_setitimer
.long _sys_getitimer /* 105 */
.long _sys_newstat
.long _sys_newlstat
.long _sys_newfstat
.long _sys_uname
.long _sys_iopl /* 110 */
.long _sys_vhangup
.long _sys_idle
.long _sys_vm86
.long _sys_wait4
.long _sys_swapoff /* 115 */
.long _sys_sysinfo
.long _sys_ipc
.long _sys_fsync
.long _sys_sigreturn
.long _sys_clone /* 120 */
.long _sys_setdomainname
.long _sys_newuname
.long _sys_modify_ldt
.long _sys_adjtimex
.long _sys_mprotect /* 125 */
.long _sys_sigprocmask
.long _sys_create_module
.long _sys_init_module
.long _sys_delete_module
.long _sys_get_kernel_syms /* 130 */
.long _sys_quotactl
.long _sys_getpgid
.long _sys_fchdir
.long _sys_bdflush
.space (NR_syscalls-130)*4
...@@ -10,7 +10,19 @@ ...@@ -10,7 +10,19 @@
#include <linux/types.h> #include <linux/types.h>
#ifdef __cplusplus
#define C_BEGIN extern "C" {
#define C_END }
#else
#define C_BEGIN
#define C_END
#endif
#undef __cplusplus
#define extern #define extern
#define inline #define inline
#define __LIBRARY__ #define __LIBRARY__
C_BEGIN
#include <linux/string.h> #include <linux/string.h>
C_END
...@@ -7,6 +7,11 @@ ...@@ -7,6 +7,11 @@
* *
*/ */
/*
* Modified by Alex Bligh (alex@cconcepts.co.uk) 4 Apr 1994 to use multiple
* pages. So for 'page' throughout, read 'area'.
*/
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/system.h> #include <asm/system.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -17,7 +22,7 @@ ...@@ -17,7 +22,7 @@
I want this number to be increased in the near future: I want this number to be increased in the near future:
loadable device drivers should use this function to get memory */ loadable device drivers should use this function to get memory */
#define MAX_KMALLOC_K 4 #define MAX_KMALLOC_K ((PAGE_SIZE<<(NUM_AREA_ORDERS-1))>>10)
/* This defines how many times we should try to allocate a free page before /* This defines how many times we should try to allocate a free page before
...@@ -86,25 +91,35 @@ struct size_descriptor { ...@@ -86,25 +91,35 @@ struct size_descriptor {
int nfrees; int nfrees;
int nbytesmalloced; int nbytesmalloced;
int npages; int npages;
unsigned long gfporder; /* number of pages in the area required */
}; };
/*
* For now it is unsafe to allocate bucket sizes between n & n=16 where n is
* 4096 * any power of two
*/
struct size_descriptor sizes[] = { struct size_descriptor sizes[] = {
{ NULL, 32,127, 0,0,0,0 }, { NULL, 32,127, 0,0,0,0, 0},
{ NULL, 64, 63, 0,0,0,0 }, { NULL, 64, 63, 0,0,0,0, 0 },
{ NULL, 128, 31, 0,0,0,0 }, { NULL, 128, 31, 0,0,0,0, 0 },
{ NULL, 252, 16, 0,0,0,0 }, { NULL, 252, 16, 0,0,0,0, 0 },
{ NULL, 508, 8, 0,0,0,0 }, { NULL, 508, 8, 0,0,0,0, 0 },
{ NULL,1020, 4, 0,0,0,0 }, { NULL,1020, 4, 0,0,0,0, 0 },
{ NULL,2040, 2, 0,0,0,0 }, { NULL,2040, 2, 0,0,0,0, 0 },
{ NULL,4080, 1, 0,0,0,0 }, { NULL,4096-16, 1, 0,0,0,0, 0 },
{ NULL, 0, 0, 0,0,0,0 } { NULL,8192-16, 1, 0,0,0,0, 1 },
{ NULL,16384-16, 1, 0,0,0,0, 2 },
{ NULL,32768-16, 1, 0,0,0,0, 3 },
{ NULL,65536-16, 1, 0,0,0,0, 4 },
{ NULL,131072-16, 1, 0,0,0,0, 5 },
{ NULL, 0, 0, 0,0,0,0, 0 }
}; };
#define NBLOCKS(order) (sizes[order].nblocks) #define NBLOCKS(order) (sizes[order].nblocks)
#define BLOCKSIZE(order) (sizes[order].size) #define BLOCKSIZE(order) (sizes[order].size)
#define AREASIZE(order) (PAGE_SIZE<<(sizes[order].gfporder))
long kmalloc_init (long start_mem,long end_mem) long kmalloc_init (long start_mem,long end_mem)
...@@ -118,12 +133,12 @@ long kmalloc_init (long start_mem,long end_mem) ...@@ -118,12 +133,12 @@ long kmalloc_init (long start_mem,long end_mem)
for (order = 0;BLOCKSIZE(order);order++) for (order = 0;BLOCKSIZE(order);order++)
{ {
if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) > if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) >
PAGE_SIZE) AREASIZE(order))
{ {
printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n", printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
NBLOCKS (order) * BLOCKSIZE(order) + NBLOCKS (order) * BLOCKSIZE(order) +
sizeof (struct page_descriptor), sizeof (struct page_descriptor),
(int) PAGE_SIZE, (int) AREASIZE(order),
BLOCKSIZE (order)); BLOCKSIZE (order));
panic ("This only happens if someone messes with kmalloc"); panic ("This only happens if someone messes with kmalloc");
} }
...@@ -161,12 +176,6 @@ void * kmalloc (size_t size, int priority) ...@@ -161,12 +176,6 @@ void * kmalloc (size_t size, int priority)
priority = GFP_ATOMIC; priority = GFP_ATOMIC;
} }
} }
if (size > MAX_KMALLOC_K * 1024)
{
printk ("kmalloc: I refuse to allocate %d bytes (for now max = %d).\n",
size,MAX_KMALLOC_K*1024);
return (NULL);
}
order = get_order (size); order = get_order (size);
if (order < 0) if (order < 0)
...@@ -215,7 +224,7 @@ while (tries --) ...@@ -215,7 +224,7 @@ while (tries --)
sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */ sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */
/* This can be done with ints on: This is private to this invocation */ /* This can be done with ints on: This is private to this invocation */
page = (struct page_descriptor *) __get_free_page (priority & GFP_LEVEL_MASK); page = (struct page_descriptor *) __get_free_pages (priority & GFP_LEVEL_MASK, sizes[order].gfporder);
if (!page) { if (!page) {
static unsigned long last = 0; static unsigned long last = 0;
if (last + 10*HZ < jiffies) { if (last + 10*HZ < jiffies) {
...@@ -339,10 +348,15 @@ if (page->nfree == NBLOCKS (page->order)) ...@@ -339,10 +348,15 @@ if (page->nfree == NBLOCKS (page->order))
else else
printk ("Ooops. page %p doesn't show on freelist.\n", page); printk ("Ooops. page %p doesn't show on freelist.\n", page);
} }
free_page ((long)page); /* FIXME: I'm sure we should do something with npages here (like npages--) */
free_pages ((long)page, sizes[order].gfporder);
} }
restore_flags(flags); restore_flags(flags);
/* FIXME: ?? Are these increment & decrement operations guaranteed to be
* atomic? Could an IRQ not occur between the read & the write?
* Maybe yes on a x86 with GCC...??
*/
sizes[order].nfrees++; /* Noncritical (monitoring) admin stuff */ sizes[order].nfrees++; /* Noncritical (monitoring) admin stuff */
sizes[order].nbytesmalloced -= size; sizes[order].nbytesmalloced -= size;
} }
/* /*
* linux/mm/memory.c * linux/mm/memory.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
*/ */
/* /*
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* 20.12.91 - Ok, making the swap-device changeable like the root. * 20.12.91 - Ok, making the swap-device changeable like the root.
*/ */
/*
* 05.04.94 - Multi-page memory management added for v1.1.
* Idea by Alex Bligh (alex@cconcepts.co.uk)
*/
#include <asm/system.h> #include <asm/system.h>
#include <linux/config.h> #include <linux/config.h>
...@@ -48,17 +53,14 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ ...@@ -48,17 +53,14 @@ extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */
extern void sound_mem_init(void); extern void sound_mem_init(void);
extern void die_if_kernel(char *,struct pt_regs *,long); extern void die_if_kernel(char *,struct pt_regs *,long);
int nr_swap_pages = 0;
int nr_free_pages = 0;
unsigned long free_page_list = 0;
/* /*
* The secondary free_page_list is used for malloc() etc things that * The free_area_list arrays point to the queue heads of the free areas
* may need pages during interrupts etc. Normal get_free_page() operations * of different sizes
* don't touch it, so it stays as a kind of "panic-list", that can be
* accessed when all other mm tricks have failed.
*/ */
int nr_secondary_pages = 0; int nr_swap_pages = 0;
unsigned long secondary_page_list = 0; int nr_free_pages = 0;
struct mem_list free_area_list[NR_MEM_LISTS];
unsigned char * free_area_map[NR_MEM_LISTS];
#define copy_page(from,to) \ #define copy_page(from,to) \
__asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si") __asm__("cld ; rep ; movsl": :"S" (from),"D" (to),"c" (1024):"cx","di","si")
...@@ -978,8 +980,7 @@ void show_mem(void) ...@@ -978,8 +980,7 @@ void show_mem(void)
int shared = 0; int shared = 0;
printk("Mem-info:\n"); printk("Mem-info:\n");
printk("Free pages: %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10)); show_free_areas();
printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
i = high_memory >> PAGE_SHIFT; i = high_memory >> PAGE_SHIFT;
while (i-- > 0) { while (i-- > 0) {
...@@ -1052,7 +1053,7 @@ void mem_init(unsigned long start_low_mem, ...@@ -1052,7 +1053,7 @@ void mem_init(unsigned long start_low_mem,
int codepages = 0; int codepages = 0;
int reservedpages = 0; int reservedpages = 0;
int datapages = 0; int datapages = 0;
unsigned long tmp; unsigned long tmp, mask;
unsigned short * p; unsigned short * p;
extern int etext; extern int etext;
...@@ -1067,22 +1068,34 @@ void mem_init(unsigned long start_low_mem, ...@@ -1067,22 +1068,34 @@ void mem_init(unsigned long start_low_mem,
start_mem = (unsigned long) p; start_mem = (unsigned long) p;
while (p > mem_map) while (p > mem_map)
*--p = MAP_PAGE_RESERVED; *--p = MAP_PAGE_RESERVED;
/* set up the free-area data structures */
for (mask = PAGE_MASK, tmp = 0 ; tmp < NR_MEM_LISTS ; tmp++, mask <<= 1) {
unsigned long bitmap_size;
free_area_list[tmp].prev = free_area_list[tmp].next = &free_area_list[tmp];
end_mem = (end_mem + ~mask) & mask;
bitmap_size = end_mem >> (PAGE_SHIFT + tmp);
bitmap_size = (bitmap_size + 7) >> 3;
free_area_map[tmp] = (unsigned char *) start_mem;
memset((void *) start_mem, 0, bitmap_size);
start_mem += bitmap_size;
}
/* mark usable pages in the mem_map[] */
start_low_mem = PAGE_ALIGN(start_low_mem); start_low_mem = PAGE_ALIGN(start_low_mem);
start_mem = PAGE_ALIGN(start_mem); start_mem = PAGE_ALIGN(start_mem);
while (start_low_mem < 0xA0000) { while (start_low_mem < 0xA0000) {
mem_map[MAP_NR(start_low_mem)] = 0; mem_map[MAP_NR(start_low_mem)] = 0;
start_low_mem += PAGE_SIZE; start_low_mem += PAGE_SIZE;
} }
while (start_mem < end_mem) { while (start_mem < high_memory) {
mem_map[MAP_NR(start_mem)] = 0; mem_map[MAP_NR(start_mem)] = 0;
start_mem += PAGE_SIZE; start_mem += PAGE_SIZE;
} }
#ifdef CONFIG_SOUND #ifdef CONFIG_SOUND
sound_mem_init(); sound_mem_init();
#endif #endif
free_page_list = 0; for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
nr_free_pages = 0;
for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) {
if (mem_map[MAP_NR(tmp)]) { if (mem_map[MAP_NR(tmp)]) {
if (tmp >= 0xA0000 && tmp < 0x100000) if (tmp >= 0xA0000 && tmp < 0x100000)
reservedpages++; reservedpages++;
...@@ -1092,14 +1105,13 @@ void mem_init(unsigned long start_low_mem, ...@@ -1092,14 +1105,13 @@ void mem_init(unsigned long start_low_mem,
datapages++; datapages++;
continue; continue;
} }
*(unsigned long *) tmp = free_page_list; mem_map[MAP_NR(tmp)] = 1;
free_page_list = tmp; free_page(tmp);
nr_free_pages++;
} }
tmp = nr_free_pages << PAGE_SHIFT; tmp = nr_free_pages << PAGE_SHIFT;
printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
tmp >> 10, tmp >> 10,
end_mem >> 10, high_memory >> 10,
codepages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10)); datapages << (PAGE_SHIFT-10));
......
/* /*
* linux/mm/swap.c * linux/mm/swap.c
* *
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
*/ */
/* /*
...@@ -45,7 +45,6 @@ static struct swap_info_struct { ...@@ -45,7 +45,6 @@ static struct swap_info_struct {
unsigned long max; unsigned long max;
} swap_info[MAX_SWAPFILES]; } swap_info[MAX_SWAPFILES];
extern unsigned long free_page_list;
extern int shm_swap (int); extern int shm_swap (int);
/* /*
...@@ -486,16 +485,18 @@ static int try_to_free_page(void) ...@@ -486,16 +485,18 @@ static int try_to_free_page(void)
return 0; return 0;
} }
/* static inline void add_mem_queue(struct mem_list * head, struct mem_list * entry)
* Note that this must be atomic, or bad things will happen when {
* pages are requested in interrupts (as malloc can do). Thus the entry->prev = head;
* cli/sti's. entry->next = head->next;
*/ entry->next->prev = entry;
static inline void add_mem_queue(unsigned long addr, unsigned long * queue) head->next = entry;
}
static inline void remove_mem_queue(struct mem_list * head, struct mem_list * entry)
{ {
addr &= PAGE_MASK; entry->next->prev = entry->prev;
*(unsigned long *) addr = *queue; entry->prev->next = entry->next;
*queue = addr;
} }
/* /*
...@@ -509,27 +510,40 @@ static inline void add_mem_queue(unsigned long addr, unsigned long * queue) ...@@ -509,27 +510,40 @@ static inline void add_mem_queue(unsigned long addr, unsigned long * queue)
* With the above two rules, you get a straight-line execution path * With the above two rules, you get a straight-line execution path
* for the normal case, giving better asm-code. * for the normal case, giving better asm-code.
*/ */
void free_page(unsigned long addr)
/*
* Buddy system. Hairy. You really aren't expected to understand this
*/
static inline void free_pages_ok(unsigned long addr, unsigned long order)
{
unsigned long index = addr >> (PAGE_SHIFT + 1 + order);
unsigned long mask = PAGE_MASK << order;
addr &= mask;
nr_free_pages += 1 << order;
while (order < NR_MEM_LISTS-1) {
if (!change_bit(index, free_area_map[order]))
break;
remove_mem_queue(free_area_list+order, (struct mem_list *) (addr ^ (1+~mask)));
order++;
index >>= 1;
mask <<= 1;
addr &= mask;
}
add_mem_queue(free_area_list+order, (struct mem_list *) addr);
}
void free_pages(unsigned long addr, unsigned long order)
{ {
if (addr < high_memory) { if (addr < high_memory) {
unsigned long flag;
unsigned short * map = mem_map + MAP_NR(addr); unsigned short * map = mem_map + MAP_NR(addr);
if (*map) { if (*map) {
if (!(*map & MAP_PAGE_RESERVED)) { if (!(*map & MAP_PAGE_RESERVED)) {
unsigned long flag;
save_flags(flag); save_flags(flag);
cli(); cli();
if (!--*map) { if (!--*map)
if (nr_secondary_pages < MAX_SECONDARY_PAGES) { free_pages_ok(addr, order);
add_mem_queue(addr,&secondary_page_list);
nr_secondary_pages++;
restore_flags(flag);
return;
}
add_mem_queue(addr,&free_page_list);
nr_free_pages++;
}
restore_flags(flag); restore_flags(flag);
} }
return; return;
...@@ -541,57 +555,43 @@ void free_page(unsigned long addr) ...@@ -541,57 +555,43 @@ void free_page(unsigned long addr)
} }
/* /*
* This is one ugly macro, but it simplifies checking, and makes * Some ugly macros to speed up __get_free_pages()..
* this speed-critical place reasonably fast, especially as we have
* to do things with the interrupt flag etc.
*
* Note that this #define is heavily optimized to give fast code
* for the normal case - the if-statements are ordered so that gcc-2.2.2
* will make *no* jumps for the normal code. Don't touch unless you
* know what you are doing.
*/
#define REMOVE_FROM_MEM_QUEUE(queue,nr) \
cli(); \
if ((result = queue) != 0) { \
if (!(result & ~PAGE_MASK) && result < high_memory) { \
queue = *(unsigned long *) result; \
if (!mem_map[MAP_NR(result)]) { \
mem_map[MAP_NR(result)] = 1; \
nr--; \
last_free_pages[index = (index + 1) & (NR_LAST_FREE_PAGES - 1)] = result; \
restore_flags(flag); \
return result; \
} \
printk("Free page %08lx has mem_map = %d\n", \
result,mem_map[MAP_NR(result)]); \
} else \
printk("Result = 0x%08lx - memory map destroyed\n", result); \
queue = 0; \
nr = 0; \
} else if (nr) { \
printk(#nr " is %d, but " #queue " is empty\n",nr); \
nr = 0; \
} \
restore_flags(flag)
/*
* Get physical address of first (actually last :-) free page, and mark it
* used. If no free pages left, return 0.
*
* Note that this is one of the most heavily called functions in the kernel,
* so it's a bit timing-critical (especially as we have to disable interrupts
* in it). See the above macro which does most of the work, and which is
* optimized for a fast normal path of execution.
*/ */
unsigned long __get_free_page(int priority) #define RMQUEUE(order) \
do { struct mem_list * queue = free_area_list+order; \
unsigned long new_order = order; \
do { struct mem_list *next = queue->next; \
if (queue != next) { \
queue->next = next->next; \
next->next->prev = queue; \
mark_used((unsigned long) next, new_order); \
nr_free_pages -= 1 << order; \
restore_flags(flags); \
EXPAND(next, order, new_order); \
return (unsigned long) next; \
} new_order++; queue++; \
} while (new_order < NR_MEM_LISTS); \
} while (0)
static inline int mark_used(unsigned long addr, unsigned long order)
{ {
unsigned long result, flag; return change_bit(addr >> (PAGE_SHIFT+1+order), free_area_map[order]);
static unsigned long index = 0; }
/* this routine can be called at interrupt time via #define EXPAND(addr,low,high) \
malloc. We want to make sure that the critical do { unsigned long size = PAGE_SIZE << high; \
sections of code have interrupts disabled. -RAB while (high > low) { \
Is this code reentrant? */ high--; size >>= 1; cli(); \
add_mem_queue(free_area_list+high, addr); \
mark_used((unsigned long) addr, high); \
restore_flags(flags); \
addr = (void *) (size + (unsigned long) addr); \
} mem_map[MAP_NR((unsigned long) addr)] = 1; \
} while (0)
unsigned long __get_free_pages(int priority, unsigned long order)
{
unsigned long flags;
if (intr_count && priority != GFP_ATOMIC) { if (intr_count && priority != GFP_ATOMIC) {
static int count = 0; static int count = 0;
...@@ -601,18 +601,46 @@ unsigned long __get_free_page(int priority) ...@@ -601,18 +601,46 @@ unsigned long __get_free_page(int priority)
priority = GFP_ATOMIC; priority = GFP_ATOMIC;
} }
} }
save_flags(flag); save_flags(flags);
repeat: repeat:
REMOVE_FROM_MEM_QUEUE(free_page_list,nr_free_pages); cli();
if (priority == GFP_BUFFER) if ((priority==GFP_ATOMIC) || nr_free_pages > MAX_SECONDARY_PAGES) {
RMQUEUE(order);
restore_flags(flags);
return 0; return 0;
if (priority != GFP_ATOMIC) }
if (try_to_free_page()) restore_flags(flags);
goto repeat; if (priority != GFP_BUFFER && try_to_free_page())
REMOVE_FROM_MEM_QUEUE(secondary_page_list,nr_secondary_pages); goto repeat;
return 0; return 0;
} }
/*
* Show free area list (used inside shift_scroll-lock stuff)
* We also calculate the percentage fragmentation. We do this by counting the
* memory on each free list with the exception of the first item on the list.
*/
void show_free_areas(void)
{
unsigned long order, flags;
unsigned long total = 0;
printk("Free pages: %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10));
save_flags(flags);
cli();
for (order=0 ; order < NR_MEM_LISTS; order++) {
struct mem_list * tmp;
unsigned long nr = 0;
for (tmp = free_area_list[order].next ; tmp != free_area_list + order ; tmp = tmp->next) {
nr ++;
}
total += nr * (4 << order);
printk("%lu*%ukB ", nr, 4 << order);
}
restore_flags(flags);
printk("= %lukB)\n", total);
}
/* /*
* Trying to stop swapping from a file is fraught with races, so * Trying to stop swapping from a file is fraught with races, so
* we repeat quite a bit here when we have to pause. swapoff() * we repeat quite a bit here when we have to pause. swapoff()
......
...@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format) ...@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format)
if (timer_active) if (timer_active)
add_timer(&sp->timer); add_timer(&sp->timer);
/* Is place in buffer too rare? then abort. */ /* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80) { if (pos > buffer+PAGE_SIZE-90) {
printk("oops, too many %s sockets for netinfo.\n", printk("oops, too many %s sockets for netinfo.\n",
pro->name); pro->name);
return(strlen(buffer)); return(strlen(buffer));
......
...@@ -244,14 +244,6 @@ raw_sendto(struct sock *sk, unsigned char *from, int len, ...@@ -244,14 +244,6 @@ raw_sendto(struct sock *sk, unsigned char *from, int len,
} }
skb->len = tmp + len; skb->len = tmp + len;
if(dev!=NULL && skb->len > 4095)
{
kfree_skb(skb, FREE_WRITE);
release_sock(sk);
return(-EMSGSIZE);
}
sk->prot->queue_xmit(sk, dev, skb, 1); sk->prot->queue_xmit(sk, dev, skb, 1);
release_sock(sk); release_sock(sk);
return(len); return(len);
......
...@@ -458,7 +458,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority) ...@@ -458,7 +458,7 @@ struct sk_buff *alloc_skb(unsigned int size,int priority)
void kfree_skbmem(void *mem,unsigned size) void kfree_skbmem(void *mem,unsigned size)
{ {
struct sk_buff *x=mem; struct sk_buff *x=(struct sk_buff *) mem;
IS_SKB(x); IS_SKB(x);
if(x->magic_debug_cookie==SK_GOOD_SKB) if(x->magic_debug_cookie==SK_GOOD_SKB)
{ {
......
...@@ -79,7 +79,7 @@ struct sk_buff { ...@@ -79,7 +79,7 @@ struct sk_buff {
unsigned char data[0]; unsigned char data[0];
}; };
#define SK_WMEM_MAX 8192 #define SK_WMEM_MAX 32767
#define SK_RMEM_MAX 32767 #define SK_RMEM_MAX 32767
#define SK_FREED_SKB 0x0DE2C0DE #define SK_FREED_SKB 0x0DE2C0DE
......
...@@ -1655,7 +1655,7 @@ sock_wfree(struct sock *sk, void *mem, unsigned long size) ...@@ -1655,7 +1655,7 @@ sock_wfree(struct sock *sk, void *mem, unsigned long size)
{ {
DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); DPRINTF((DBG_INET, "sock_wfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
IS_SKB(mem); IS_SKB((struct sk_buff *) mem);
kfree_skbmem(mem, size); kfree_skbmem(mem, size);
if (sk) { if (sk) {
sk->wmem_alloc -= size; sk->wmem_alloc -= size;
...@@ -1675,7 +1675,7 @@ void ...@@ -1675,7 +1675,7 @@ void
sock_rfree(struct sock *sk, void *mem, unsigned long size) sock_rfree(struct sock *sk, void *mem, unsigned long size)
{ {
DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size)); DPRINTF((DBG_INET, "sock_rfree(sk=%X, mem=%X, size=%d)\n", sk, mem, size));
IS_SKB(mem); IS_SKB((struct sk_buff *) mem);
kfree_skbmem(mem, size); kfree_skbmem(mem, size);
if (sk) { if (sk) {
sk->rmem_alloc -= size; sk->rmem_alloc -= size;
......
...@@ -152,22 +152,6 @@ get_firstr(struct sock *sk) ...@@ -152,22 +152,6 @@ get_firstr(struct sock *sk)
return skb_dequeue(&sk->rqueue); return skb_dequeue(&sk->rqueue);
} }
/*
* Difference between two values in tcp ack terms.
*/
static long
diff(unsigned long seq1, unsigned long seq2)
{
long d;
d = seq1 - seq2;
if (d > 0) return(d);
/* I hope this returns what I want. */
return(~d+1);
}
/* This routine picks a TCP windows for a socket based on /* This routine picks a TCP windows for a socket based on
the following constraints the following constraints
......
...@@ -263,21 +263,6 @@ udp_send(struct sock *sk, struct sockaddr_in *sin, ...@@ -263,21 +263,6 @@ udp_send(struct sock *sk, struct sockaddr_in *sin,
skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */ skb->len = tmp + sizeof(struct udphdr) + len; /* len + UDP + IP + MAC */
skb->dev = dev; skb->dev = dev;
#ifdef OLD
/*
* This code used to hack in some form of fragmentation.
* I removed that, since it didn't work anyway, and it made the
* code a bad thing to read and understand. -FvK
*/
if (len > dev->mtu) {
#else
if (skb->len > 4095)
{
#endif
printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
return(-EMSGSIZE);
}
/* Fill in the UDP header. */ /* Fill in the UDP header. */
uh = (struct udphdr *) buff; uh = (struct udphdr *) buff;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment