qemu_pci_serial device locking/sync
This commit is contained in:
@ -6,6 +6,8 @@
|
||||
#include "sysdefs/dev.h"
|
||||
#include "util/util.h"
|
||||
#include "dev/dev.h"
|
||||
#include "cjob/cjob.h"
|
||||
#include "proc/proc.h"
|
||||
#include "errors.h"
|
||||
#include "hshtb.h"
|
||||
#include "kprintf.h"
|
||||
@ -53,6 +55,11 @@ int32_t qemu_pci_serial_dev_sendb(struct Dev *dev, uint8_t *buffer, size_t len,
|
||||
(void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
_serial_sendb(qpsd->iobase, buffer[0]);
|
||||
|
||||
return E_OK;
|
||||
@ -62,6 +69,10 @@ int32_t qemu_pci_serial_dev_sendready(struct Dev *dev, uint8_t *buffer, size_t l
|
||||
(void)buffer; (void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
return _serial_sendready(qpsd->iobase);
|
||||
}
|
||||
@ -70,16 +81,75 @@ int32_t qemu_pci_serial_dev_recvb(struct Dev *dev, uint8_t *buffer, size_t len,
|
||||
(void)buffer; (void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
return _serial_recvb(qpsd->iobase);
|
||||
}
|
||||
|
||||
int32_t qemu_pci_serial_dev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
||||
(void)dev; (void)buffer; (void)len; (void)pid;
|
||||
(void)buffer; (void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
return _serial_recvready(qpsd->iobase);
|
||||
}
|
||||
|
||||
int32_t qemu_pci_serial_dev_lock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
||||
(void)buffer; (void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
return _serial_recvready(qpsd->iobase);
|
||||
if (qpsd->lockstate == (int)pid) {
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
if (qpsd->lockstate == -1) {
|
||||
qpsd->lockstate = (int)pid;
|
||||
return E_OK;
|
||||
}
|
||||
return E_DEVLOCKED;
|
||||
}
|
||||
|
||||
int32_t qemu_pci_serial_dev_unlock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
|
||||
(void)buffer; (void)len; (void)pid;
|
||||
|
||||
QemuPciSerialDev *qpsd = dev->extra;
|
||||
|
||||
if (qpsd->lockstate == (int)pid) {
|
||||
qpsd->lockstate = -1;
|
||||
return E_OK;
|
||||
}
|
||||
return E_DEVNOTYOURLOCK;
|
||||
}
|
||||
|
||||
void pci_qemu_pci_serial_gc_cjob(void *arg) {
|
||||
Dev *dev = arg;
|
||||
|
||||
QemuPciSerialDev *qpsd;
|
||||
|
||||
spinlock_acquire(&dev->spinlock);
|
||||
qpsd = dev->extra;
|
||||
uint64_t pid = qpsd->lockstate;
|
||||
spinlock_release(&dev->spinlock);
|
||||
|
||||
Proc *proc = NULL;
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
LL_FINDPROP(PROCS.procs, proc, pid, pid);
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
|
||||
if (proc == NULL) {
|
||||
spinlock_acquire(&dev->spinlock);
|
||||
qpsd = dev->extra;
|
||||
qpsd->lockstate = -1;
|
||||
spinlock_release(&dev->spinlock);
|
||||
}
|
||||
}
|
||||
|
||||
void pci_qemu_pci_serial_init(void) {
|
||||
@ -97,6 +167,7 @@ void pci_qemu_pci_serial_init(void) {
|
||||
|
||||
QEMU_PCI_SERIAL_DEV._magic = QEMU_PCI_SERIAL_MAGIC;
|
||||
QEMU_PCI_SERIAL_DEV.iobase = iobase;
|
||||
QEMU_PCI_SERIAL_DEV.lockstate = -1;
|
||||
|
||||
Dev *serialdev = NULL;
|
||||
HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev);
|
||||
@ -104,8 +175,13 @@ void pci_qemu_pci_serial_init(void) {
|
||||
serialdev->fns[1] = &qemu_pci_serial_dev_sendready;
|
||||
serialdev->fns[2] = &qemu_pci_serial_dev_recvb;
|
||||
serialdev->fns[3] = &qemu_pci_serial_dev_recvready;
|
||||
serialdev->fns[4] = &qemu_pci_serial_dev_lock;
|
||||
serialdev->fns[5] = &qemu_pci_serial_dev_unlock;
|
||||
spinlock_init(&serialdev->spinlock);
|
||||
serialdev->extra = &QEMU_PCI_SERIAL_DEV;
|
||||
|
||||
cjob_register(&pci_qemu_pci_serial_gc_cjob, serialdev);
|
||||
|
||||
_serial_init(QEMU_PCI_SERIAL_DEV.iobase);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user