···11-/* $OpenBSD: sio.c,v 1.29 2026/03/10 06:23:44 ratchov Exp $ */
11+/* $OpenBSD: sio.c,v 1.30 2026/03/10 06:47:41 ratchov Exp $ */
22/*
33 * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
44 *
···500500 cpos, cdiff, wpos, wdiff, rpos, rdiff, hdl->cpending);
501501}
502502#endif
503503+504504+/*
505505+ * Restart the device restoring its state (i.e. hdl->cpos, hdl->wused,
506506+ * hdl->rused), making the restart transparent to upper layers.
507507+ */
508508+int
509509+_sio_xrun(struct sio_hdl *hdl)
510510+{
511511+ int cmove;
512512+513513+#ifdef DEBUG
514514+ if (_sndio_debug >= 1)
515515+ _sio_printpos(hdl);
516516+#endif
517517+ /*
518518+ * The device restarts with empty buffers and block aligned.
519519+ */
520520+ if (!hdl->ops->flush(hdl))
521521+ return 0;
522522+523523+ _sio_onxrun_cb(hdl);
524524+525525+ if (!hdl->ops->start(hdl))
526526+ return 0;
527527+528528+ DPRINTFN(1, "%s: rused = %d, wused = %d\n", __func__,
529529+ hdl->rused, hdl->wused);
530530+531531+ /*
532532+ * To restore the device state, we play silence, drop recorded data,
533533+ * and advance the clock. We suppose that it takes N blocks to restore
534534+ * the state (where N is any integer).
535535+ *
536536+ * After N blocks of operation cpos (the clock) must have advanced to
537537+ * the next block boundary (the stream must remain block-aligned):
538538+ *
539539+ * cpos' = cpos + round - cpos % round
540540+ *
541541+ * on the other hand, cpos advances by N * par->round frames plus
542542+ * hdl->delta (the advance we report immediately):
543543+ *
544544+ * cpos' = cpos + delta + N * round
545545+ *
546546+ * by combining above expressions, we obtain the advance to report:
547547+ *
548548+ * delta = - cpos % round - (N - 1) * round
549549+ *
550550+ * For playback, after N blocks, the buffer usage has decreased by
551551+ * the elapsed time:
552552+ *
553553+ * wused' = wused - (cpos' - cpos)
554554+ *
555555+ * on the other hand it is equal to the amount of silence we have
556556+ * inserted minus the N blocks that the device has consumed:
557557+ *
558558+ * wused' = wsil - N * par->round
559559+ *
560560+ * by combining both expressions, we obtain the amount of silence
561561+ * we've to insert:
562562+ *
563563+ * wsil = wused + (N - 1) * par->round + cpos % round
564564+ *
565565+ * Similarly, for recording the buffer usage has increased by
566566+ * the elapsed time:
567567+ *
568568+ * rused' = rused + (cpos' - cpos)
569569+ *
570570+ * it is also equal to the N blocks the device has produced minus
571571+ * the amount of frames we drop:
572572+ *
573573+ * rused' = N * round - rdrop
574574+ *
575575+ * by combining both expressions, we obtain the amount of frames
576576+ * to drop:
577577+ *
578578+ * rdrop = cpos % round + (N - 1) * round - rused;
579579+ *
580580+ * We're free to choose N. The smaller N (ideally 1) the sooner
581581+ * performance will resume. But wsil and rdrop may not be negative.
582582+ *
583583+ */
584584+585585+ cmove = hdl->cpos % hdl->par.round;
586586+587587+ if (hdl->mode & SIO_REC) {
588588+ while (1) {
589589+ hdl->rdrop = cmove * hdl->par.bps * hdl->par.rchan - hdl->rused;
590590+ if (hdl->rdrop >= 0)
591591+ break;
592592+ /*
593593+ * rdrop can't be negative, try a larger 'N'
594594+ */
595595+ cmove += hdl->par.round;
596596+ }
597597+ }
598598+599599+ if (hdl->mode & SIO_PLAY)
600600+ hdl->wsil = hdl->wused + cmove * hdl->par.bps * hdl->par.pchan;
601601+602602+ DPRINTFN(1, "%s: cmove = %d, wsil = %d, rdrop = %d\n", __func__,
603603+ cmove, hdl->wsil, hdl->rdrop);
604604+605605+ _sio_onmove_cb(hdl, -cmove);
606606+ return 1;
607607+}
503608504609void
505610_sio_onmove_cb(struct sio_hdl *hdl, int delta)
···11-/* $OpenBSD: sio_sun.c,v 1.35 2026/03/10 06:41:10 ratchov Exp $ */
11+/* $OpenBSD: sio_sun.c,v 1.36 2026/03/10 06:47:41 ratchov Exp $ */
22/*
33 * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
44 *
···522522 }
523523524524 return n;
525525-}
526526-527527-/*
528528- * Restart the device restoring its state (i.e. hdl->cpos, hdl->wused,
529529- * hdl->rused), making the restart transparent to upper layers.
530530- */
531531-static int
532532-_sio_xrun(struct sio_hdl *hdl)
533533-{
534534- int cmove;
535535-536536-#ifdef DEBUG
537537- if (_sndio_debug >= 1)
538538- _sio_printpos(hdl);
539539-#endif
540540- /*
541541- * The device restarts with empty buffers and block aligned.
542542- */
543543- if (!hdl->ops->flush(hdl))
544544- return 0;
545545-546546- _sio_onxrun_cb(hdl);
547547-548548- if (!hdl->ops->start(hdl))
549549- return 0;
550550-551551- DPRINTFN(1, "%s: rused = %d, wused = %d\n", __func__,
552552- hdl->rused, hdl->wused);
553553-554554- /*
555555- * To restore the device state, we play silence, drop recorded data,
556556- * and advance the clock. We suppose that it takes N blocks to restore
557557- * the state (where N is any integer).
558558- *
559559- * After N blocks of operation cpos (the clock) must have advanced to
560560- * the next block boundary (the stream must remain block-aligned):
561561- *
562562- * cpos' = cpos + round - cpos % round
563563- *
564564- * on the other hand, cpos advances by N * par->round frames plus
565565- * hdl->delta (the advance we report immediately):
566566- *
567567- * cpos' = cpos + delta + N * round
568568- *
569569- * by combining above expressions, we obtain the advance to report:
570570- *
571571- * delta = - cpos % round - (N - 1) * round
572572- *
573573- * For playback, after N blocks, the buffer usage has decreased by
574574- * the elapsed time:
575575- *
576576- * wused' = wused - (cpos' - cpos)
577577- *
578578- * on the other hand it is equal to the amount of silence we have
579579- * inserted minus the N blocks that the device has consumed:
580580- *
581581- * wused' = wsil - N * par->round
582582- *
583583- * by combining both expressions, we obtain the amount of silence
584584- * we've to insert:
585585- *
586586- * wsil = wused + (N - 1) * par->round + cpos % round
587587- *
588588- * Similarly, for recording the buffer usage has increased by
589589- * the elapsed time:
590590- *
591591- * rused' = rused + (cpos' - cpos)
592592- *
593593- * it is also equal to the N blocks the device has produced minus
594594- * the amount of frames we drop:
595595- *
596596- * rused' = N * round - rdrop
597597- *
598598- * by combining both expressions, we obtain the amount of frames
599599- * to drop:
600600- *
601601- * rdrop = cpos % round + (N - 1) * round - rused;
602602- *
603603- * We're free to choose N. The smaller N (ideally 1) the sooner
604604- * performance will resume. But wsil and rdrop may not be negative.
605605- *
606606- */
607607-608608- cmove = hdl->cpos % hdl->par.round;
609609-610610- if (hdl->mode & SIO_REC) {
611611- while (1) {
612612- hdl->rdrop = cmove * hdl->par.bps * hdl->par.rchan - hdl->rused;
613613- if (hdl->rdrop >= 0)
614614- break;
615615- /*
616616- * rdrop can't be negative, try a larger 'N'
617617- */
618618- cmove += hdl->par.round;
619619- }
620620- }
621621-622622- if (hdl->mode & SIO_PLAY)
623623- hdl->wsil = hdl->wused + cmove * hdl->par.bps * hdl->par.pchan;
624624-625625- DPRINTFN(1, "%s: cmove = %d, wsil = %d, rdrop = %d\n", __func__,
626626- cmove, hdl->wsil, hdl->rdrop);
627627-628628- _sio_onmove_cb(hdl, -cmove);
629629- return 1;
630525}
631526632527static int