I searched hard (both on the S [O | F | U] network and elsewhere) and I think this is an unusual question. I work with the Atmel AT91SAM9263-EK development board (ARM926EJ-S kernel, ARMv5 instruction set) running Debian Linux 2.6.28-4. I am writing using (I believe) the tty driver to talk to the RS-485 serial controller . I need records and readings to be atomic. Several lines of source code (listed below the end of this message regarding the installation directory of the kernel source code) imply or implicitly define this.
Is there any way to verify that writing / reading to / from this device is actually an atomic operation? Or, is the device / dev / ttyXX considered FIFO, and the argument ends there? It seems that it is not enough just to trust that the code fulfills this claim, which it makes - as far back as February of this year, freebsd demonstrated the absence of atomic records for small lines . Yes, I understand that freebsd is not exactly the same as Linux, but I want to say that it does not hurt to be careful. All I can think of is to continue sending data and looking for a permutation - I was hoping for something more scientific and, ideally, deterministic. Unfortunately, I donβt remember anything exactly from my parallel programming classes in college days. I would appreciate a slap in the face or a push in the right direction. Thank you in advance if you decide to answer.
Yours faithfully,
Jayce
driver / char / tty_io.c: 1087
void tty_write_message(struct tty_struct *tty, char *msg) { lock_kernel(); if (tty) { mutex_lock(&tty->atomic_write_lock); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) tty->ops->write(tty, msg, strlen(msg)); tty_write_unlock(tty); } unlock_kernel(); return; }
arc / arm / enable / ASM / bitops.h: 37
static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1UL << (bit & 31); p += bit >> 5; raw_local_irq_save(flags); *p |= mask; raw_local_irq_restore(flags); }
Drivers / serial / serial_core.c: 2376
static int uart_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct uart_state *state = tty->driver_data; struct uart_port *port; struct circ_buf *circ; unsigned long flags; int c, ret = 0; if (!state || !state->info) { WARN_ON(1); return -EL3HLT; } port = state->port; circ = &state->info->xmit; if (!circ->buf) return 0; spin_lock_irqsave(&port->lock, flags); while (1) { c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(circ->buf + circ->head, buf, c); circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); buf += c; count -= c; ret += c; } spin_unlock_irqrestore(&port->lock, flags); uart_start(tty); return ret; }
In addition, write (3) documentation from a person:
An attempt to write to a pipe or FIFO has several key characteristics:
- Atomic / non-atomic: A record is atomic if the entire amount recorded in one operation does not alternate with data from any other process. This is useful when multiple authors send data to a single reader. Applications should know how large a write request can be expected atomically. This maximum is called {PIPE_BUF}. This volume of IEEE Std 1003.1-2001 does not indicate whether write requests for more than {PIPE_BUF} bytes are atomic, but requires that records from {PIPE_BUF} or fewer bytes are atomic.