summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-12-07 19:34:29 +0000
committermarcel <marcel@FreeBSD.org>2003-12-07 19:34:29 +0000
commit2ba380839b51268fdea62444f179aed76fb83b0e (patch)
tree08f2958e6ff4c6406aee376ff848a178ecfeda26
parent0e8712116d44b45f10cfd5b1b09b736cffff4b76 (diff)
downloadFreeBSD-src-2ba380839b51268fdea62444f179aed76fb83b0e.zip
FreeBSD-src-2ba380839b51268fdea62444f179aed76fb83b0e.tar.gz
Add kse_switchin(2). This syscall can be used by KSE implementations
to have the kernel switch to a new thread, instead of doing it in userland. It is in fact needed on ia64 where syscall restarts do not return to userland first. It's completely handled inside the kernel. As such, any context created by the kernel as part of an upcall and caused by some syscall needs to be restored by the kernel.
-rw-r--r--sys/kern/kern_kse.c24
-rw-r--r--sys/kern/kern_thread.c24
-rw-r--r--sys/kern/syscalls.master2
-rw-r--r--sys/sys/kse.h1
4 files changed, 51 insertions, 0 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index 985fce2..f47beec 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -382,6 +382,30 @@ proc_linkup(struct proc *p, struct ksegrp *kg,
thread_link(td, kg);
}
+#ifndef _SYS_SYSPROTO_H_
+struct kse_switchin_args {
+ const struct __mcontext *mcp;
+ long val;
+ long *loc;
+};
+#endif
+
+int
+kse_switchin(struct thread *td, struct kse_switchin_args *uap)
+{
+ mcontext_t mc;
+ int error;
+
+ error = (uap->mcp == NULL) ? EINVAL : 0;
+ if (!error)
+ error = copyin(uap->mcp, &mc, sizeof(mc));
+ if (!error)
+ error = set_mcontext(td, &mc);
+ if (!error && uap->loc != NULL)
+ suword(uap->loc, uap->val);
+ return ((error == 0) ? EJUSTRETURN : error);
+}
+
/*
struct kse_thr_interrupt_args {
struct kse_thr_mailbox * tmbx;
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 985fce2..f47beec 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -382,6 +382,30 @@ proc_linkup(struct proc *p, struct ksegrp *kg,
thread_link(td, kg);
}
+#ifndef _SYS_SYSPROTO_H_
+struct kse_switchin_args {
+ const struct __mcontext *mcp;
+ long val;
+ long *loc;
+};
+#endif
+
+int
+kse_switchin(struct thread *td, struct kse_switchin_args *uap)
+{
+ mcontext_t mc;
+ int error;
+
+ error = (uap->mcp == NULL) ? EINVAL : 0;
+ if (!error)
+ error = copyin(uap->mcp, &mc, sizeof(mc));
+ if (!error)
+ error = set_mcontext(td, &mc);
+ if (!error && uap->loc != NULL)
+ suword(uap->loc, uap->val);
+ return ((error == 0) ? EJUSTRETURN : error);
+}
+
/*
struct kse_thr_interrupt_args {
struct kse_thr_mailbox * tmbx;
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 483c92d..76ed423 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -639,6 +639,8 @@
int attrnamespace, void *data, size_t nbytes); }
439 STD BSD { ssize_t extattr_list_link(const char *path, \
int attrnamespace, void *data, size_t nbytes); }
+440 MSTD BSD { int kse_switchin(const struct __mcontext *mcp, \
+ long val, long *loc); }
; Please copy any additions and changes to the following compatability tables:
; sys/ia64/ia32/syscalls.master (take a best guess)
diff --git a/sys/sys/kse.h b/sys/sys/kse.h
index 9cb096b..95b9fff 100644
--- a/sys/sys/kse.h
+++ b/sys/sys/kse.h
@@ -109,6 +109,7 @@ int kse_exit(void);
int kse_release(struct timespec *);
int kse_thr_interrupt(struct kse_thr_mailbox *, int, long);
int kse_wakeup(struct kse_mailbox *);
+int kse_switchin(mcontext_t *, long, long *);
#endif /* !_KERNEL */
#endif /* !_SYS_KSE_H_ */
OpenPOWER on IntegriCloud