Merge branch 'upstream'
This commit is contained in:
commit
93cc12e3f2
@ -135,12 +135,6 @@ coremap_used_bytes() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
vm_tlbshootdown_all(void)
|
|
||||||
{
|
|
||||||
panic("dumbvm tried to do tlb shootdown?!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_tlbshootdown(const struct tlbshootdown *ts)
|
vm_tlbshootdown(const struct tlbshootdown *ts)
|
||||||
{
|
{
|
||||||
|
@ -75,24 +75,21 @@ struct cpu {
|
|||||||
* Accessed by other cpus.
|
* Accessed by other cpus.
|
||||||
* Protected by the IPI lock.
|
* Protected by the IPI lock.
|
||||||
*
|
*
|
||||||
* If c_numshootdown is -1 (TLBSHOOTDOWN_ALL), all mappings
|
* TLB shootdown requests made to this CPU are queued in
|
||||||
* should be invalidated. This is used if more than
|
* c_shootdown[], with c_numshootdown holding the number of
|
||||||
* TLBSHOOTDOWN_MAX mappings are going to be invalidated at
|
* requests. TLBSHOOTDOWN_MAX is the maximum number that can
|
||||||
* once. TLBSHOOTDOWN_MAX is MD and chosen based on when it
|
* be queued at once, which is machine-dependent.
|
||||||
* becomes more efficient just to flush the whole TLB.
|
|
||||||
*
|
*
|
||||||
* struct tlbshootdown is machine-dependent and might
|
* The contents of struct tlbshootdown are also machine-
|
||||||
* reasonably be either an address space and vaddr pair, or a
|
* dependent and might reasonably be either an address space
|
||||||
* paddr, or something else.
|
* and vaddr pair, or a paddr, or something else.
|
||||||
*/
|
*/
|
||||||
uint32_t c_ipi_pending; /* One bit for each IPI number */
|
uint32_t c_ipi_pending; /* One bit for each IPI number */
|
||||||
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
|
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
|
||||||
int c_numshootdown;
|
unsigned c_numshootdown;
|
||||||
struct spinlock c_ipi_lock;
|
struct spinlock c_ipi_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TLBSHOOTDOWN_ALL (-1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialization functions.
|
* Initialization functions.
|
||||||
*
|
*
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
* Leave this alone, so we can tell what version of the OS/161 base
|
* Leave this alone, so we can tell what version of the OS/161 base
|
||||||
* code we gave you.
|
* code we gave you.
|
||||||
*/
|
*/
|
||||||
#define BASE_VERSION "2.0.1"
|
#define BASE_VERSION "2.0.2"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change this as you see fit in the course of hacking the system.
|
* Change this as you see fit in the course of hacking the system.
|
||||||
|
@ -156,6 +156,13 @@ int vfs_getcwd(struct uio *buf);
|
|||||||
* vfs_unmount - Unmount the filesystem presently mounted on the
|
* vfs_unmount - Unmount the filesystem presently mounted on the
|
||||||
* specified device.
|
* specified device.
|
||||||
*
|
*
|
||||||
|
* vfs_swapon - Look up DEVNAME and mark it as a swap device,
|
||||||
|
* returning a vnode. Similar to vfs_mount.
|
||||||
|
*
|
||||||
|
* vfs_swapoff - Unmark DEVNAME as a swap device. The vnode
|
||||||
|
* previously returned by vfs_swapon should be
|
||||||
|
* decref'd first. Similar to vfs_unmount.
|
||||||
|
*
|
||||||
* vfs_unmountall - Unmount all mounted filesystems.
|
* vfs_unmountall - Unmount all mounted filesystems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -172,6 +179,8 @@ int vfs_mount(const char *devname, void *data,
|
|||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct fs **result));
|
struct fs **result));
|
||||||
int vfs_unmount(const char *devname);
|
int vfs_unmount(const char *devname);
|
||||||
|
int vfs_swapon(const char *devname, struct vnode **result);
|
||||||
|
int vfs_swapoff(const char *devname);
|
||||||
int vfs_unmountall(void);
|
int vfs_unmountall(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -63,7 +63,6 @@ void free_kpages(vaddr_t addr);
|
|||||||
unsigned int coremap_used_bytes(void);
|
unsigned int coremap_used_bytes(void);
|
||||||
|
|
||||||
/* TLB shootdown handling called from interprocessor_interrupt */
|
/* TLB shootdown handling called from interprocessor_interrupt */
|
||||||
void vm_tlbshootdown_all(void);
|
|
||||||
void vm_tlbshootdown(const struct tlbshootdown *);
|
void vm_tlbshootdown(const struct tlbshootdown *);
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ thread_make_runnable(struct thread *target, bool already_have_lock)
|
|||||||
target->t_state = S_READY;
|
target->t_state = S_READY;
|
||||||
threadlist_addtail(&targetcpu->c_runqueue, target);
|
threadlist_addtail(&targetcpu->c_runqueue, target);
|
||||||
|
|
||||||
if (targetcpu->c_isidle) {
|
if (targetcpu->c_isidle && targetcpu != curcpu->c_self) {
|
||||||
/*
|
/*
|
||||||
* Other processor is idle; send interrupt to make
|
* Other processor is idle; send interrupt to make
|
||||||
* sure it unidles.
|
* sure it unidles.
|
||||||
@ -1139,6 +1139,9 @@ ipi_send(struct cpu *target, int code)
|
|||||||
spinlock_release(&target->c_ipi_lock);
|
spinlock_release(&target->c_ipi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send an IPI to all CPUs.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
ipi_broadcast(int code)
|
ipi_broadcast(int code)
|
||||||
{
|
{
|
||||||
@ -1153,16 +1156,28 @@ ipi_broadcast(int code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a TLB shootdown IPI to the specified CPU.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
||||||
{
|
{
|
||||||
int n;
|
unsigned n;
|
||||||
|
|
||||||
spinlock_acquire(&target->c_ipi_lock);
|
spinlock_acquire(&target->c_ipi_lock);
|
||||||
|
|
||||||
n = target->c_numshootdown;
|
n = target->c_numshootdown;
|
||||||
if (n == TLBSHOOTDOWN_MAX) {
|
if (n == TLBSHOOTDOWN_MAX) {
|
||||||
target->c_numshootdown = TLBSHOOTDOWN_ALL;
|
/*
|
||||||
|
* If you have problems with this panic going off,
|
||||||
|
* consider: (1) increasing the maximum, (2) putting
|
||||||
|
* logic here to sleep until space appears (may
|
||||||
|
* interact awkwardly with VM system locking), (3)
|
||||||
|
* putting logic here to coalesce requests together,
|
||||||
|
* and/or (4) improving VM system state tracking to
|
||||||
|
* reduce the number of unnecessary shootdowns.
|
||||||
|
*/
|
||||||
|
panic("ipi_tlbshootdown: Too many shootdowns queued\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
target->c_shootdown[n] = *mapping;
|
target->c_shootdown[n] = *mapping;
|
||||||
@ -1175,11 +1190,14 @@ ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
|||||||
spinlock_release(&target->c_ipi_lock);
|
spinlock_release(&target->c_ipi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle an incoming interprocessor interrupt.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
interprocessor_interrupt(void)
|
interprocessor_interrupt(void)
|
||||||
{
|
{
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
int i;
|
unsigned i;
|
||||||
|
|
||||||
spinlock_acquire(&curcpu->c_ipi_lock);
|
spinlock_acquire(&curcpu->c_ipi_lock);
|
||||||
bits = curcpu->c_ipi_pending;
|
bits = curcpu->c_ipi_pending;
|
||||||
@ -1207,14 +1225,14 @@ interprocessor_interrupt(void)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (bits & (1U << IPI_TLBSHOOTDOWN)) {
|
if (bits & (1U << IPI_TLBSHOOTDOWN)) {
|
||||||
if (curcpu->c_numshootdown == TLBSHOOTDOWN_ALL) {
|
/*
|
||||||
vm_tlbshootdown_all();
|
* Note: depending on your VM system locking you might
|
||||||
}
|
* need to release the ipi lock while calling
|
||||||
else {
|
* vm_tlbshootdown.
|
||||||
|
*/
|
||||||
for (i=0; i<curcpu->c_numshootdown; i++) {
|
for (i=0; i<curcpu->c_numshootdown; i++) {
|
||||||
vm_tlbshootdown(&curcpu->c_shootdown[i]);
|
vm_tlbshootdown(&curcpu->c_shootdown[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
curcpu->c_numshootdown = 0;
|
curcpu->c_numshootdown = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,9 @@ struct knowndev {
|
|||||||
struct fs *kd_fs;
|
struct fs *kd_fs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A placeholder for kd_fs for devices used as swap */
|
||||||
|
#define SWAP_FS ((struct fs *)-1)
|
||||||
|
|
||||||
DECLARRAY(knowndev, static __UNUSED inline);
|
DECLARRAY(knowndev, static __UNUSED inline);
|
||||||
DEFARRAY(knowndev, static __UNUSED inline);
|
DEFARRAY(knowndev, static __UNUSED inline);
|
||||||
|
|
||||||
@ -160,7 +163,7 @@ vfs_sync(void)
|
|||||||
num = knowndevarray_num(knowndevs);
|
num = knowndevarray_num(knowndevs);
|
||||||
for (i=0; i<num; i++) {
|
for (i=0; i<num; i++) {
|
||||||
dev = knowndevarray_get(knowndevs, i);
|
dev = knowndevarray_get(knowndevs, i);
|
||||||
if (dev->kd_fs != NULL) {
|
if (dev->kd_fs != NULL && dev->kd_fs != SWAP_FS) {
|
||||||
/*result =*/ FSOP_SYNC(dev->kd_fs);
|
/*result =*/ FSOP_SYNC(dev->kd_fs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,7 +198,7 @@ vfs_getroot(const char *devname, struct vnode **ret)
|
|||||||
* and DEVNAME names the device, return ENXIO.
|
* and DEVNAME names the device, return ENXIO.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (kd->kd_fs!=NULL) {
|
if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
|
||||||
const char *volname;
|
const char *volname;
|
||||||
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
||||||
|
|
||||||
@ -344,7 +347,7 @@ badnames(const char *n1, const char *n2, const char *n3)
|
|||||||
for (i=0; i<num; i++) {
|
for (i=0; i<num; i++) {
|
||||||
kd = knowndevarray_get(knowndevs, i);
|
kd = knowndevarray_get(knowndevs, i);
|
||||||
|
|
||||||
if (kd->kd_fs) {
|
if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
|
||||||
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
||||||
if (samestring3(volname, n1, n2, n3)) {
|
if (samestring3(volname, n1, n2, n3)) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -542,6 +545,7 @@ vfs_mount(const char *devname, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
KASSERT(fs != NULL);
|
KASSERT(fs != NULL);
|
||||||
|
KASSERT(fs != SWAP_FS);
|
||||||
|
|
||||||
kd->kd_fs = fs;
|
kd->kd_fs = fs;
|
||||||
|
|
||||||
@ -553,6 +557,59 @@ vfs_mount(const char *devname, void *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like mount, but for attaching swap. Hands back the raw device
|
||||||
|
* vnode. Unlike mount tolerates a trailing colon on the device name,
|
||||||
|
* to avoid student-facing confusion.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vfs_swapon(const char *devname, struct vnode **ret)
|
||||||
|
{
|
||||||
|
char *myname = NULL;
|
||||||
|
size_t len;
|
||||||
|
struct knowndev *kd;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
len = strlen(devname);
|
||||||
|
if (len > 0 && devname[len - 1] == ':') {
|
||||||
|
/* tolerate trailing :, e.g. lhd0: rather than lhd0 */
|
||||||
|
myname = kstrdup(devname);
|
||||||
|
if (myname == NULL) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
myname[len - 1] = 0;
|
||||||
|
devname = myname;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfs_biglock_acquire();
|
||||||
|
|
||||||
|
result = findmount(devname, &kd);
|
||||||
|
if (result) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kd->kd_fs != NULL) {
|
||||||
|
result = EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
KASSERT(kd->kd_rawname != NULL);
|
||||||
|
KASSERT(kd->kd_device != NULL);
|
||||||
|
|
||||||
|
kprintf("vfs: Swap attached to %s\n", kd->kd_name);
|
||||||
|
|
||||||
|
kd->kd_fs = SWAP_FS;
|
||||||
|
VOP_INCREF(kd->kd_vnode);
|
||||||
|
*ret = kd->kd_vnode;
|
||||||
|
|
||||||
|
out:
|
||||||
|
vfs_biglock_release();
|
||||||
|
if (myname != NULL) {
|
||||||
|
kfree(myname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unmount a filesystem/device by name.
|
* Unmount a filesystem/device by name.
|
||||||
* First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
|
* First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
|
||||||
@ -570,7 +627,7 @@ vfs_unmount(const char *devname)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kd->kd_fs == NULL) {
|
if (kd->kd_fs == NULL || kd->kd_fs == SWAP_FS) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -600,6 +657,43 @@ vfs_unmount(const char *devname)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detach swap. Like unmount.
|
||||||
|
*
|
||||||
|
* (Provided for completeness; there is no real need to remove swap
|
||||||
|
* explicitly prior to shutting down, except perhaps when swapping to
|
||||||
|
* things that themselves want a clean shutdown, like RAIDs.)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vfs_swapoff(const char *devname)
|
||||||
|
{
|
||||||
|
struct knowndev *kd;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
vfs_biglock_acquire();
|
||||||
|
|
||||||
|
result = findmount(devname, &kd);
|
||||||
|
if (result) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kd->kd_fs != SWAP_FS) {
|
||||||
|
result = EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("vfs: Swap detached from %s:\n", kd->kd_name);
|
||||||
|
|
||||||
|
/* drop it */
|
||||||
|
kd->kd_fs = NULL;
|
||||||
|
|
||||||
|
KASSERT(result==0);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
vfs_biglock_release();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global unmount function.
|
* Global unmount function.
|
||||||
*/
|
*/
|
||||||
@ -623,6 +717,11 @@ vfs_unmountall(void)
|
|||||||
/* not mounted */
|
/* not mounted */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (dev->kd_fs == SWAP_FS) {
|
||||||
|
/* just drop it */
|
||||||
|
dev->kd_fs = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
kprintf("vfs: Unmounting %s:\n", dev->kd_name);
|
kprintf("vfs: Unmounting %s:\n", dev->kd_name);
|
||||||
|
|
||||||
|
@ -129,7 +129,8 @@ vnode_decref(struct vnode *vn)
|
|||||||
void
|
void
|
||||||
vnode_check(struct vnode *v, const char *opstr)
|
vnode_check(struct vnode *v, const char *opstr)
|
||||||
{
|
{
|
||||||
vfs_biglock_acquire();
|
/* not safe, and not really needed to check constant fields */
|
||||||
|
/*vfs_biglock_acquire();*/
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
panic("vnode_check: vop_%s: null vnode\n", opstr);
|
panic("vnode_check: vop_%s: null vnode\n", opstr);
|
||||||
@ -173,5 +174,5 @@ vnode_check(struct vnode *v, const char *opstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&v->vn_countlock);
|
spinlock_release(&v->vn_countlock);
|
||||||
vfs_biglock_release();
|
/*vfs_biglock_release();*/
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
# the build. Default is $(WORKDIR)/tooldir.
|
# the build. Default is $(WORKDIR)/tooldir.
|
||||||
#
|
#
|
||||||
# INSTALLTOP Staging directory for installation.
|
# INSTALLTOP Staging directory for installation.
|
||||||
# Default is $(WORKDIR)/install
|
# Default is $(WORKDIR)/install.
|
||||||
#
|
#
|
||||||
# Probably the only reason to change these would be if you're short on
|
# Probably the only reason to change these would be if you're short on
|
||||||
# diskspace in $(WORKDIR).
|
# diskspace in $(WORKDIR).
|
||||||
|
@ -55,10 +55,13 @@ installmanpages:
|
|||||||
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
|
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
|
# clean: remove build products (nothing to do)
|
||||||
|
clean-local: ;
|
||||||
|
|
||||||
# Mark targets that don't represent files PHONY, to prevent various
|
# Mark targets that don't represent files PHONY, to prevent various
|
||||||
# lossage if files by those names appear.
|
# lossage if files by those names appear.
|
||||||
.PHONY: all all-local install-staging-local install-local installmanpages
|
.PHONY: all all-local install-staging-local install-local installmanpages
|
||||||
|
.PHONY: clean-local
|
||||||
|
|
||||||
# Finally, get the shared definitions for the most basic rules.
|
# Finally, get the shared definitions for the most basic rules.
|
||||||
.include "$(TOP)/mk/os161.baserules.mk"
|
.include "$(TOP)/mk/os161.baserules.mk"
|
||||||
|
@ -174,8 +174,11 @@ spawn(int njobs)
|
|||||||
for (i=0; i<njobs; i++) {
|
for (i=0; i<njobs; i++) {
|
||||||
pids[i] = fork();
|
pids[i] = fork();
|
||||||
if (pids[i] == -1) {
|
if (pids[i] == -1) {
|
||||||
/* abandon the other procs; no way to kill them */
|
/* continue with the procs we have; cannot kill them */
|
||||||
err(1, "fork");
|
warn("fork");
|
||||||
|
warnx("*** Only started %u processes ***", i);
|
||||||
|
njobs = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (pids[i] == 0) {
|
if (pids[i] == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user