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
|
||||
|
||||
__CRT_INLINE VOID __faststorefence() {
|
||||
__asm__ __volatile__ ("sfence");
|
||||
__asm__ __volatile__ ("mfence");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,7 +40,7 @@ fn test_select() {
|
|||
go do_send_byte(mut chb)
|
||||
go do_send_i64(mut chl)
|
||||
mut channels := [chi, recch, chl, chb]
|
||||
directions := [false, true, false, false]
|
||||
directions := [sync.Direction.pop, .push, .pop, .pop]
|
||||
mut sum := i64(0)
|
||||
mut rl := i64(0)
|
||||
mut ri := int(0)
|
|
@ -71,6 +71,11 @@ mut:
|
|||
nxt &Subscription
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
pop
|
||||
push
|
||||
}
|
||||
|
||||
struct Channel {
|
||||
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
|
||||
|
@ -97,17 +102,18 @@ mut: // atomic
|
|||
}
|
||||
|
||||
pub fn new_channel<T>(n u32) &Channel {
|
||||
st := sizeof(T)
|
||||
return &Channel{
|
||||
writesem: new_semaphore_init(if n > 0 { n + 1 } else { 1 })
|
||||
readsem: new_semaphore_init(if n > 0 { u32(0) } else { 1 })
|
||||
writesem_im: new_semaphore()
|
||||
readsem_im: new_semaphore()
|
||||
objsize: sizeof(T)
|
||||
objsize: st
|
||||
queue_length: n
|
||||
write_free: n
|
||||
read_avail: 0
|
||||
ringbuf: if n > 0 { malloc(int(n * sizeof(T))) } else { byteptr(0) }
|
||||
statusbuf: if n > 0 { vcalloc(int(n * sizeof(u16))) } else { byteptr(0) }
|
||||
ringbuf: if n > 0 { malloc(int(n * st)) } else { byteptr(0) }
|
||||
statusbuf: if n > 0 { vcalloc(int(n * 2)) } else { byteptr(0) }
|
||||
write_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`)
|
||||
// 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 {
|
||||
assert channels.len == is_push.len
|
||||
assert is_push.len == objrefs.len
|
||||
pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []voidptr, timeout time.Duration) int {
|
||||
assert channels.len == dir.len
|
||||
assert dir.len == objrefs.len
|
||||
mut subscr := []Subscription{len: channels.len}
|
||||
sem := new_semaphore()
|
||||
for i, ch in channels {
|
||||
if is_push[i] {
|
||||
if dir[i] == .push {
|
||||
mut null16 := u16(0)
|
||||
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
||||
null16 = u16(0)
|
||||
|
@ -453,7 +459,7 @@ pub fn channel_select(mut channels []&Channel, is_push []bool, mut objrefs []voi
|
|||
if i >= channels.len {
|
||||
i -= channels.len
|
||||
}
|
||||
if is_push[i] {
|
||||
if dir[i] == .push {
|
||||
if channels[i].try_push(objrefs[i], true) {
|
||||
event_idx = i
|
||||
goto restore
|
||||
|
@ -477,7 +483,7 @@ pub fn channel_select(mut channels []&Channel, is_push []bool, mut objrefs []voi
|
|||
restore:
|
||||
// reset subscribers
|
||||
for i, ch in channels {
|
||||
if is_push[i] {
|
||||
if dir[i] == .push {
|
||||
mut null16 := u16(0)
|
||||
for !C.atomic_compare_exchange_weak_u16(&ch.write_sub_mtx, &null16, u16(1)) {
|
||||
null16 = u16(0)
|
||||
|
|
Loading…
Reference in New Issue