Commit 24c9da66 authored by Linus Torvalds's avatar Linus Torvalds

Second patch to 0.96a

I have just sent off the second patch to 0.96a: it should be on the
normal ftp-sites (nic, tsx-11 and banjo), although the only site which I
can make it directly readable on is banjo, so on the other sites it will
take the site-managers to make the patch available.

Patch 2 implements:

- itimers (by Darren Senn), which are now also used to implement the
  alarm() system call.

- ultrastor scsi driver patches (by gentzel)

- [f]statfs() system call is implemented (so df can be made fs-
  independent). Also some other minor fs-changes for the upcoming new
  filesystem. Patches by Remy Card.

- preliminary core-file dumping code (linux creates a core-file, but
  it's not in the correct format yet [*]).

- minor changes/bugfixes.

While patching in patch1 is a good idea for anybody, patch 2 isn't
really vital. I've made it available just so kernel hackers can keep up
with the kernel I have right now if they wish. Patch 2 is relative to
patch 1: you have to patch that in first.

[*] The current core-file is very simple, and the kernel code is there
just so that some enterprising character can expand it. A core-file
looks like this right now:

offset data
0x0000 "core-dump: regs=\n"
0x0040 struct pt_regs (see <sys/ptrace.c>)
0x0400 "floating-point regs:\n"
0x0440 struct i387 (see <linux/sched.h>)
0x0800 the first 1kB of user-space

Not very practical, but it /might/ help if the X-server dies of a
segmentation fault or similar (you can use pt_regs.eip to see where it
happened). The kernel code is very easy to change to accomodate for the
real core-file format, I just didn't know what it should be.

                Linus
parent 5b58d8fe
...@@ -224,8 +224,7 @@ got_sectors: ...@@ -224,8 +224,7 @@ got_sectors:
mov ax,#0x021c ! /dev/PS0 - 1.44Mb mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18 cmp bx,#18
je root_defined je root_defined
undef_root: mov ax,#0x0200 ! /dev/fd0 - autodetect
jmp undef_root
root_defined: root_defined:
seg cs seg cs
mov root_dev,ax mov root_dev,ax
......
...@@ -21,7 +21,9 @@ ...@@ -21,7 +21,9 @@
#include <errno.h> #include <errno.h>
#include <linux/string.h> #include <linux/string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ptrace.h>
#include <a.out.h> #include <a.out.h>
#include <fcntl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -39,6 +41,86 @@ extern int sys_close(int fd); ...@@ -39,6 +41,86 @@ extern int sys_close(int fd);
*/ */
#define MAX_ARG_PAGES 32 #define MAX_ARG_PAGES 32
/*
* These are the only things you should do on a core-file: use only these
* macros to write out all the necessary info.
*/
#define DUMP_WRITE(addr,nr) \
while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
#define DUMP_SEEK(offset) \
if (file.f_op->lseek) { \
if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
goto close_coredump; \
} else file.f_pos = (offset)
/*
* Routine writes a core dump image in the current directory.
* Currently only a stub-function.
*
* Note that setuid/setgid files won't make a core-dump if the uid/gid
* changed due to the set[u|g]id. It's enforced by the "current->dumpable"
* field, which also makes sure the core-dumps won't be recursive if the
* dumping of the process results in another error..
*/
int core_dump(long signr, struct pt_regs * regs)
{
struct inode * inode = NULL;
struct file file;
unsigned short fs;
int has_dumped = 0;
if (!current->dumpable)
return 0;
current->dumpable = 0;
__asm__("mov %%fs,%0":"=r" (fs));
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode))
goto end_coredump;
if (!S_ISREG(inode->i_mode))
goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_coredump;
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
file.f_inode = inode;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
if (file.f_op->open)
if (file.f_op->open(inode,&file))
goto end_coredump;
if (!file.f_op->write)
goto close_coredump;
has_dumped = 1;
/* write and seek example: from kernel space */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
DUMP_WRITE("core-dump, regs=\n",17);
DUMP_SEEK(64);
DUMP_WRITE(regs,sizeof(*regs));
if (current->used_math) {
if (last_task_used_math == current)
__asm__("clts ; fnsave %0"::"m" (current->tss.i387));
DUMP_SEEK(1024);
DUMP_WRITE("floating-point regs=\n",21);
DUMP_SEEK(1088);
DUMP_WRITE(&current->tss.i387,sizeof(current->tss.i387));
}
/* now we start writing out the user space info */
__asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
/* the dummy dump-file contains the first block of user space... */
DUMP_SEEK(2048);
DUMP_WRITE(0,1024);
close_coredump:
if (file.f_op->release)
file.f_op->release(inode,&file);
end_coredump:
__asm__("mov %0,%%fs"::"r" (fs));
iput(inode);
return has_dumped;
}
/* /*
* Note that a shared library must be both readable and executable due to * Note that a shared library must be both readable and executable due to
* security reasons. * security reasons.
...@@ -406,6 +488,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename, ...@@ -406,6 +488,7 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
} }
} }
/* OK, This is the point of no return */ /* OK, This is the point of no return */
current->dumpable = 1;
for (i=0; (ch = get_fs_byte(filename++)) != '\0';) for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
if (ch == '/') if (ch == '/')
i = 0; i = 0;
...@@ -421,6 +504,9 @@ int do_execve(unsigned long * eip,long tmp,char * filename, ...@@ -421,6 +504,9 @@ int do_execve(unsigned long * eip,long tmp,char * filename,
iput(current->libraries[i].library); iput(current->libraries[i].library);
current->libraries[i].library = NULL; current->libraries[i].library = NULL;
} }
if (e_uid != current->euid || e_gid != current->egid ||
!permission(inode,MAY_READ))
current->dumpable = 0;
current->numlibraries = 0; current->numlibraries = 0;
current->executable = inode; current->executable = inode;
current->signal = 0; current->signal = 0;
......
/* /*
* linux/fs/bitmap.c * linux/fs/minix/bitmap.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
...@@ -44,6 +44,35 @@ __asm__("cld\n" \ ...@@ -44,6 +44,35 @@ __asm__("cld\n" \
:"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \ :"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
__res;}) __res;})
static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
unsigned numbits)
{
unsigned i, j, end, sum = 0;
struct buffer_head *bh;
for (i=0; (i<numblocks) && numbits; i++) {
if (!(bh=map[i]))
return(0);
if (numbits >= (8*BLOCK_SIZE)) {
end = BLOCK_SIZE;
numbits -= 8*BLOCK_SIZE;
} else {
int tmp;
end = numbits >> 3;
numbits &= 0x7;
tmp = bh->b_data[end] & ((1<<numbits)-1);
sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
numbits = 0;
}
for (j=0; j<end; j++)
sum += nibblemap[bh->b_data[j] & 0xf]
+ nibblemap[(bh->b_data[j]>>4)&0xf];
}
return(sum);
}
int minix_free_block(int dev, int block) int minix_free_block(int dev, int block)
{ {
struct super_block * sb; struct super_block * sb;
...@@ -107,6 +136,12 @@ int minix_new_block(int dev) ...@@ -107,6 +136,12 @@ int minix_new_block(int dev)
return j; return j;
} }
unsigned long minix_count_free_blocks(struct super_block *sb)
{
return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
<< sb->s_log_zone_size;
}
void minix_free_inode(struct inode * inode) void minix_free_inode(struct inode * inode)
{ {
struct buffer_head * bh; struct buffer_head * bh;
...@@ -182,3 +217,8 @@ struct inode * minix_new_inode(int dev) ...@@ -182,3 +217,8 @@ struct inode * minix_new_inode(int dev)
inode->i_op = NULL; inode->i_op = NULL;
return inode; return inode;
} }
unsigned long minix_count_free_inodes(struct super_block *sb)
{
return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
}
/* /*
* linux/fs/chrdev.c * linux/fs/minix/blkdev.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
...@@ -19,7 +19,6 @@ static int blkdev_open(struct inode * inode, struct file * filp) ...@@ -19,7 +19,6 @@ static int blkdev_open(struct inode * inode, struct file * filp)
{ {
int i; int i;
check_disk_change(inode->i_rdev);
i = MAJOR(inode->i_rdev); i = MAJOR(inode->i_rdev);
if (i < MAX_BLKDEV) { if (i < MAX_BLKDEV) {
filp->f_op = blkdev_fops[i]; filp->f_op = blkdev_fops[i];
......
/* /*
* linux/fs/chrdev.c * linux/fs/minix/chrdev.c
* *
* (C) 1991 Linus Torvalds * (C) 1991 Linus Torvalds
*/ */
......
/* /*
* linux/fs/minix/dir.c * linux/fs/minix/dir.c
* *
* minix directory hadnling functions * (C) 1991 Linus Torvalds
*
* minix directory handling functions
*/ */
#include <errno.h> #include <errno.h>
......
/* /*
* linux/fs/minix/file.c * linux/fs/minix/file.c
* *
* (C) 1991 Linus Torvalds
*
* minix regular file handling primitives * minix regular file handling primitives
*/ */
...@@ -212,10 +214,8 @@ static int minix_file_write(struct inode * inode, struct file * filp, char * buf ...@@ -212,10 +214,8 @@ static int minix_file_write(struct inode * inode, struct file * filp, char * buf
brelse(bh); brelse(bh);
} }
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
} filp->f_pos = pos;
inode->i_dirt = 1; inode->i_dirt = 1;
return written; return written;
} }
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/segment.h>
int sync_dev(int dev); int sync_dev(int dev);
...@@ -40,12 +41,14 @@ static struct super_operations minix_sops = { ...@@ -40,12 +41,14 @@ static struct super_operations minix_sops = {
minix_read_inode, minix_read_inode,
minix_write_inode, minix_write_inode,
minix_put_inode, minix_put_inode,
minix_put_super minix_put_super,
minix_statfs
}; };
struct super_block *minix_read_super(struct super_block *s,void *data) struct super_block *minix_read_super(struct super_block *s,void *data)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct minix_super_block *ms;
int i,dev=s->s_dev,block; int i,dev=s->s_dev,block;
lock_super(s); lock_super(s);
...@@ -55,8 +58,17 @@ struct super_block *minix_read_super(struct super_block *s,void *data) ...@@ -55,8 +58,17 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
printk("bread failed\n"); printk("bread failed\n");
return NULL; return NULL;
} }
*((struct minix_super_block *) s) = /* *((struct minix_super_block *) s) =
*((struct minix_super_block *) bh->b_data); *((struct minix_super_block *) bh->b_data); */
ms = (struct minix_super_block *) bh->b_data;
s->s_ninodes = ms->s_ninodes;
s->s_nzones = ms->s_nzones;
s->s_imap_blocks = ms->s_imap_blocks;
s->s_zmap_blocks = ms->s_zmap_blocks;
s->s_firstdatazone = ms->s_firstdatazone;
s->s_log_zone_size = ms->s_log_zone_size;
s->s_max_size = ms->s_max_size;
s->s_magic = ms->s_magic;
brelse(bh); brelse(bh);
if (s->s_magic != MINIX_SUPER_MAGIC) { if (s->s_magic != MINIX_SUPER_MAGIC) {
s->s_dev = 0; s->s_dev = 0;
...@@ -103,6 +115,21 @@ struct super_block *minix_read_super(struct super_block *s,void *data) ...@@ -103,6 +115,21 @@ struct super_block *minix_read_super(struct super_block *s,void *data)
return s; return s;
} }
void minix_statfs (struct super_block *sb, struct statfs *buf)
{
long tmp;
put_fs_long(MINIX_SUPER_MAGIC, &buf->f_type);
put_fs_long(1024, &buf->f_bsize);
put_fs_long(sb->s_nzones << sb->s_log_zone_size, &buf->f_blocks);
tmp = minix_count_free_blocks(sb);
put_fs_long(tmp, &buf->f_bfree);
put_fs_long(tmp, &buf->f_bavail);
put_fs_long(sb->s_ninodes, &buf->f_files);
put_fs_long(minix_count_free_inodes(sb), &buf->f_ffree);
/* Don't know what value to put in buf->f_fsid */
}
static int _minix_bmap(struct inode * inode,int block,int create) static int _minix_bmap(struct inode * inode,int block,int create)
{ {
struct buffer_head * bh; struct buffer_head * bh;
......
/* /*
* linux/fs/minix/symlink.c * linux/fs/minix/symlink.c
* *
* (C) 1991 Linus Torvalds
*
* minix symlink handling code * minix symlink handling code
*/ */
......
...@@ -201,7 +201,7 @@ int open_namei(const char * pathname, int flag, int mode, ...@@ -201,7 +201,7 @@ int open_namei(const char * pathname, int flag, int mode,
if ((flag & O_TRUNC) && !(flag & O_ACCMODE)) if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
flag |= O_WRONLY; flag |= O_WRONLY;
mode &= 0777 & ~current->umask; mode &= 07777 & ~current->umask;
mode |= I_REGULAR; mode |= I_REGULAR;
if (!(dir = dir_namei(pathname,&namelen,&basename,NULL))) if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
return -ENOENT; return -ENOENT;
......
...@@ -33,14 +33,34 @@ int sys_ustat(int dev, struct ustat * ubuf) ...@@ -33,14 +33,34 @@ int sys_ustat(int dev, struct ustat * ubuf)
int sys_statfs(const char * path, struct statfs * buf) int sys_statfs(const char * path, struct statfs * buf)
{ {
printk("statfs not implemented\n"); struct inode * inode;
verify_area(buf, sizeof(struct statfs));
if (!(inode = namei(path)))
return -ENOENT;
if (!inode->i_sb->s_op->statfs) {
iput(inode);
return -ENOSYS; return -ENOSYS;
}
inode->i_sb->s_op->statfs(inode->i_sb, buf);
iput(inode);
return 0;
} }
int sys_fstatfs(unsigned int fd, struct statfs * buf) int sys_fstatfs(unsigned int fd, struct statfs * buf)
{ {
printk("fstatfs not implemented\n"); struct inode * inode;
struct file * file;
verify_area(buf, sizeof(struct statfs));
if (fd >= NR_OPEN || !(file = current->filp[fd]))
return -EBADF;
if (!(inode = file->f_inode))
return -ENOENT;
if (!inode->i_sb->s_op->statfs)
return -ENOSYS; return -ENOSYS;
inode->i_sb->s_op->statfs(inode->i_sb, buf);
return 0;
} }
int sys_truncate(const char * path, unsigned int length) int sys_truncate(const char * path, unsigned int length)
...@@ -256,13 +276,13 @@ int sys_open(const char * filename,int flag,int mode) ...@@ -256,13 +276,13 @@ int sys_open(const char * filename,int flag,int mode)
if (!current->filp[fd]) if (!current->filp[fd])
break; break;
if (fd>=NR_OPEN) if (fd>=NR_OPEN)
return -EINVAL; return -EMFILE;
current->close_on_exec &= ~(1<<fd); current->close_on_exec &= ~(1<<fd);
f=0+file_table; f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++) for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break; if (!f->f_count) break;
if (i>=NR_FILE) if (i>=NR_FILE)
return -EINVAL; return -ENFILE;
(current->filp[fd] = f)->f_count++; (current->filp[fd] = f)->f_count++;
if ((i = open_namei(filename,flag,mode,&inode))<0) { if ((i = open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL; current->filp[fd]=NULL;
......
...@@ -174,6 +174,7 @@ int sys_pipe(unsigned long * fildes) ...@@ -174,6 +174,7 @@ int sys_pipe(unsigned long * fildes)
} }
f[0]->f_inode = f[1]->f_inode = inode; f[0]->f_inode = f[1]->f_inode = inode;
f[0]->f_pos = f[1]->f_pos = 0; f[0]->f_pos = f[1]->f_pos = 0;
f[0]->f_flags = f[1]->f_flags = 0;
f[0]->f_op = &read_pipe_fops; f[0]->f_op = &read_pipe_fops;
f[0]->f_mode = 1; /* read */ f[0]->f_mode = 1; /* read */
f[1]->f_op = &write_pipe_fops; f[1]->f_op = &write_pipe_fops;
......
...@@ -18,9 +18,11 @@ __asm__ volatile ("outb %0,%1" ...@@ -18,9 +18,11 @@ __asm__ volatile ("outb %0,%1"
extern void inline outb_p(char value, unsigned short port) extern void inline outb_p(char value, unsigned short port)
{ {
__asm__ volatile ("outb %0,%1\n\t" __asm__ volatile ("outb %0,%1\n\t"
#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
#endif
"outb %0,$0x80" "outb %0,$0x80"
::"a" ((char) value),"d" ((unsigned short) port)); ::"a" ((char) value),"d" ((unsigned short) port));
} }
...@@ -37,9 +39,11 @@ extern unsigned char inline inb_p(unsigned short port) ...@@ -37,9 +39,11 @@ extern unsigned char inline inb_p(unsigned short port)
{ {
unsigned char _v; unsigned char _v;
__asm__ volatile ("inb %1,%0\n\t" __asm__ volatile ("inb %1,%0\n\t"
#ifdef REALLY_SLOW_IO
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
"outb %0,$0x80\n\t" "outb %0,$0x80\n\t"
#endif
"outb %0,$0x80" "outb %0,$0x80"
:"=a" (_v):"d" ((unsigned short) port)); :"=a" (_v):"d" ((unsigned short) port));
return _v; return _v;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/dirent.h> #include <sys/dirent.h>
#include <sys/vfs.h>
/* devices are as follows: (same as minix, so we can use the minix /* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.) * file system. These are major numbers.)
...@@ -135,12 +136,12 @@ typedef struct select_table_struct { ...@@ -135,12 +136,12 @@ typedef struct select_table_struct {
} select_table; } select_table;
struct super_block { struct super_block {
unsigned short s_ninodes; unsigned long s_ninodes;
unsigned short s_nzones; unsigned long s_nzones;
unsigned short s_imap_blocks; unsigned long s_imap_blocks;
unsigned short s_zmap_blocks; unsigned long s_zmap_blocks;
unsigned short s_firstdatazone; unsigned long s_firstdatazone;
unsigned short s_log_zone_size; unsigned long s_log_zone_size;
unsigned long s_max_size; unsigned long s_max_size;
unsigned short s_magic; unsigned short s_magic;
/* These are only in memory */ /* These are only in memory */
...@@ -191,6 +192,7 @@ struct super_operations { ...@@ -191,6 +192,7 @@ struct super_operations {
void (*write_inode) (struct inode *inode); void (*write_inode) (struct inode *inode);
void (*put_inode) (struct inode *inode); void (*put_inode) (struct inode *inode);
void (*put_super)(struct super_block *sb); void (*put_super)(struct super_block *sb);
void (*statfs) (struct super_block *sb, struct statfs *buf);
}; };
struct file_system_type { struct file_system_type {
......
...@@ -60,8 +60,10 @@ extern int minix_rename(struct inode * old_dir, const char * old_name, int old_l ...@@ -60,8 +60,10 @@ extern int minix_rename(struct inode * old_dir, const char * old_name, int old_l
struct inode * new_dir, const char * new_name, int new_len); struct inode * new_dir, const char * new_name, int new_len);
extern struct inode * minix_new_inode(int dev); extern struct inode * minix_new_inode(int dev);
extern void minix_free_inode(struct inode * inode); extern void minix_free_inode(struct inode * inode);
extern unsigned long minix_count_free_inodes(struct super_block *sb);
extern int minix_new_block(int dev); extern int minix_new_block(int dev);
extern int minix_free_block(int dev, int block); extern int minix_free_block(int dev, int block);
extern unsigned long minix_count_free_blocks(struct super_block *sb);
extern int minix_create_block(struct inode *, int); extern int minix_create_block(struct inode *, int);
extern int minix_bmap(struct inode *,int); extern int minix_bmap(struct inode *,int);
...@@ -72,6 +74,7 @@ extern struct super_block *minix_read_super(struct super_block *,void *); ...@@ -72,6 +74,7 @@ extern struct super_block *minix_read_super(struct super_block *,void *);
extern void minix_read_inode(struct inode *); extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *); extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *); extern void minix_put_inode(struct inode *);
extern void minix_statfs(struct super_block *, struct statfs *);
extern int minix_lseek(struct inode *, struct file *, off_t, int); extern int minix_lseek(struct inode *, struct file *, off_t, int);
extern int minix_read(struct inode *, struct file *, char *, int); extern int minix_read(struct inode *, struct file *, char *, int);
......
...@@ -119,6 +119,7 @@ struct task_struct { ...@@ -119,6 +119,7 @@ struct task_struct {
long blocked; /* bitmap of masked signals */ long blocked; /* bitmap of masked signals */
/* various fields */ /* various fields */
int exit_code; int exit_code;
int dumpable;
unsigned long start_code,end_code,end_data,brk,start_stack; unsigned long start_code,end_code,end_data,brk,start_stack;
long pid,pgrp,session,leader; long pid,pgrp,session,leader;
int groups[NGROUPS]; int groups[NGROUPS];
...@@ -134,7 +135,9 @@ struct task_struct { ...@@ -134,7 +135,9 @@ struct task_struct {
struct task_struct *next_wait; struct task_struct *next_wait;
unsigned short uid,euid,suid; unsigned short uid,euid,suid;
unsigned short gid,egid,sgid; unsigned short gid,egid,sgid;
unsigned long timeout,alarm; unsigned long timeout;
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_incr;
long utime,stime,cutime,cstime,start_time; long utime,stime,cutime,cstime,start_time;
unsigned long min_flt, maj_flt; unsigned long min_flt, maj_flt;
unsigned long cmin_flt, cmaj_flt; unsigned long cmin_flt, cmaj_flt;
...@@ -181,12 +184,12 @@ struct task_struct { ...@@ -181,12 +184,12 @@ struct task_struct {
#define INIT_TASK \ #define INIT_TASK \
/* state etc */ { 0,15,15, \ /* state etc */ { 0,15,15, \
/* signals */ 0,{{},},0, \ /* signals */ 0,{{},},0, \
/* ec,brk... */ 0,0,0,0,0,0, \ /* ec,brk... */ 0,0,0,0,0,0,0, \
/* pid etc.. */ 0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \
/* suppl grps*/ {NOGROUP,}, \ /* suppl grps*/ {NOGROUP,}, \
/* proc links*/ &init_task.task,NULL,NULL,NULL,NULL, \ /* proc links*/ &init_task.task,NULL,NULL,NULL,NULL, \
/* uid etc */ 0,0,0,0,0,0, \ /* uid etc */ 0,0,0,0,0,0, \
/* timeout */ 0,0,0,0,0,0,0, \ /* timeout */ 0,0,0,0,0,0,0,0,0,0,0,0, \
/* min_flt */ 0,0,0,0, \ /* min_flt */ 0,0,0,0, \
/* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \ /* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
{0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \ {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
......
...@@ -106,6 +106,8 @@ extern int sys_fstatfs(); ...@@ -106,6 +106,8 @@ extern int sys_fstatfs();
extern int sys_ioperm(); extern int sys_ioperm();
extern int sys_socketcall(); extern int sys_socketcall();
extern int sys_syslog(); extern int sys_syslog();
extern int sys_getitimer();
extern int sys_setitimer();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, 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_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
...@@ -126,7 +128,7 @@ sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib, ...@@ -126,7 +128,7 @@ sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
sys_socketcall, sys_syslog }; sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer };
/* So we don't have to do any more manual updating.... */ /* So we don't have to do any more manual updating.... */
int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
...@@ -117,6 +117,9 @@ ...@@ -117,6 +117,9 @@
extern int errno; extern int errno;
#define __NR_setitimer 104
#define __NR_getitimer 105
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \ #define _syscall0(type,name) \
type name(void) \ type name(void) \
......
...@@ -43,9 +43,10 @@ typedef unsigned int sigset_t; /* 32 bits */ ...@@ -43,9 +43,10 @@ typedef unsigned int sigset_t; /* 32 bits */
#define SIGPOLL SIGIO #define SIGPOLL SIGIO
#define SIGXCPU 24 #define SIGXCPU 24
#define SIGXFSZ 25 #define SIGXFSZ 25
*/
#define SIGVTALRM 26 #define SIGVTALRM 26
#define SIGPROF 27 #define SIGPROF 27
*/
#define SIGWINCH 28 #define SIGWINCH 28
......
...@@ -54,6 +54,9 @@ struct itimerval { ...@@ -54,6 +54,9 @@ struct itimerval {
struct timeval it_value; /* current value */ struct timeval it_value; /* current value */
}; };
int getitimer(int which, struct itimerval *value);
int setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
#include <time.h> #include <time.h>
#include <sys/types.h> #include <sys/types.h>
......
...@@ -28,7 +28,7 @@ CPP =cpp -nostdinc -I../include ...@@ -28,7 +28,7 @@ CPP =cpp -nostdinc -I../include
OBJS = sched.o sys_call.o traps.o asm.o fork.o \ OBJS = sched.o sys_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \ panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o ptrace.o ioport.o signal.o mktime.o ptrace.o ioport.o itimer.o
kernel.o: $(OBJS) kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS) $(LD) -r -o kernel.o $(OBJS)
......
...@@ -149,47 +149,40 @@ extern inline void unlock_buffer(struct buffer_head * bh) ...@@ -149,47 +149,40 @@ extern inline void unlock_buffer(struct buffer_head * bh)
wake_up(&bh->b_wait); wake_up(&bh->b_wait);
} }
extern inline void end_request(int uptodate) static void end_request(int uptodate)
{ {
struct request * tmp; struct request * req;
struct buffer_head * bh;
tmp = CURRENT;
DEVICE_OFF(tmp->dev);
CURRENT = tmp->next;
if (tmp->bh) {
tmp->bh->b_uptodate = uptodate;
unlock_buffer(tmp->bh);
}
if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",tmp->dev,
tmp->bh->b_blocknr);
}
wake_up(&tmp->waiting);
tmp->dev = -1;
wake_up(&wait_for_request);
}
extern inline void next_buffer(int uptodate)
{
struct buffer_head *tmp;
tmp = CURRENT->bh; req = CURRENT;
CURRENT->bh = tmp->b_reqnext; req->errors = 0;
tmp->b_reqnext = NULL;
tmp->b_uptodate = uptodate;
unlock_buffer(tmp);
if (!uptodate) { if (!uptodate) {
printk(DEVICE_NAME " I/O error\n\r"); printk(DEVICE_NAME " I/O error\n\r");
printk("dev %04x, block %d\n\r",tmp->b_dev, tmp->b_blocknr); printk("dev %04x, sector %d\n\r",req->dev,req->sector);
req->nr_sectors--;
req->nr_sectors &= ~1;
req->sector += 2;
req->sector &= ~1;
} }
if (!CURRENT->bh) { if (bh = req->bh) {
printk("next_buffer: request buffer list destroyed\r\n"); req->bh = bh->b_reqnext;
end_request(0); bh->b_reqnext = NULL;
bh->b_uptodate = uptodate;
unlock_buffer(bh);
if (bh = req->bh) {
if (req->nr_sectors < 2) {
req->nr_sectors = 2;
printk("end_request: buffer-list destroyed\n");
}
req->buffer = bh->b_data;
return; return;
} }
CURRENT->buffer = CURRENT->bh->b_data; }
CURRENT->errors = 0; DEVICE_OFF(req->dev);
CURRENT = req->next;
wake_up(&req->waiting);
req->dev = -1;
wake_up(&wait_for_request);
} }
#ifdef DEVICE_INTR #ifdef DEVICE_INTR
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
/* /*
* Automatic floppy-detection and formatting written by Werner Almesberger * Automatic floppy-detection and formatting written by Werner Almesberger
* (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
* the floppy-change signa| detection. * the floppy-change signal detection.
*/ */
#include <linux/sched.h> #include <linux/sched.h>
...@@ -942,7 +942,8 @@ static void config_types(void) ...@@ -942,7 +942,8 @@ static void config_types(void)
{ {
printk("Floppy drive(s): "); printk("Floppy drive(s): ");
base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15); base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
if (((CMOS_READ(0x14) >> 6) & 1) == 0) base_type[0] = NULL; if (((CMOS_READ(0x14) >> 6) & 1) == 0)
base_type[1] = NULL;
else { else {
printk(", "); printk(", ");
base_type[1] = find_base(1,CMOS_READ(0x10) & 15); base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#define REALLY_SLOW_IO
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
...@@ -423,17 +425,8 @@ static void bad_rw_intr(void) ...@@ -423,17 +425,8 @@ static void bad_rw_intr(void)
if (!CURRENT) if (!CURRENT)
return; return;
if (++CURRENT->errors >= MAX_ERRORS) if (++CURRENT->errors >= MAX_ERRORS)
if (CURRENT->bh && CURRENT->nr_sectors > 2) {
CURRENT->nr_sectors--;
CURRENT->sector++;
if (CURRENT->nr_sectors & 1) {
CURRENT->nr_sectors--;
CURRENT->sector++;
}
next_buffer(0);
} else
end_request(0); end_request(0);
if (CURRENT->errors > MAX_ERRORS/2) else if (CURRENT->errors > MAX_ERRORS/2)
reset = 1; reset = 1;
else else
recalibrate = 1; recalibrate = 1;
...@@ -457,16 +450,15 @@ static void read_intr(void) ...@@ -457,16 +450,15 @@ static void read_intr(void)
if ((i & STAT_MASK) != STAT_OK) if ((i & STAT_MASK) != STAT_OK)
goto bad_read; goto bad_read;
CURRENT->errors = 0; CURRENT->errors = 0;
if (CURRENT->bh && (CURRENT->nr_sectors&1) && CURRENT->nr_sectors > 2)
next_buffer(1);
else
CURRENT->buffer += 512; CURRENT->buffer += 512;
CURRENT->sector++; CURRENT->sector++;
if (--CURRENT->nr_sectors) { i = --CURRENT->nr_sectors;
if (!i || (CURRENT->bh && !(i&1)))
end_request(1);
if (i > 0) {
SET_INTR(&read_intr); SET_INTR(&read_intr);
return; return;
} }
end_request(1);
#if (HD_DELAY > 0) #if (HD_DELAY > 0)
last_req = read_timer(); last_req = read_timer();
#endif #endif
...@@ -487,24 +479,22 @@ static void write_intr(void) ...@@ -487,24 +479,22 @@ static void write_intr(void)
i = (unsigned) inb_p(HD_STATUS); i = (unsigned) inb_p(HD_STATUS);
if ((i & STAT_MASK) != STAT_OK) if ((i & STAT_MASK) != STAT_OK)
goto bad_write; goto bad_write;
if (CURRENT->nr_sectors < 2) { if (CURRENT->nr_sectors > 1 && !(i & DRQ_STAT))
goto bad_write;
CURRENT->sector++;
i = --CURRENT->nr_sectors;
CURRENT->buffer += 512;
if (!i || (CURRENT->bh && !(i & 1)))
end_request(1); end_request(1);
if (i > 0) {
SET_INTR(&write_intr);
port_write(HD_DATA,CURRENT->buffer,256);
} else {
#if (HD_DELAY > 0) #if (HD_DELAY > 0)
last_req = read_timer(); last_req = read_timer();
#endif #endif
do_hd_request(); do_hd_request();
return;
} }
if (!(i & DRQ_STAT))
goto bad_write;
CURRENT->sector++;
CURRENT->nr_sectors--;
if (CURRENT->bh && !(CURRENT->nr_sectors & 1))
next_buffer(1);
else
CURRENT->buffer += 512;
SET_INTR(&write_intr);
port_write(HD_DATA,CURRENT->buffer,256);
return; return;
bad_write: bad_write:
if (i & ERR_STAT) if (i & ERR_STAT)
...@@ -534,15 +524,6 @@ static void hd_times_out(void) ...@@ -534,15 +524,6 @@ static void hd_times_out(void)
printk("HD timeout\n\r"); printk("HD timeout\n\r");
cli(); cli();
if (++CURRENT->errors >= MAX_ERRORS) if (++CURRENT->errors >= MAX_ERRORS)
if (CURRENT->bh && CURRENT->nr_sectors > 2) {
CURRENT->nr_sectors--;
CURRENT->sector++;
if (CURRENT->nr_sectors & 1) {
CURRENT->nr_sectors--;
CURRENT->sector++;
}
next_buffer(0);
} else
end_request(0); end_request(0);
do_hd_request(); do_hd_request();
} }
...@@ -558,7 +539,7 @@ static void do_hd_request(void) ...@@ -558,7 +539,7 @@ static void do_hd_request(void)
dev = MINOR(CURRENT->dev); dev = MINOR(CURRENT->dev);
block = CURRENT->sector; block = CURRENT->sector;
nsect = CURRENT->nr_sectors; nsect = CURRENT->nr_sectors;
if (dev >= (NR_HD<<6) || block+nsect > hd[dev].nr_sects) { if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects) {
end_request(0); end_request(0);
goto repeat; goto repeat;
} }
......
...@@ -125,6 +125,11 @@ static void make_request(int major,int rw, struct buffer_head * bh) ...@@ -125,6 +125,11 @@ static void make_request(int major,int rw, struct buffer_head * bh)
printk("Bad block dev command, must be R/W/RA/WA\n"); printk("Bad block dev command, must be R/W/RA/WA\n");
return; return;
} }
if (blk_size[major])
if (blk_size[major][MINOR(bh->b_dev)] <= bh->b_blocknr) {
bh->b_dirt = bh->b_uptodate = 0;
return;
}
lock_buffer(bh); lock_buffer(bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) { if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
unlock_buffer(bh); unlock_buffer(bh);
......
This diff is collapsed.
...@@ -9,10 +9,6 @@ ...@@ -9,10 +9,6 @@
#ifndef _ULTRASTOR_H #ifndef _ULTRASTOR_H
#define _ULTRASTOR_H #define _ULTRASTOR_H
/* ??? Some of the stuff in this file is really private to ultrastor.c and
should be moved elsewhere (as this file is included by higher-level driver
files). */
/* ??? These don't really belong here */ /* ??? These don't really belong here */
#ifndef TRUE #ifndef TRUE
# define TRUE 1 # define TRUE 1
...@@ -21,32 +17,40 @@ ...@@ -21,32 +17,40 @@
# define FALSE 0 # define FALSE 0
#endif #endif
/* ??? This should go eventually, once the queueing bug is fixed */
#define USE_QUEUECOMMAND FALSE
int ultrastor_14f_detect(int); int ultrastor_14f_detect(int);
const char *ultrastor_14f_info(void); const char *ultrastor_14f_info(void);
#if 0 /* ??? Future direction... */
int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd, int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
void *buff, int bufflen, void *buff, int bufflen,
void (*done)(int, int)); void (*done)(int, int));
#else #if !USE_QUEUECOMMAND
int ultrastor_14f_command(unsigned char target, const void *cmnd, int ultrastor_14f_command(unsigned char target, const void *cmnd,
void *buff, int bufflen); void *buff, int bufflen);
#endif #endif
int ultrastor_14f_abort(int); int ultrastor_14f_abort(int);
int ultrastor_14f_reset(void); int ultrastor_14f_reset(void);
#if 0 /* ??? Future direction... */ #if !USE_QUEUECOMMAND
# define ULTRASTOR_14F \ #define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
TRUE, 0, 0 }
#else
# define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \ { "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, \
ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \ ultrastor_14f_command, 0, ultrastor_14f_abort, ultrastor_14f_reset, \
FALSE, 0, 0 } FALSE, 0, 0 }
#else
#define ULTRASTOR_14F \
{ "UltraStor 14F", ultrastor_14f_detect, ultrastor_14f_info, 0, \
ultrastor_14f_queuecommand, ultrastor_14f_abort, ultrastor_14f_reset, \
TRUE, 0, 0 }
#endif #endif
#define PORT_OVERRIDE 0x330 #define UD_DETECT 0x1
#define UD_COMMAND 0x2
#define UD_RESET 0x4
#ifdef ULTRASTOR_PRIVATE
/* #define PORT_OVERRIDE 0x330 */
/* Port addresses (relative to the base address) */ /* Port addresses (relative to the base address) */
#define LCL_DOORBELL_MASK(port) ((port) + 0x0) #define LCL_DOORBELL_MASK(port) ((port) + 0x0)
...@@ -82,3 +86,5 @@ int ultrastor_14f_reset(void); ...@@ -82,3 +86,5 @@ int ultrastor_14f_reset(void);
#define HA_CMD_WRITE_BUFF 0x4 #define HA_CMD_WRITE_BUFF 0x4
#endif #endif
#endif
...@@ -883,6 +883,8 @@ void con_init(void) ...@@ -883,6 +883,8 @@ void con_init(void)
char *display_ptr; char *display_ptr;
int currcons = 0; int currcons = 0;
long base; long base;
int orig_x = ORIG_X;
int orig_y = ORIG_Y;
video_num_columns = ORIG_VIDEO_COLS; video_num_columns = ORIG_VIDEO_COLS;
video_size_row = video_num_columns * 2; video_size_row = video_num_columns * 2;
...@@ -975,7 +977,7 @@ void con_init(void) ...@@ -975,7 +977,7 @@ void con_init(void)
vt_cons[0].vt_mode = KD_TEXT; vt_cons[0].vt_mode = KD_TEXT;
vc_cons[0].vc_bold_attr = -1; vc_cons[0].vc_bold_attr = -1;
gotoxy(currcons,ORIG_X,ORIG_Y); gotoxy(currcons,orig_x,orig_y);
for (currcons = 1; currcons<NR_CONSOLES; currcons++) { for (currcons = 1; currcons<NR_CONSOLES; currcons++) {
vc_cons[currcons] = vc_cons[0]; vc_cons[currcons] = vc_cons[0];
vt_cons[currcons] = vt_cons[0]; vt_cons[currcons] = vt_cons[0];
......
...@@ -1012,7 +1012,7 @@ void kb_ack(void) ...@@ -1012,7 +1012,7 @@ void kb_ack(void)
int i; int i;
for(i=0; i<0x10000; i++) for(i=0; i<0x10000; i++)
if (inb(0x64) == 0xfa) if (inb(0x60) == 0xfa)
break; break;
} }
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
#include <sys/kd.h>
#include "vt_kern.h"
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif #endif
...@@ -65,6 +68,8 @@ struct tty_queue * table_list[]={ ...@@ -65,6 +68,8 @@ struct tty_queue * table_list[]={
void change_console(unsigned int new_console) void change_console(unsigned int new_console)
{ {
if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
return;
if (new_console == fg_console || new_console >= NR_CONSOLES) if (new_console == fg_console || new_console >= NR_CONSOLES)
return; return;
table_list[0] = con_queues + 0 + new_console*3; table_list[0] = con_queues + 0 + new_console*3;
...@@ -124,9 +129,14 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -124,9 +129,14 @@ void copy_to_cooked(struct tty_struct * tty)
((EOF_CHAR(tty) != _POSIX_VDISABLE) && ((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
(c==EOF_CHAR(tty))))) { (c==EOF_CHAR(tty))))) {
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (c<32) if (c<32) {
PUTCH(127,tty->write_q); PUTCH(8,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(' ',tty->write_q);
PUTCH(8,tty->write_q);
}
PUTCH(8,tty->write_q);
PUTCH(' ',tty->write_q);
PUTCH(8,tty->write_q);
TTY_WRITE_FLUSH(tty); TTY_WRITE_FLUSH(tty);
} }
DEC(tty->secondary->head); DEC(tty->secondary->head);
...@@ -141,9 +151,14 @@ void copy_to_cooked(struct tty_struct * tty) ...@@ -141,9 +151,14 @@ void copy_to_cooked(struct tty_struct * tty)
(c==EOF_CHAR(tty)))) (c==EOF_CHAR(tty))))
continue; continue;
if (L_ECHO(tty)) { if (L_ECHO(tty)) {
if (c<32) if (c<32) {
PUTCH(127,tty->write_q); PUTCH(8,tty->write_q);
PUTCH(127,tty->write_q); PUTCH(' ',tty->write_q);
PUTCH(8,tty->write_q);
}
PUTCH(8,tty->write_q);
PUTCH(32,tty->write_q);
PUTCH(8,tty->write_q);
TTY_WRITE_FLUSH(tty); TTY_WRITE_FLUSH(tty);
} }
DEC(tty->secondary->head); DEC(tty->secondary->head);
......
...@@ -116,7 +116,8 @@ int sys_fork(long ebx,long ecx,long edx, ...@@ -116,7 +116,8 @@ int sys_fork(long ebx,long ecx,long edx,
current->p_cptr = p; current->p_cptr = p;
p->counter = p->priority; p->counter = p->priority;
p->signal = 0; p->signal = 0;
p->alarm = 0; p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
p->leader = 0; /* process leadership doesn't inherit */ p->leader = 0; /* process leadership doesn't inherit */
p->utime = p->stime = 0; p->utime = p->stime = 0;
p->cutime = p->cstime = 0; p->cutime = p->cstime = 0;
......
/*
* linux/kernel/itimer.c
*
* (C) 1992 Darren Senn
*/
/* These are all the functions necessary to implement itimers */
#include <linux/sched.h>
#include <asm/segment.h>
#include <signal.h>
#include <sys/time.h>
#include <errno.h>
static unsigned long tvtojiffies(struct timeval *value)
{
return((unsigned long )value->tv_sec * HZ +
(unsigned long )value->tv_usec / (1000000 / HZ));
}
static void jiffiestotv(unsigned long jiffies, struct timeval *value)
{
value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
value->tv_sec = jiffies / HZ;
return;
}
int _getitimer(int which, struct itimerval *value)
{
register unsigned long val, interval;
switch (which) {
case ITIMER_REAL:
val = current->it_real_value;
interval = current->it_real_incr;
break;
case ITIMER_VIRTUAL:
val = current->it_virt_value;
interval = current->it_virt_incr;
break;
case ITIMER_PROF:
val = current->it_prof_value;
interval = current->it_prof_incr;
break;
default:
return(-EINVAL);
}
jiffiestotv(val, &value->it_value);
jiffiestotv(interval, &value->it_interval);
return(0);
}
int sys_getitimer(int which, struct itimerval *value)
{
struct itimerval get_buffer;
int k;
if (!value)
return -EFAULT;
k = _getitimer(which, &get_buffer);
if (k < 0)
return k;
verify_area(value, sizeof(struct itimerval));
memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
return 0;
}
int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
register unsigned long i, j;
int k;
i = tvtojiffies(&value->it_interval);
j = tvtojiffies(&value->it_value);
if (ovalue && (k = _getitimer(which, ovalue)) < 0)
return k;
switch (which) {
case ITIMER_REAL:
current->it_real_value = j;
current->it_real_incr = i;
break;
case ITIMER_VIRTUAL:
current->it_virt_value = j;
current->it_virt_incr = i;
break;
case ITIMER_PROF:
current->it_prof_value = j;
current->it_prof_incr = i;
break;
default:
return -EINVAL;
}
return 0;
}
int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
struct itimerval set_buffer, get_buffer;
int k;
if (!value)
return -EFAULT;
memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
k = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
if (k < 0 || !ovalue)
return k;
verify_area(ovalue, sizeof(struct itimerval));
memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
return 0;
}
...@@ -58,7 +58,7 @@ static char * sib(struct info * info, int mod) ...@@ -58,7 +58,7 @@ static char * sib(struct info * info, int mod)
char * ea(struct info * info, unsigned short code) char * ea(struct info * info, unsigned short code)
{ {
unsigned char mod,rm; unsigned char mod,rm;
long * tmp = &EAX; long * tmp;
int offset = 0; int offset = 0;
mod = (code >> 6) & 3; mod = (code >> 6) & 3;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <sys/time.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
...@@ -68,7 +69,7 @@ union task_union { ...@@ -68,7 +69,7 @@ union task_union {
char stack[PAGE_SIZE]; char stack[PAGE_SIZE];
}; };
static union task_union init_task = {INIT_TASK,}; static union task_union init_task = {INIT_TASK, };
unsigned long volatile jiffies=0; unsigned long volatile jiffies=0;
unsigned long startup_time=0; unsigned long startup_time=0;
...@@ -134,10 +135,6 @@ void schedule(void) ...@@ -134,10 +135,6 @@ void schedule(void)
(*p)->timeout = 0; (*p)->timeout = 0;
(*p)->state = TASK_RUNNING; (*p)->state = TASK_RUNNING;
} }
if ((*p)->alarm && (*p)->alarm < jiffies) {
(*p)->signal |= (1<<(SIGALRM-1));
(*p)->alarm = 0;
}
if (((*p)->signal & ~(*p)->blocked) && if (((*p)->signal & ~(*p)->blocked) &&
(*p)->state==TASK_INTERRUPTIBLE) (*p)->state==TASK_INTERRUPTIBLE)
(*p)->state=TASK_RUNNING; (*p)->state=TASK_RUNNING;
...@@ -352,7 +349,7 @@ static unsigned long cexp[3] = { ...@@ -352,7 +349,7 @@ static unsigned long cexp[3] = {
2014, /* 0.9834714538216174 * FSCALE, exp(-1/60) */ 2014, /* 0.9834714538216174 * FSCALE, exp(-1/60) */
2037, /* 0.9944598480048967 * FSCALE, exp(-1/180) */ 2037, /* 0.9944598480048967 * FSCALE, exp(-1/180) */
}; };
unsigned long averunnable[3]; /* fixed point numbers */ unsigned long averunnable[3] = { 0, }; /* fixed point numbers */
void update_avg(void) void update_avg(void)
{ {
...@@ -376,7 +373,8 @@ void do_timer(long cpl) ...@@ -376,7 +373,8 @@ void do_timer(long cpl)
{ {
unsigned long mask; unsigned long mask;
struct timer_struct *tp = timer_table+0; struct timer_struct *tp = timer_table+0;
static int avg_cnt; struct task_struct ** task_p;
static int avg_cnt = 0;
for (mask = 1 ; mask ; tp++,mask += mask) { for (mask = 1 ; mask ; tp++,mask += mask) {
if (mask > timer_active) if (mask > timer_active)
...@@ -390,6 +388,25 @@ void do_timer(long cpl) ...@@ -390,6 +388,25 @@ void do_timer(long cpl)
sti(); sti();
} }
/* Update ITIMER_REAL for every task */
for (task_p = &LAST_TASK; task_p >= &FIRST_TASK; task_p--)
if (*task_p && (*task_p)->it_real_value
&& !(--(*task_p)->it_real_value)) {
(*task_p)->signal |= (1<<(SIGALRM-1));
(*task_p)->it_real_value = (*task_p)->it_real_incr;
need_resched = 1;
}
/* Update ITIMER_PROF for the current task */
if (current->it_prof_value && !(--current->it_prof_value)) {
current->it_prof_value = current->it_prof_incr;
current->signal |= (1<<(SIGPROF-1));
}
/* Update ITIMER_VIRT for current task if not in a system call */
if (cpl && current->it_virt_value && !(--current->it_virt_value)) {
current->it_virt_value = current->it_virt_incr;
current->signal |= (1<<(SIGVTALRM-1));
}
if (cpl) if (cpl)
current->utime++; current->utime++;
else else
...@@ -420,12 +437,14 @@ void do_timer(long cpl) ...@@ -420,12 +437,14 @@ void do_timer(long cpl)
int sys_alarm(long seconds) int sys_alarm(long seconds)
{ {
int old = current->alarm; extern int _setitimer(int, struct itimerval *, struct itimerval *);
struct itimerval new, old;
if (old)
old = (old - jiffies) / HZ; new.it_interval.tv_sec = new.it_interval.tv_usec = 0;
current->alarm = (seconds>0)?(jiffies+HZ*seconds):0; new.it_value.tv_sec = seconds;
return (old); new.it_value.tv_usec = 0;
_setitimer(ITIMER_REAL, &new, &old);
return(old.it_value.tv_sec + (old.it_value.tv_usec / 1000000));
} }
int sys_getpid(void) int sys_getpid(void)
......
...@@ -10,8 +10,11 @@ ...@@ -10,8 +10,11 @@
#include <signal.h> #include <signal.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/ptrace.h>
#include <errno.h> #include <errno.h>
extern int core_dump(long signr,struct pt_regs * regs);
int sys_sgetmask() int sys_sgetmask()
{ {
return current->blocked; return current->blocked;
...@@ -117,44 +120,29 @@ int sys_sigaction(int signum, const struct sigaction * action, ...@@ -117,44 +120,29 @@ int sys_sigaction(int signum, const struct sigaction * action,
return 0; return 0;
} }
/*
* Routine writes a core dump image in the current directory.
* Currently not implemented.
*/
int core_dump(long signr)
{
return(0); /* We didn't do a dump */
}
extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); extern int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
int do_signal(long signr,long ebx, long ecx, long edx, int do_signal(long signr,struct pt_regs * regs)
long esi, long edi, long ebp, long eax,
long ds, long es, long fs, long gs,
long orig_eax,
long eip, long cs, long eflags,
unsigned long * esp, long ss)
{ {
unsigned long sa_handler; unsigned long sa_handler;
long old_eip=eip; long old_eip = regs->eip;
struct sigaction * sa = current->sigaction + signr - 1; struct sigaction * sa = current->sigaction + signr - 1;
int longs; int longs;
unsigned long * tmp_esp; unsigned long * tmp_esp;
#ifdef notdef #ifdef notdef
printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n", printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
current->pid, signr, eax, orig_eax, current->pid, signr, regs->eax, regs->orig_eax,
sa->sa_flags & SA_INTERRUPT); sa->sa_flags & SA_INTERRUPT);
#endif #endif
if ((orig_eax != -1) && if ((regs->orig_eax != -1) &&
((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) { ((regs->eax == -ERESTARTSYS) || (regs->eax == -ERESTARTNOINTR))) {
if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) || if ((regs->eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
signr < SIGCONT || signr > SIGTTOU)) signr < SIGCONT || signr > SIGTTOU))
*(&eax) = -EINTR; regs->eax = -EINTR;
else { else {
*(&eax) = orig_eax; regs->eax = regs->orig_eax;
*(&eip) = old_eip -= 2; regs->eip = old_eip -= 2;
} }
} }
sa_handler = (unsigned long) sa->sa_handler; sa_handler = (unsigned long) sa->sa_handler;
...@@ -191,7 +179,7 @@ int do_signal(long signr,long ebx, long ecx, long edx, ...@@ -191,7 +179,7 @@ int do_signal(long signr,long ebx, long ecx, long edx,
case SIGIOT: case SIGIOT:
case SIGFPE: case SIGFPE:
case SIGSEGV: case SIGSEGV:
if (core_dump(signr)) if (core_dump(signr,regs))
do_exit(signr|0x80); do_exit(signr|0x80);
/* fall through */ /* fall through */
default: default:
...@@ -203,19 +191,19 @@ int do_signal(long signr,long ebx, long ecx, long edx, ...@@ -203,19 +191,19 @@ int do_signal(long signr,long ebx, long ecx, long edx,
*/ */
if (sa->sa_flags & SA_ONESHOT) if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL; sa->sa_handler = NULL;
*(&eip) = sa_handler; regs->eip = sa_handler;
longs = (sa->sa_flags & SA_NOMASK)?7:8; longs = (sa->sa_flags & SA_NOMASK)?(7*4):(8*4);
*(&esp) -= longs; regs->esp -= longs;
verify_area(esp,longs*4); tmp_esp = (unsigned long *) regs->esp;
tmp_esp=esp; verify_area(tmp_esp,longs);
put_fs_long((long) sa->sa_restorer,tmp_esp++); put_fs_long((long) sa->sa_restorer,tmp_esp++);
put_fs_long(signr,tmp_esp++); put_fs_long(signr,tmp_esp++);
if (!(sa->sa_flags & SA_NOMASK)) if (!(sa->sa_flags & SA_NOMASK))
put_fs_long(current->blocked,tmp_esp++); put_fs_long(current->blocked,tmp_esp++);
put_fs_long(eax,tmp_esp++); put_fs_long(regs->eax,tmp_esp++);
put_fs_long(ecx,tmp_esp++); put_fs_long(regs->ecx,tmp_esp++);
put_fs_long(edx,tmp_esp++); put_fs_long(regs->edx,tmp_esp++);
put_fs_long(eflags,tmp_esp++); put_fs_long(regs->eflags,tmp_esp++);
put_fs_long(old_eip,tmp_esp++); put_fs_long(old_eip,tmp_esp++);
current->blocked |= sa->sa_mask; current->blocked |= sa->sa_mask;
/* force a supervisor-mode page-in of the signal handler to reduce races */ /* force a supervisor-mode page-in of the signal handler to reduce races */
......
...@@ -180,14 +180,14 @@ void ctrl_alt_del(void) ...@@ -180,14 +180,14 @@ void ctrl_alt_del(void)
*/ */
int sys_setregid(int rgid, int egid) int sys_setregid(int rgid, int egid)
{ {
if (rgid>0) { if (rgid >= 0) {
if ((current->gid == rgid) || if ((current->gid == rgid) ||
suser()) suser())
current->gid = rgid; current->gid = rgid;
else else
return(-EPERM); return(-EPERM);
} }
if (egid>0) { if (egid >= 0) {
if ((current->gid == egid) || if ((current->gid == egid) ||
(current->egid == egid) || (current->egid == egid) ||
suser()) { suser()) {
...@@ -267,7 +267,7 @@ int sys_setreuid(int ruid, int euid) ...@@ -267,7 +267,7 @@ int sys_setreuid(int ruid, int euid)
{ {
int old_ruid = current->uid; int old_ruid = current->uid;
if (ruid>0) { if (ruid >= 0) {
if ((current->euid==ruid) || if ((current->euid==ruid) ||
(old_ruid == ruid) || (old_ruid == ruid) ||
suser()) suser())
...@@ -275,7 +275,7 @@ int sys_setreuid(int ruid, int euid) ...@@ -275,7 +275,7 @@ int sys_setreuid(int ruid, int euid)
else else
return(-EPERM); return(-EPERM);
} }
if (euid>0) { if (euid >= 0) {
if ((old_ruid == euid) || if ((old_ruid == euid) ||
(current->euid == euid) || (current->euid == euid) ||
suser()) { suser()) {
......
...@@ -187,10 +187,13 @@ ret_from_sys_call: ...@@ -187,10 +187,13 @@ ret_from_sys_call:
je 2f je 2f
btrl %ecx,%ebx btrl %ecx,%ebx
movl %ebx,signal(%eax) movl %ebx,signal(%eax)
movl %esp,%ebx
pushl %ebx
incl %ecx incl %ecx
pushl %ecx pushl %ecx
call _do_signal call _do_signal
popl %ecx popl %ecx
popl %ebx
testl %eax, %eax testl %eax, %eax
jne 1b # see if we need to switch tasks, or do more signals jne 1b # see if we need to switch tasks, or do more signals
2: popl %ebx 2: popl %ebx
......
...@@ -23,7 +23,7 @@ CPP =gcc -E -nostdinc -I../include ...@@ -23,7 +23,7 @@ CPP =gcc -E -nostdinc -I../include
-c -o $*.o $< -c -o $*.o $<
OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \ OBJS = ctype.o _exit.o open.o close.o errno.o write.o dup.o setsid.o \
execve.o wait.o string.o malloc.o execve.o wait.o string.o malloc.o itimer.o
lib.a: $(OBJS) lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS) $(AR) rcs lib.a $(OBJS)
......
...@@ -81,7 +81,7 @@ int main(int argc, char ** argv) ...@@ -81,7 +81,7 @@ int main(int argc, char ** argv)
} }
fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
if ((major_root != 2) && (major_root != 3) && if ((major_root != 2) && (major_root != 3) &&
(major_root != 0)) { (major_root != 8) && (major_root != 0)) {
fprintf(stderr, "Illegal root device (major = %d)\n", fprintf(stderr, "Illegal root device (major = %d)\n",
major_root); major_root);
die("Bad root device --- major #"); die("Bad root device --- major #");
......
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