watch.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright 2021 The Libc Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package libc // import "modernc.org/libc"
  5. import (
  6. "fmt"
  7. "math"
  8. "os"
  9. "sync"
  10. "unsafe"
  11. )
  12. var (
  13. watches = map[uintptr]watch{}
  14. watchesMu sync.Mutex
  15. )
  16. type watch interface {
  17. msg() string
  18. }
  19. type watcher string
  20. func (w watcher) msg() string {
  21. if w == "" {
  22. return ""
  23. }
  24. return fmt.Sprintf(": %s", w)
  25. }
  26. type watchInt8 struct {
  27. val int8
  28. watcher
  29. }
  30. func WatchInt8(p uintptr, msg string) {
  31. watchesMu.Lock()
  32. watches[p] = &watchInt8{*(*int8)(unsafe.Pointer(p)), watcher(msg)}
  33. watchesMu.Unlock()
  34. }
  35. type watchUint8 struct {
  36. val uint8
  37. watcher
  38. }
  39. func WatchUint8(p uintptr, msg string) {
  40. watchesMu.Lock()
  41. watches[p] = &watchUint8{*(*uint8)(unsafe.Pointer(p)), watcher(msg)}
  42. watchesMu.Unlock()
  43. }
  44. type watchInt16 struct {
  45. val int16
  46. watcher
  47. }
  48. func WatchInt16(p uintptr, msg string) {
  49. watchesMu.Lock()
  50. watches[p] = &watchInt16{*(*int16)(unsafe.Pointer(p)), watcher(msg)}
  51. watchesMu.Unlock()
  52. }
  53. type watchUint16 struct {
  54. val uint16
  55. watcher
  56. }
  57. func WatchUint16(p uintptr, msg string) {
  58. watchesMu.Lock()
  59. watches[p] = &watchUint16{*(*uint16)(unsafe.Pointer(p)), watcher(msg)}
  60. watchesMu.Unlock()
  61. }
  62. type watchInt32 struct {
  63. val int32
  64. watcher
  65. }
  66. func WatchInt32(p uintptr, msg string) {
  67. watchesMu.Lock()
  68. watches[p] = &watchInt32{*(*int32)(unsafe.Pointer(p)), watcher(msg)}
  69. watchesMu.Unlock()
  70. }
  71. type watchUint32 struct {
  72. val uint32
  73. watcher
  74. }
  75. func WatchUint32(p uintptr, msg string) {
  76. watchesMu.Lock()
  77. watches[p] = &watchUint32{*(*uint32)(unsafe.Pointer(p)), watcher(msg)}
  78. watchesMu.Unlock()
  79. }
  80. type watchInt64 struct {
  81. val int64
  82. watcher
  83. }
  84. func WatchInt64(p uintptr, msg string) {
  85. watchesMu.Lock()
  86. watches[p] = &watchInt64{*(*int64)(unsafe.Pointer(p)), watcher(msg)}
  87. watchesMu.Unlock()
  88. }
  89. type watchUint64 struct {
  90. val uint64
  91. watcher
  92. }
  93. func WatchUint64(p uintptr, msg string) {
  94. watchesMu.Lock()
  95. watches[p] = &watchUint64{*(*uint64)(unsafe.Pointer(p)), watcher(msg)}
  96. watchesMu.Unlock()
  97. }
  98. type watchFloat32 struct {
  99. val float32
  100. watcher
  101. }
  102. func WatchFloat32(p uintptr, msg string) {
  103. watchesMu.Lock()
  104. watches[p] = &watchFloat32{*(*float32)(unsafe.Pointer(p)), watcher(msg)}
  105. watchesMu.Unlock()
  106. }
  107. type watchFloat64 struct {
  108. val float64
  109. watcher
  110. }
  111. func WatchFloat64(p uintptr, msg string) {
  112. watchesMu.Lock()
  113. watches[p] = &watchFloat64{*(*float64)(unsafe.Pointer(p)), watcher(msg)}
  114. watchesMu.Unlock()
  115. }
  116. type watchPtr struct {
  117. val uintptr
  118. watcher
  119. }
  120. func WatchPtr(p uintptr, msg string) {
  121. watchesMu.Lock()
  122. watches[p] = &watchPtr{*(*uintptr)(unsafe.Pointer(p)), watcher(msg)}
  123. watchesMu.Unlock()
  124. }
  125. func Watch() {
  126. watchesMu.Lock()
  127. flush := false
  128. for p, v := range watches {
  129. switch x := v.(type) {
  130. case *watchInt8:
  131. if val := *(*int8)(unsafe.Pointer(p)); val != x.val {
  132. flush = true
  133. fmt.Fprintf(os.Stderr, "%v: int8@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  134. x.val = val
  135. }
  136. case *watchUint8:
  137. if val := *(*uint8)(unsafe.Pointer(p)); val != x.val {
  138. flush = true
  139. fmt.Fprintf(os.Stderr, "%v: uint8@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  140. x.val = val
  141. }
  142. case *watchInt16:
  143. if val := *(*int16)(unsafe.Pointer(p)); val != x.val {
  144. flush = true
  145. fmt.Fprintf(os.Stderr, "%v: int16@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  146. x.val = val
  147. }
  148. case *watchUint16:
  149. if val := *(*uint16)(unsafe.Pointer(p)); val != x.val {
  150. flush = true
  151. fmt.Fprintf(os.Stderr, "%v: uint16@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  152. x.val = val
  153. }
  154. case *watchInt32:
  155. if val := *(*int32)(unsafe.Pointer(p)); val != x.val {
  156. flush = true
  157. fmt.Fprintf(os.Stderr, "%v: int32@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  158. x.val = val
  159. }
  160. case *watchUint32:
  161. if val := *(*uint32)(unsafe.Pointer(p)); val != x.val {
  162. flush = true
  163. fmt.Fprintf(os.Stderr, "%v: uint32@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  164. x.val = val
  165. }
  166. case *watchInt64:
  167. if val := *(*int64)(unsafe.Pointer(p)); val != x.val {
  168. flush = true
  169. fmt.Fprintf(os.Stderr, "%v: int64@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  170. x.val = val
  171. }
  172. case *watchUint64:
  173. if val := *(*uint64)(unsafe.Pointer(p)); val != x.val {
  174. flush = true
  175. fmt.Fprintf(os.Stderr, "%v: uint64@%#x was %d, new %d%s\n", origin(2), p, x.val, val, x.msg())
  176. x.val = val
  177. }
  178. case *watchFloat32:
  179. if val := *(*float32)(unsafe.Pointer(p)); math.Float32bits(val) != math.Float32bits(x.val) {
  180. flush = true
  181. fmt.Fprintf(os.Stderr, "%v: float32@%#x was %v(%#x), new %v(%#x)%s\n", origin(2), p, x.val, math.Float32bits(x.val), val, math.Float32bits(val), x.msg())
  182. x.val = val
  183. }
  184. case *watchFloat64:
  185. if val := *(*float64)(unsafe.Pointer(p)); math.Float64bits(val) != math.Float64bits(x.val) {
  186. flush = true
  187. fmt.Fprintf(os.Stderr, "%v: float64@%#x was %v(%#x), new %v(%#x)%s\n", origin(2), p, x.val, math.Float64bits(x.val), val, math.Float64bits(val), x.msg())
  188. x.val = val
  189. }
  190. case *watchPtr:
  191. if val := *(*uintptr)(unsafe.Pointer(p)); val != x.val {
  192. flush = true
  193. fmt.Fprintf(os.Stderr, "%v: ptr@%#x was %#x, new %#x%s\n", origin(2), p, x.val, val, x.msg())
  194. x.val = val
  195. }
  196. default:
  197. panic(todo("%T", x))
  198. }
  199. }
  200. if flush {
  201. os.Stderr.Sync()
  202. }
  203. watchesMu.Unlock()
  204. }
  205. func WatchDelete(p uintptr) {
  206. watchesMu.Lock()
  207. delete(watches, p)
  208. watchesMu.Unlock()
  209. }