STRUCT COMEDI_ASYNC(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct comedi_async β€” the Kernel API Manual moment

okay so bestie, we're in the Kernel API Manual today, and the star of the show is struct comedi_async, which is literally the control data for asynchronous COMEDI commands ✨ like that's its whole job, that's the vibe.


✨ NAME ✨

struct comedi_async β€” control data for asynchronous COMEDI commands πŸŽ€


🌸 SYNOPSIS 🌸

struct comedi_async {
    unsigned int prealloc_bufsz;
    struct comedi_buf_map *buf_map;
    unsigned int max_bufsize;
    unsigned int buf_write_count;
    unsigned int buf_write_alloc_count;
    unsigned int buf_read_count;
    unsigned int buf_read_alloc_count;
    unsigned int buf_write_ptr;
    unsigned int buf_read_ptr;
    unsigned int cur_chan;
    unsigned int scans_done;
    unsigned int scan_progress;
    unsigned int munge_chan;
    unsigned int munge_count;
    unsigned int munge_ptr;
    unsigned int events;
    struct comedi_cmd cmd;
    wait_queue_head_t wait_head;
    struct completion run_complete;
    refcount_t run_active;
    unsigned int cb_mask;
    int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x);
};

🫢 Members 🫢

like, every single one, no skips, periodt:

  • prealloc_bufsz β€” the buffer size, in bytes πŸ’–
  • buf_map β€” map of the buffer pages πŸ—ΊοΈ
  • max_bufsize β€” the max buffer size you're allowed, in bytes πŸ™ˆ
  • buf_write_count β€” the "write completed" count (in bytes, modulo 2**32)
  • buf_write_alloc_count β€” the "allocated for writing" count (in bytes, modulo 2**32)
  • buf_read_count β€” the "read completed" count (in bytes, modulo 2**32)
  • buf_read_alloc_count β€” the "allocated for reading" count (in bytes, modulo 2**32)
  • buf_write_ptr β€” buffer position for the writer ✍️
  • buf_read_ptr β€” buffer position for the reader πŸ‘€
  • cur_chan β€” current position in the chanlist for the scan (for those drivers that actually use it, iykyk)
  • scans_done β€” how many scans have been completed πŸ”₯
  • scan_progress β€” amount received or sent for the current scan, in bytes
  • munge_chan β€” current position in the chanlist for the "munging" 🧚
  • munge_count β€” the "munge" count (in bytes, modulo 2**32)
  • munge_ptr β€” buffer position for the "munging" πŸŒ€
  • events β€” bit-vector of the events that have occurred ⭐
  • cmd β€” all the details of the comedi command currently in progress
  • wait_head β€” task wait queue for the file reader or writer 😴
  • run_complete β€” the "run complete" completion event βœ…
  • run_active β€” the "run active" reference counter
  • cb_mask β€” bit-vector of events that should wake the waiting tasks ⏰
  • inttrig β€” software trigger function for the command, or NULL πŸ’€

πŸ’œ Description πŸ’œ

okay so first, a note about the ..._count and ..._ptr members, because this is the part where it gets iconic:

Think of the _Count values as being integers of unlimited size, indexing into a buffer of infinite length (even though only an advancing portion of the buffer of fixed length prealloc_bufsz is accessible at any time). Then:

Buf_Read_Count <= Buf_Read_Alloc_Count <= Munge_Count <= Buf_Write_Count
<= Buf_Write_Alloc_Count <= (Buf_Read_Count + prealloc_bufsz)

(and no, those aren't the actual member names, apart from prealloc_bufsz β€” don't come for me πŸ™ˆ). When the buffer gets reset, those _Count values start at 0 and only ever increase, maintaining the inequalities above until the next time the buffer is reset. The buffer gets divided into these regions by the inequalities:

  • [0, Buf_Read_Count): old region, no longer accessible ❌
  • [Buf_Read_Count, Buf_Read_Alloc_Count): filled and munged region, allocated for reading but not yet read
  • [Buf_Read_Alloc_Count, Munge_Count): filled and munged region, not yet allocated for reading
  • [Munge_Count, Buf_Write_Count): filled region, not yet munged
  • [Buf_Write_Count, Buf_Write_Alloc_Count): unfilled region, allocated for writing but not yet written
  • [Buf_Write_Alloc_Count, Buf_Read_Count + prealloc_bufsz): unfilled region, not yet allocated for writing
  • [Buf_Read_Count + prealloc_bufsz, infinity): unfilled region, not yet accessible 🌌

Data needs to be written into the buffer before it can be read out, and it may need to be converted (or "munged") between those two operations. Extra unfilled buffer space may need to be allocated for writing (advancing Buf_Write_Alloc_Count) before new data is written. After writing new data, the newly filled space needs to be released (advancing Buf_Write_Count). This also results in the new data being "munged" (advancing Munge_Count). Before data is read out of the buffer, extra space may need to be allocated for reading (advancing Buf_Read_Alloc_Count). After the data has been read out, the space needs to be released (advancing Buf_Read_Count) 🫢

The actual members β€” buf_read_count, buf_read_alloc_count, munge_count, buf_write_count, and buf_write_alloc_count β€” take the value of the corresponding capitalized _Count values modulo 2^32 (UINT_MAX+1). Subtracting a "higher" _count value from a "lower" _count value gives the same answer as subtracting a "higher" _Count value from a lower _Count value, because prealloc_bufsz < UINT_MAX+1. The modulo operation is done implicitly, she's just like that πŸ’…

The buf_read_ptr, munge_ptr, and buf_write_ptr members take the value of the corresponding capitalized _Count values modulo prealloc_bufsz. These correspond to byte indices in the physical buffer. The modulo operation is done by subtracting prealloc_bufsz when the value exceeds prealloc_bufsz (assuming prealloc_bufsz plus the increment is less than or equal to UINT_MAX).


πŸ¦‹ SEE ALSO πŸ¦‹

Kernel file ./include/linux/comedi/comedidev.h struct:


and that's the whole page bestie!! πŸŽ€ this lil icon lives at ./include/linux/comedi, it's dated October 2026, and yes it's still called struct comedi_async(9) β€” go read it, slay, bye πŸ’–βœ¨

πŸ“¦ where this page comes from