Fail loudly on a touch read, stop the workers before their sockets close, and file down the small edges
This commit is contained in:
@@ -170,23 +170,24 @@ func findDisplay(fd int) (connID, crtcID uint32, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The card number is not stable across machines, so the card driving a
|
// The card number is not stable across machines, so the card driving a
|
||||||
// connected display is the one we want.
|
// connected display is the one we want, and the display it found comes back
|
||||||
func openCard() (int, error) {
|
// with it.
|
||||||
|
func openCard() (fd int, connID, crtcID uint32, err error) {
|
||||||
paths, err := filepath.Glob("/dev/dri/card*")
|
paths, err := filepath.Glob("/dev/dri/card*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, 0, 0, err
|
||||||
}
|
}
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
fd, err := unix.Open(p, unix.O_RDWR|unix.O_CLOEXEC, 0)
|
fd, err := unix.Open(p, unix.O_RDWR|unix.O_CLOEXEC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, _, err := findDisplay(fd); err == nil {
|
if connID, crtcID, err := findDisplay(fd); err == nil {
|
||||||
return fd, nil
|
return fd, connID, crtcID, nil
|
||||||
}
|
}
|
||||||
unix.Close(fd)
|
unix.Close(fd)
|
||||||
}
|
}
|
||||||
return -1, fmt.Errorf("no drm device with a connected display")
|
return -1, 0, 0, fmt.Errorf("no drm device with a connected display")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fb *framebuffer) addScanout(i int) error {
|
func (fb *framebuffer) addScanout(i int) error {
|
||||||
@@ -223,7 +224,7 @@ func (fb *framebuffer) addScanout(i int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openFramebuffer() (*framebuffer, error) {
|
func openFramebuffer() (*framebuffer, error) {
|
||||||
fd, err := openCard()
|
fd, connID, crtcID, err := openCard()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -236,11 +237,6 @@ func openFramebuffer() (*framebuffer, error) {
|
|||||||
return nil, fmt.Errorf("take drm master: %w", err)
|
return nil, fmt.Errorf("take drm master: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
connID, crtcID, err := findDisplay(fd)
|
|
||||||
if err != nil {
|
|
||||||
fb.close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
mode, err := preferredMode(fd, connID)
|
mode, err := preferredMode(fd, connID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fb.close()
|
fb.close()
|
||||||
|
|||||||
@@ -119,8 +119,11 @@ func watchTouch(w, h int) (*touchState, error) {
|
|||||||
var down bool
|
var down bool
|
||||||
for {
|
for {
|
||||||
n, err := f.Read(buf)
|
n, err := f.Read(buf)
|
||||||
|
// Nothing else feeds this state, so returning here would freeze the
|
||||||
|
// last touch in place and leave the reset button dead while the panel
|
||||||
|
// goes on looking alive.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
panic(fmt.Sprintf("reading touchscreen events: %v", err))
|
||||||
}
|
}
|
||||||
for o := 0; o+sizeofInputEvent <= n; o += sizeofInputEvent {
|
for o := 0; o+sizeofInputEvent <= n; o += sizeofInputEvent {
|
||||||
typ := *(*uint16)(unsafe.Pointer(&buf[o+16]))
|
typ := *(*uint16)(unsafe.Pointer(&buf[o+16]))
|
||||||
@@ -142,9 +145,11 @@ func watchTouch(w, h int) (*touchState, error) {
|
|||||||
if code != synReport {
|
if code != synReport {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// Scaled onto [0, w-1], so full deflection is the last pixel
|
||||||
|
// rather than one past it.
|
||||||
state.set(
|
state.set(
|
||||||
int(int64(rawX-minX)*int64(w)/int64(maxX-minX)),
|
int(int64(rawX-minX)*int64(w-1)/int64(maxX-minX)),
|
||||||
int(int64(rawY-minY)*int64(h)/int64(maxY-minY)),
|
int(int64(rawY-minY)*int64(h-1)/int64(maxY-minY)),
|
||||||
down)
|
down)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -640,6 +640,20 @@ func run(aName, bName string, nsPerM float64) error {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
samp.run(&done, startTx)
|
samp.run(&done, startTx)
|
||||||
}()
|
}()
|
||||||
|
// Every return from here on stops the workers before the deferred closes
|
||||||
|
// pull their sockets out from under them: otherwise the sampler panics on a
|
||||||
|
// closed fd and can mask the error that actually ended the run. An error
|
||||||
|
// before the gate opens closes it here, or the wait would hang on
|
||||||
|
// goroutines still parked at startTx.
|
||||||
|
defer func() {
|
||||||
|
done.Store(true)
|
||||||
|
select {
|
||||||
|
case <-startTx:
|
||||||
|
default:
|
||||||
|
close(startTx)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}()
|
||||||
rxReady.Wait()
|
rxReady.Wait()
|
||||||
|
|
||||||
sig := make(chan os.Signal, 1)
|
sig := make(chan os.Signal, 1)
|
||||||
@@ -674,8 +688,6 @@ func run(aName, bName string, nsPerM float64) error {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-sig:
|
case <-sig:
|
||||||
done.Store(true)
|
|
||||||
wg.Wait()
|
|
||||||
return nil
|
return nil
|
||||||
case <-space:
|
case <-space:
|
||||||
start = resetAll(dirs, stats)
|
start = resetAll(dirs, stats)
|
||||||
|
|||||||
@@ -170,10 +170,13 @@ func (p *probeSender) awaitTx(scratch, oob []byte) (int64, bool) {
|
|||||||
fds := []unix.PollFd{{Fd: int32(p.fd), Events: unix.POLLERR}}
|
fds := []unix.PollFd{{Fd: int32(p.fd), Events: unix.POLLERR}}
|
||||||
deadline := time.Now().Add(probeTimeout)
|
deadline := time.Now().Add(probeTimeout)
|
||||||
for {
|
for {
|
||||||
ms := int(time.Until(deadline).Milliseconds())
|
left := time.Until(deadline)
|
||||||
if ms <= 0 {
|
if left <= 0 {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
// Rounded up, since truncating would give up with time still on the
|
||||||
|
// clock and shave the last fraction of a millisecond off every wait.
|
||||||
|
ms := int((left + time.Millisecond - 1) / time.Millisecond)
|
||||||
n, err := unix.Poll(fds, ms)
|
n, err := unix.Poll(fds, ms)
|
||||||
if err == unix.EINTR {
|
if err == unix.EINTR {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ func commas(v uint64) string {
|
|||||||
// on the label. Below a thousand no letter is left dangling, since a trailing
|
// on the label. Below a thousand no letter is left dangling, since a trailing
|
||||||
// space would push the figure off centre.
|
// space would push the figure off centre.
|
||||||
func scaleSI(v float64) string {
|
func scaleSI(v float64) string {
|
||||||
|
// %.2f rounds 999.995 and up to a fourth digit, so the magnitude rolls over
|
||||||
|
// where the rounding does rather than at the bare thousand.
|
||||||
for _, mag := range []string{"", "k", "M", "G", "T"} {
|
for _, mag := range []string{"", "k", "M", "G", "T"} {
|
||||||
if v < 1000 {
|
if v < 999.995 {
|
||||||
if mag == "" {
|
if mag == "" {
|
||||||
return fmt.Sprintf("%.2f", v)
|
return fmt.Sprintf("%.2f", v)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user