patch-2.1.23 linux/arch/alpha/kernel/osf_sys.c

Next file: linux/arch/alpha/kernel/process.c
Previous file: linux/arch/alpha/kernel/entry.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.22/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
@@ -14,6 +14,8 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
@@ -43,6 +45,26 @@
 
 extern asmlinkage int sys_umount(char *);
 extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
+extern asmlinkage unsigned long sys_brk(unsigned long);
+
+/*
+ * This is pure guess-work..
+ */
+asmlinkage int osf_set_program_attributes(
+	unsigned long text_start, unsigned long text_len,
+	unsigned long bss_start, unsigned long bss_len)
+{
+	struct mm_struct *mm;
+
+	lock_kernel();
+	mm = current->mm;
+	mm->end_code = bss_start + bss_len;
+	mm->brk = bss_start + bss_len;
+	printk("set_program_attributes(%lx %lx %lx %lx)\n",
+		text_start, text_len, bss_start, bss_len);
+	unlock_kernel();
+	return 0;
+}
 
 /*
  * OSF/1 directory handling functions...
@@ -134,12 +156,17 @@
 	extern int sys_getpriority(int, int);
 	int prio;
 
+	/*
+	 * We don't need to aquire the kernel lock here, because
+	 * all of these operations are local. sys_getpriority
+	 * will get the lock as required..
+	 */
 	prio = sys_getpriority(which, who);
-	if (prio < 0)
-		return prio;
-
-	regs.r0 = 0;		/* special return: no errors */
-	return 20 - prio;
+	if (prio >= 0) {
+		regs.r0 = 0;		/* special return: no errors */
+		prio = 20 - prio;
+	}
+	return prio;
 }
 
 
@@ -151,25 +178,39 @@
 	return 0;
 }
 
+/*
+ * No need to aquire the kernel lock, we're local..
+ */
 asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
 				     struct pt_regs regs)
 {
-	(&regs)->r20 = current->euid;
-	return current->uid;
+	struct task_struct * tsk = current;
+	(&regs)->r20 = tsk->euid;
+	return tsk->uid;
 }
 
 asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
 				     struct pt_regs regs)
 {
-	(&regs)->r20 = current->egid;
-	return current->gid;
+	struct task_struct * tsk = current;
+	(&regs)->r20 = tsk->egid;
+	return tsk->gid;
 }
 
 asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
 				     struct pt_regs regs)
 {
-	(&regs)->r20 = current->p_opptr->pid;
-	return current->pid;
+	struct task_struct *tsk = current;
+
+	/* 
+	 * This isn't strictly "local" any more and we should actually
+	 * aquire the kernel lock. The "p_opptr" pointer might change
+	 * if the parent goes away (or due to ptrace). But any race
+	 * isn't actually going to matter, as if the parent happens
+	 * to change we can happily return either of the pids.
+	 */
+	(&regs)->r20 = tsk->p_opptr->pid;
+	return tsk->pid;
 }
 
 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
@@ -177,15 +218,20 @@
 				  unsigned long off)
 {
 	struct file *file = NULL;
+	unsigned long ret = -EBADF;
 
+	lock_kernel();
 	if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
 	if (!(flags & MAP_ANONYMOUS)) {
 		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
-			return -EBADF;
+			goto out;
 	}
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	return do_mmap(file, addr, len, prot, flags, off);
+	ret = do_mmap(file, addr, len, prot, flags, off);
+out:
+	unlock_kernel();
+	return ret;
 }
 
 
@@ -228,22 +274,27 @@
 	struct inode *inode;
 	int retval;
 
+	lock_kernel();
 	if (bufsiz > sizeof(struct osf_statfs))
 		 bufsiz = sizeof(struct osf_statfs);
 	retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 	if (retval)
-		return retval;
+		goto out;
 	retval = namei(path, &inode);
 	if (retval)
-		return retval;
+		goto out;
+	retval = -ENOSYS;
 	if (!inode->i_sb->s_op->statfs) {
 		iput(inode);
-		return -ENOSYS;
+		goto out;
 	}
 	inode->i_sb->s_op->statfs(inode->i_sb, &linux_stat, sizeof(linux_stat));
 	linux_to_osf_statfs(&linux_stat, buffer);
 	iput(inode);
-	return 0;
+	retval = 0;
+out:
+	unlock_kernel();
+	return retval;
 }
 
 asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz)
@@ -253,20 +304,27 @@
 	struct inode *inode;
 	int retval;
 
+	lock_kernel();
 	retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 	if (retval)
-		return retval;
+		goto out;
 	if (bufsiz > sizeof(struct osf_statfs))
 		 bufsiz = sizeof(struct osf_statfs);
+	retval = -EBADF;
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
-		return -EBADF;
+		goto out;
+	retval = -ENOENT;
 	if (!(inode = file->f_inode))
-		return -ENOENT;
+		goto out;
+	retval = -ENOSYS;
 	if (!inode->i_sb->s_op->statfs)
-		return -ENOSYS;
+		goto out;
 	inode->i_sb->s_op->statfs(inode->i_sb, &linux_stat, sizeof(linux_stat));
 	linux_to_osf_statfs(&linux_stat, buffer);
-	return 0;
+	retval = 0;
+out:
+	unlock_kernel();
+	return retval;
 }
 
 /*
@@ -414,9 +472,9 @@
 
 asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
 {
-	int retval;
+	int retval = -EINVAL;
 
-	retval = -EINVAL;
+	lock_kernel();
 	switch (typenr) {
 	case 1:
 		retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
@@ -430,12 +488,18 @@
 	default:
 		printk("osf_mount(%ld, %x)\n", typenr, flag);
 	}
+	unlock_kernel();
 	return retval;
 }
 
 asmlinkage int osf_umount(char *path, int flag)
 {
-	return sys_umount(path);
+	int ret;
+
+	lock_kernel();
+	ret = sys_umount(path);
+	unlock_kernel();
+	return ret;
 }
 
 /*
@@ -449,11 +513,12 @@
 	unsigned long ticks;
 	int retval;
 
+	lock_kernel();
 	retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
 	if (retval)
-		return retval;
+		goto out;
 	if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
-		return retval;
+		goto out;
 	copy_from_user(&tmp, sleep, sizeof(*sleep));
 	ticks = tmp.tv_usec;
 	ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
@@ -461,8 +526,9 @@
 	current->timeout = ticks + jiffies;
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
+	retval = 0;
 	if (!remain)
-		return 0;
+		goto out;
 	ticks = jiffies;
 	if (ticks < current->timeout)
 		ticks = current->timeout - ticks;
@@ -472,26 +538,38 @@
 	tmp.tv_sec = ticks / HZ;
 	tmp.tv_usec = ticks % HZ;
 	copy_to_user(remain, &tmp, sizeof(*remain));
-	return 0;
+out:
+	unlock_kernel();
+	return retval;
 }
 
 asmlinkage int osf_utsname(char *name)
 {
-	int error = verify_area(VERIFY_WRITE, name, 5 * 32);
+	int error;
+
+	lock_kernel();
+	error = verify_area(VERIFY_WRITE, name, 5 * 32);
 	if (error)
-		return error;
+		goto out;
 	copy_to_user(name + 0, system_utsname.sysname, 32);
 	copy_to_user(name + 32, system_utsname.nodename, 32);
 	copy_to_user(name + 64, system_utsname.release, 32);
 	copy_to_user(name + 96, system_utsname.version, 32);
 	copy_to_user(name + 128, system_utsname.machine, 32);
-	return 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat)
 {
+	int ret;
+
 	/* for now, simply ignore lowat and hiwat... */
-	return sys_swapon(path, flags);
+	lock_kernel();
+	ret = sys_swapon(path, flags);
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage unsigned long sys_getpagesize(void)
@@ -510,11 +588,15 @@
 	int fd[2];
 	int error;
 
+	lock_kernel();
 	error = do_pipe(fd);
 	if (error)
-		return error;
+		goto out;
 	(&regs)->r20 = fd[1];
-	return fd[0];
+	error = fd[0];
+out:
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -525,9 +607,10 @@
 	unsigned len;
 	int i, error;
 
+	lock_kernel();
 	error = verify_area(VERIFY_WRITE, name, namelen);
 	if (error)
-		return error;
+		goto out;
 
 	len = namelen;
 	if (namelen > 32)
@@ -538,23 +621,29 @@
 		if (system_utsname.domainname[i] == '\0')
 			break;
 	}
-	return 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 
 asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
 {
 	unsigned long raddr;
-	int err;
+	long err;
 
+	lock_kernel();
 	err = sys_shmat(shmid, shmaddr, shmflg, &raddr);
 	if (err)
-		return err;
+		goto out;
 	/*
 	 * This works because all user-level addresses are
 	 * non-negative longs!
 	 */
-	return raddr;
+	err = raddr;
+out:
+	unlock_kernel();
+	return err;
 }
 
 
@@ -628,46 +717,44 @@
 	long error;
 	int *min_buf_size_ptr;
 
+	lock_kernel();
 	switch (code) {
 	case PL_SET:
 		error = verify_area(VERIFY_READ, &args->set.nbytes,
 				    sizeof(args->set.nbytes));
-		if (error)
-			return error;
-		return args->set.nbytes;
-
+		if (!error)
+			error = args->set.nbytes;
+		break;
 	case PL_FSET:
 		error = verify_area(VERIFY_READ, &args->fset.nbytes,
 				    sizeof(args->fset.nbytes));
-		if (error)
-			return error;
-		return args->fset.nbytes;
-
+		if (!error)
+			error = args->fset.nbytes;
+		break;
 	case PL_GET:
 		get_user(min_buf_size_ptr, &args->get.min_buf_size);
 		error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 				    sizeof(*min_buf_size_ptr));
-		if (error)
-			return error;
-		put_user(0, min_buf_size_ptr);
-		return 0;
-
+		if (!error)
+			put_user(0, min_buf_size_ptr);
+		break;
 	case PL_FGET:
 		get_user(min_buf_size_ptr, &args->fget.min_buf_size);
 		error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 				    sizeof(*min_buf_size_ptr));
-		if (error)
-			return error;
-		put_user(0, min_buf_size_ptr);
-		return 0;
-
+		if (!error)
+			put_user(0, min_buf_size_ptr);
+		break;
 	case PL_DEL:
 	case PL_FDEL:
-		return 0;
-
+		error = 0;
+		break;
 	default:
-		return -EOPNOTSUPP;
-	}
+		error = -EOPNOTSUPP;
+		break;
+	};
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -684,6 +771,7 @@
 	asmlinkage unsigned long sys_create_module(char *, unsigned long);
 	long retval;
 
+	lock_kernel();
 	retval = sys_create_module(module_name, size);
 	/*
 	 * we get either a module address or an error number,
@@ -692,28 +780,68 @@
 	 * much larger.
 	 */
 	if (retval + 1000 > 0)
-		return retval;
+		goto out;
 
 	/* tell entry.S:syscall_error that this is NOT an error: */
 	regs.r0 = 0;
+out:
+	unlock_kernel();
 	return retval;
 }
 
+asmlinkage long osf_sysinfo(int command, char *buf, long count)
+{
+	static char * sysinfo_table[] = {
+		system_utsname.sysname,
+		system_utsname.nodename,
+		system_utsname.release,
+		system_utsname.version,
+		system_utsname.machine,
+		"alpha",	/* instruction set architecture */
+		"dummy",	/* hardware serial number */
+		"dummy",	/* hardware manufacturer */
+		"dummy",	/* secure RPC domain */
+	};
+	unsigned long offset;
+	char *res;
+	long len, err = -EINVAL;
+
+	lock_kernel();
+	offset = command-1;
+	if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
+		/* Digital unix has a few unpublished interfaces here */
+		printk("sysinfo(%d)", command);
+		goto out;
+	}
+	res = sysinfo_table[offset];
+	len = strlen(res)+1;
+	if (len > count)
+		len = count;
+	if (copy_to_user(buf, res, len))
+		err = -EFAULT;
+	else
+		err = 0;
+out:
+	unlock_kernel();
+	return err;
+}
 
 asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
 					int *start, void *arg)
 {
 	extern unsigned long rdfpcr(void);
 	unsigned long fpcw;
+	unsigned long ret = -EOPNOTSUPP;
 
+	lock_kernel();
 	switch (op) {
 	case 45:		/* GSI_IEEE_FP_CONTROL */
 		/* build and return current fp control word: */
 		fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
 		fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
 		put_user(fpcw, (unsigned long *) buffer);
-		return 0;
-
+		ret = 0;
+		break;
 	case 46:		/* GSI_IEEE_STATE_AT_SIGNAL */
 		/*
 		 * Not sure anybody will ever use this weird stuff.  These
@@ -721,11 +849,11 @@
 		 * be used when a signal handler starts executing.
 		 */
 		break;
-
 	default:
 		break;
 	}
-	return -EOPNOTSUPP;
+	unlock_kernel();
+	return ret;
 }
 
 
@@ -733,15 +861,17 @@
 					int *start, void *arg)
 {
 	unsigned long fpcw;
+	unsigned long ret = -EOPNOTSUPP;
 
+	lock_kernel();
 	switch (op) {
 	case 14:		/* SSI_IEEE_FP_CONTROL */
 		/* update trap enable bits: */
 		get_user(fpcw, (unsigned long *) buffer);
 		current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
 		current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
-		return 0;
-
+		ret = 0;
+		break;
 	case 15:		/* SSI_IEEE_STATE_AT_SIGNAL */
 	case 16:		/* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
 		/*
@@ -752,5 +882,6 @@
 	default:
 		break;
 	}
-	return -EOPNOTSUPP;
+	unlock_kernel();
+	return ret;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov