arch/um/drivers/line.c

Source file repositories/reference/linux-study-clean/arch/um/drivers/line.c

File Facts

System
Linux kernel
Corpus path
arch/um/drivers/line.c
Extension
.c
Size
16610 bytes
Lines
772
Domain
Architecture Layer
Bucket
arch/um
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct winch {
	struct list_head list;
	int fd;
	int tty_fd;
	int pid;
	struct tty_port *port;
	unsigned long stack;
	struct work_struct work;
};

static void __free_winch(struct work_struct *work)
{
	struct winch *winch = container_of(work, struct winch, work);
	um_free_irq(WINCH_IRQ, winch);

	if (winch->pid != -1)
		os_kill_process(winch->pid, 1);
	if (winch->stack != 0)
		free_stack(winch->stack, 0);
	kfree(winch);
}

static void free_winch(struct winch *winch)
{
	int fd = winch->fd;
	winch->fd = -1;
	if (fd != -1)
		os_close_file(fd);
	__free_winch(&winch->work);
}

static irqreturn_t winch_interrupt(int irq, void *data)
{
	struct winch *winch = data;
	struct tty_struct *tty;
	struct line *line;
	int fd = winch->fd;
	int err;
	char c;
	struct pid *pgrp;

	if (fd != -1) {
		err = generic_read(fd, &c, NULL);
		/* A read of 2 means the winch thread failed and has warned */
		if (err < 0 || (err == 1 && c == 2)) {
			if (err != -EAGAIN) {
				winch->fd = -1;
				list_del(&winch->list);
				os_close_file(fd);
				if (err < 0) {
					printk(KERN_ERR "winch_interrupt : read failed, errno = %d\n",
					       -err);
					printk(KERN_ERR "fd %d is losing SIGWINCH support\n",
					       winch->tty_fd);
				}
				INIT_WORK(&winch->work, __free_winch);
				schedule_work(&winch->work);
				return IRQ_HANDLED;
			}
			goto out;
		}
	}
	tty = tty_port_tty_get(winch->port);
	if (tty != NULL) {
		line = tty->driver_data;
		if (line != NULL) {
			chan_window_size(line, &tty->winsize.ws_row,
					 &tty->winsize.ws_col);
			pgrp = tty_get_pgrp(tty);
			if (pgrp)
				kill_pgrp(pgrp, SIGWINCH, 1);
			put_pid(pgrp);
		}
		tty_kref_put(tty);
	}
 out:
	return IRQ_HANDLED;
}

void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
			unsigned long stack)
{
	struct winch *winch;

	winch = kmalloc_obj(*winch);
	if (winch == NULL) {
		printk(KERN_ERR "register_winch_irq - kmalloc failed\n");
		goto cleanup;
	}

Annotation

Implementation Notes