sync: use `mfence` on windows-tcc (#6079)
parent
ea76a33b43
commit
d63daa0798
|
@ -123,7 +123,7 @@ __CRT_INLINE SHORT _InterlockedExchangeAdd16(SHORT volatile *Addend, SHORT Value
|
||||||
#define InterlockedIncrement64 _InterlockedExchangeAdd64
|
#define InterlockedIncrement64 _InterlockedExchangeAdd64
|
||||||
|
|
||||||
__CRT_INLINE VOID __faststorefence() {
|
__CRT_INLINE VOID __faststorefence() {
|
||||||
__asm__ __volatile__ ("sfence");
|
__asm__ __volatile__ ("mfence");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,7 +40,7 @@ fn test_select() {
|
||||||
go do_send_byte(mut chb)
|
go do_send_byte(mut chb)
|
||||||
go do_send_i64(mut chl)
|
go do_send_i64(mut chl)
|
||||||
mut channels := [chi, recch, chl, chb]
|
mut channels := [chi, recch, chl, chb]
|
||||||
directions := [false, true, false, false]
|
directions := [sync.Direction.pop, .push, .pop, .pop]
|
||||||
mut sum := i64(0)
|
mut sum := i64(0)
|
||||||
mut rl := i64(0)
|
mut rl := i64(0)
|
||||||
mut ri := int(0)
|
mut ri := int(0)
|
|
@ -71,6 +71,11 @@ mut:
|
||||||
nxt &Subscription
|
nxt &Subscription
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
pop
|
||||||
|
push
|
||||||
|
}
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
writesem Semaphore // to wake thread that wanted to write, but buffer was full
|
writesem Semaphore // to wake thread that wanted to write, but buffer was full
|
||||||
readsem Semaphore // to wake thread that wanted to read, but buffer was empty
|
readsem Semaphore // to wake thread that wanted to read, but buffer was empty
|
||||||
|
@ -97,17 +102,18 @@ mut: // atomic
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_channel<T>(n u32) &Channel {
|
pub fn new_channel<T>(n u32) &Channel {
|
||||||
|
st := sizeof(T)
|
||||||
return &Channel{
|
return &Channel{
|
||||||
writesem: new_semaphore_init(if n > 0 { n + 1 } else { 1 })
|
writesem: new_semaphore_init(if n > 0 { n + 1 } else { 1 })
|
||||||
readsem: new_semaphore_init(if n > 0 { u32(0) } else { 1 })
|
readsem: new_semaphore_init(if n > 0 { u32(0) } else { 1 })
|
||||||
writesem_im: new_semaphore()
|
writesem_im: new_semaphore()
|
||||||
readsem_im: new_semaphore()
|
readsem_im: new_semaphore()
|
||||||
objsize: sizeof(T)
|
objsize: st
|
||||||
queue_length: n
|
queue_length: n
|
||||||
write_free: n
|
write_free: n
|
||||||
read_avail: 0
|
read_avail: 0
|
||||||
ringbuf: if n > 0 { malloc(int(n * sizeof(T))) } else { byteptr(0) }
|
ringbuf: if n > 0 { malloc(int(n * st)) } else { byteptr(0) }
|
||||||
statusbuf: if n > 0 { vcalloc(int(n * sizeof(u16))) } else { byteptr(0) }
|
statusbuf: if n > 0 { vcalloc(int(n * 2)) } else { byteptr(0) }
|
||||||
write_subscriber: 0
|
write_subscriber: 0
|
||||||
read_subscriber: 0
|
read_subscriber: 0
|
||||||
}
|
}
|
||||||
|
@ -412,13 +418,13 @@ fn (mut ch Channel) try_pop(dest voidptr, no_block bool) bool {
|
||||||
// Wait `timeout` on any of `channels[i]` until one of them can push (`is_push[i] = true`) or pop (`is_push[i] = false`)
|
// Wait `timeout` on any of `channels[i]` until one of them can push (`is_push[i] = true`) or pop (`is_push[i] = false`)
|
||||||
// object referenced by `objrefs[i]`. `timeout = 0` means wait unlimited time
|
// object referenced by `objrefs[i]`. `timeout = 0` means wait unlimited time
|
||||||
|
|
||||||
pub fn channel_select(mut channels []&Channel, is_push []bool, mut objrefs []voidptr, timeout time.Duration) int {
|
pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []voidptr, timeout time.Duration) int {
|
||||||
assert channels.len == is_push.len
|
assert channels.len == dir.len
|
||||||
assert is_push.len == objrefs.len
|
assert dir.len == objrefs.len
|
||||||
mut subscr := []Subscription{len: channels.len}
|
mut subscr := []Subscription{len: channels.len}
|
||||||
sem := new_semaphore()
|
sem := new_semaphore()
|
||||||
for i, ch in channels {
|
for i, ch in channels {
|
||||||
if is_push[i] {
|
if dir[i] == .push {
|
||||||
mut null16 := u16(0)
|
mut null16 := u16(0)
|
||||||
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
||||||
null16 = u16(0)
|
null16 = u16(0)
|
||||||
|
@ -453,7 +459,7 @@ pub fn channel_select(mut channels []&Channel, is_push []bool, mut objrefs []voi
|
||||||
if i >= channels.len {
|
if i >= channels.len {
|
||||||
i -= channels.len
|
i -= channels.len
|
||||||
}
|
}
|
||||||
if is_push[i] {
|
if dir[i] == .push {
|
||||||
if channels[i].try_push(objrefs[i], true) {
|
if channels[i].try_push(objrefs[i], true) {
|
||||||
event_idx = i
|
event_idx = i
|
||||||
goto restore
|
goto restore
|
||||||
|
@ -477,7 +483,7 @@ pub fn channel_select(mut channels []&Channel, is_push []bool, mut objrefs []voi
|
||||||
restore:
|
restore:
|
||||||
// reset subscribers
|
// reset subscribers
|
||||||
for i, ch in channels {
|
for i, ch in channels {
|
||||||
if is_push[i] {
|
if dir[i] == .push {
|
||||||
mut null16 := u16(0)
|
mut null16 := u16(0)
|
||||||
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
||||||
null16 = u16(0)
|
null16 = u16(0)
|
||||||
|
|
Loading…
Reference in New Issue