arch/um/drivers/chan_user.c

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

File Facts

System
Linux kernel
Corpus path
arch/um/drivers/chan_user.c
Extension
.c
Size
7470 bytes
Lines
324
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_data {
	int pty_fd;
	int pipe_fd;
};

static __noreturn int winch_thread(void *arg)
{
	struct winch_data *data = arg;
	sigset_t sigs;
	int pty_fd, pipe_fd;
	int count;
	char c = 1;

	os_set_pdeathsig();

	pty_fd = data->pty_fd;
	pipe_fd = data->pipe_fd;
	count = write(pipe_fd, &c, sizeof(c));
	if (count != sizeof(c))
		os_info("winch_thread : failed to write synchronization byte, err = %d\n",
			-count);

	/*
	 * We are not using SIG_IGN on purpose, so don't fix it as I thought to
	 * do! If using SIG_IGN, the sigsuspend() call below would not stop on
	 * SIGWINCH.
	 */

	signal(SIGWINCH, winch_handler);
	sigfillset(&sigs);
	/* Block all signals possible. */
	if (sigprocmask(SIG_SETMASK, &sigs, NULL) < 0) {
		os_info("winch_thread : sigprocmask failed, errno = %d\n",
			errno);
		goto wait_kill;
	}
	/* In sigsuspend(), block anything else than SIGWINCH. */
	sigdelset(&sigs, SIGWINCH);

	if (setsid() < 0) {
		os_info("winch_thread : setsid failed, errno = %d\n",
		       errno);
		goto wait_kill;
	}

	if (ioctl(pty_fd, TIOCSCTTY, 0) < 0) {
		os_info("winch_thread : TIOCSCTTY failed on "
			"fd %d err = %d\n", pty_fd, errno);
		goto wait_kill;
	}

	if (tcsetpgrp(pty_fd, os_getpid()) < 0) {
		os_info("winch_thread : tcsetpgrp failed on fd %d err = %d\n",
			pty_fd, errno);
		goto wait_kill;
	}

	/*
	 * These are synchronization calls between various UML threads on the
	 * host - since they are not different kernel threads, we cannot use
	 * kernel semaphores. We don't use SysV semaphores because they are
	 * persistent.
	 */
	count = read(pipe_fd, &c, sizeof(c));
	if (count != sizeof(c))
		os_info("winch_thread : failed to read synchronization byte, err = %d\n",
			errno);

	while(1) {
		/*
		 * This will be interrupted by SIGWINCH only, since
		 * other signals are blocked.
		 */
		sigsuspend(&sigs);

		count = write(pipe_fd, &c, sizeof(c));
		if (count != sizeof(c))
			os_info("winch_thread : write failed, err = %d\n",
				errno);
	}

wait_kill:
	c = 2;
	count = write(pipe_fd, &c, sizeof(c));
	while (1)
		pause();
}

static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
		       unsigned long *stack_out)

Annotation

Implementation Notes