for spinlocks, use gcc intrinsics, but say what they compile to

This commit is contained in:
Robert Morris 2019-06-13 10:00:50 -04:00
parent ca39672a30
commit 46744c4a13
2 changed files with 21 additions and 21 deletions

View file

@ -27,9 +27,10 @@ acquire(struct spinlock *lk)
if(holding(lk)) if(holding(lk))
panic("acquire"); panic("acquire");
// The xchg is atomic. // On RISC-V, this turns into an atomic swap:
//while(xchg(&lk->locked, 1) != 0) // a5 = 1
// ; // s1 = &lk->locked
// amoswap.w.aq a5, a5, (s1)
while(__sync_lock_test_and_set(&lk->locked, 1) != 0) while(__sync_lock_test_and_set(&lk->locked, 1) != 0)
; ;
@ -51,19 +52,18 @@ release(struct spinlock *lk)
lk->cpu = 0; lk->cpu = 0;
// Tell the C compiler and the processor to not move loads or stores // Tell the C compiler and the CPU to not move loads or stores
// past this point, to ensure that all the stores in the critical // past this point, to ensure that all the stores in the critical
// section are visible to other cores before the lock is released. // section are visible to other cores before the lock is released.
// Both the C compiler and the hardware may re-order loads and
// stores; __sync_synchronize() tells them both not to.
// On RISC-V, this turns into a fence instruction. // On RISC-V, this turns into a fence instruction.
__sync_synchronize(); __sync_synchronize();
// Release the lock, equivalent to lk->locked = 0. // Release the lock, equivalent to lk->locked = 0.
// This code can't use a C assignment, since it might // This code can't use a C assignment, since it might
// not be atomic. A real OS would use C atomics here. // not be atomic.
// On RISC-V, use an amoswap instruction. // On RISC-V, this turns into an atomic swap:
//asm volatile("movl $0, %0" : "+m" (lk->locked) : ); // s1 = &lk->locked
// amoswap.w zero, zero, (s1)
__sync_lock_release(&lk->locked); __sync_lock_release(&lk->locked);
pop_off(); pop_off();

View file

@ -35,13 +35,13 @@
#define VIRTIO_CONFIG_S_FEATURES_OK 8 #define VIRTIO_CONFIG_S_FEATURES_OK 8
// device feature bits // device feature bits
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ #define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ #define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */ #define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ #define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
#define VIRTIO_F_ANY_LAYOUT 27 #define VIRTIO_F_ANY_LAYOUT 27
#define VIRTIO_RING_F_INDIRECT_DESC 28 #define VIRTIO_RING_F_INDIRECT_DESC 28
#define VIRTIO_RING_F_EVENT_IDX 29 #define VIRTIO_RING_F_EVENT_IDX 29
struct VRingDesc { struct VRingDesc {
uint64 addr; uint64 addr;
@ -49,14 +49,14 @@ struct VRingDesc {
uint16 flags; uint16 flags;
uint16 next; uint16 next;
}; };
#define VRING_DESC_F_NEXT 1 #define VRING_DESC_F_NEXT 1 // chained with another descriptor
#define VRING_DESC_F_WRITE 2 // device writes (vs read) #define VRING_DESC_F_WRITE 2 // device writes (vs read)
struct VRingUsedElem { struct VRingUsedElem {
uint32 id; // index of start of completed descriptor chain uint32 id; // index of start of completed descriptor chain
uint32 len; uint32 len;
}; };
// for disk ops // for disk ops
#define VIRTIO_BLK_T_IN 0 #define VIRTIO_BLK_T_IN 0 // read the disk
#define VIRTIO_BLK_T_OUT 1 #define VIRTIO_BLK_T_OUT 1 // write the disk