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