static void _root_update_thread () { error_t err; while (1) { if (hurd_condition_wait (&update_wakeup, &update_lock)) mutex_unlock (&update_lock); rwlock_writer_lock (&update_rwlock); do { ulfs_check(); err = node_init_root (netfs_root_node); } while (err == ENOENT); if (err) { fprintf (stderr, "update thread: got a %s\n", strerror (err)); } ncache_reset (); rwlock_writer_unlock (&update_rwlock); } }
static error_t repeater_select (struct protid *cred, mach_port_t reply, mach_msg_type_name_t replytype, int *type) { if (!cred) return EOPNOTSUPP; if (*type & ~SELECT_READ) return EINVAL; if (*type == 0) return 0; mutex_lock (&global_lock); while (1) { if (mousebuf.size > 0) { *type = SELECT_READ; mutex_unlock (&global_lock); return 0; } ports_interrupt_self_on_port_death (cred, reply); if (hurd_condition_wait (&select_alert, &global_lock)) { *type = 0; mutex_unlock (&global_lock); return EINTR; } } }
/* Assert the DTR if necessary. Must be called with global lock held. */ static void wait_for_dtr (void) { while (!assert_dtr) hurd_condition_wait (&hurdio_assert_dtr_condition, &global_lock); assert_dtr = 0; if (tty_arg == 0) ioport = termctl->underlying; else { /* Open the file in blocking mode, so that the carrier is established as well. */ ioport = file_name_lookup (tty_arg, O_READ|O_WRITE, 0); if (ioport == MACH_PORT_NULL) { report_carrier_error (errno); return; } } error_t err; struct termios state = termstate; /* Assume that we have a full blown terminal initially. */ tioc_caps = ~0; /* Set terminal in raw mode etc. */ err = hurdio_set_bits (&state); if (err) report_carrier_error (err); else { termstate = state; /* Signal that we have a carrier. */ report_carrier_on (); /* Signal that the writer thread should resume its work. */ condition_broadcast (&hurdio_writer_condition); } }
/* Place the mouse event EVNT in the mouse event buffer. */ static void repeat_event (kd_event *evt) { kd_event *ev; mutex_lock (&global_lock); while (mousebuf.size + sizeof (kd_event) > MOUSEBUFSZ) { /* The input buffer is full, wait until there is some space. */ if (hurd_condition_wait (&mousebuf.writecond, &global_lock)) { mutex_unlock (&global_lock); /* Interrupt, silently continue. */ } } ev = (kd_event *) &mousebuf.evtbuffer[MOUSEBUF_POS (mousebuf.pos + mousebuf.size)]; mousebuf.size += sizeof (kd_event); memcpy (ev, evt, sizeof (kd_event)); condition_broadcast (&mousebuf.readcond); mutex_unlock (&global_lock); }
kern_return_t S_proc_wait (struct proc *p, mach_port_t reply_port, mach_msg_type_name_t reply_port_type, pid_t pid, int options, int *status, int *sigcode, struct rusage *ru, pid_t *pid_status) { int cancel; int reap (struct proc *child) { if (child->p_waited || (!child->p_dead && (!child->p_stopped || !(child->p_traced || (options & WUNTRACED))))) return 0; child->p_waited = 1; *status = child->p_status; *sigcode = child->p_sigcode; *ru = child->p_rusage; /* all zeros if !p_dead */ *pid_status = child->p_pid; if (child->p_dead) complete_exit (child); return 1; } if (!p) return EOPNOTSUPP; start_over: /* See if we can satisfy the request with a stopped child; also check for invalid arguments here. */ if (!p->p_ochild) return ECHILD; if (pid > 0) { struct proc *child = pid_find_allow_zombie (pid); if (!child || child->p_parent != p) return ECHILD; if (reap (child)) return 0; } else { struct proc *child; int had_a_match = pid == 0; for (child = p->p_ochild; child; child = child->p_sib) if (waiter_cares (pid, p->p_pgrp->pg_pgid, child->p_pid, child->p_pgrp->pg_pgid)) { if (reap (child)) return 0; had_a_match = 1; } if (!had_a_match) return ECHILD; } if (options & WNOHANG) return EWOULDBLOCK; p->p_waiting = 1; cancel = hurd_condition_wait (&p->p_wakeup, &global_lock); if (p->p_dead) return EOPNOTSUPP; if (cancel) return EINTR; goto start_over; }
/* Output characters. */ static any_t hurdio_writer_loop (any_t arg) { /* XXX The output buffer has 256 bytes. */ #define BUFFER_SIZE 256 char *bufp; char pending_output[BUFFER_SIZE]; size_t amount; error_t err; int size; int npending_output_copy; mach_port_t ioport_copy; mutex_lock (&global_lock); writer_thread = mach_thread_self (); while (1) { while (writer_thread != MACH_PORT_NULL && (ioport == MACH_PORT_NULL || !qsize (outputq) || output_stopped)) hurd_condition_wait (&hurdio_writer_condition, &global_lock); if (writer_thread == MACH_PORT_NULL) /* A sign to die. */ return 0; /* Copy characters onto PENDING_OUTPUT, not bothering those already there. */ size = qsize (outputq); if (size + npending_output > BUFFER_SIZE) size = BUFFER_SIZE - npending_output; bufp = pending_output + npending_output; npending_output += size; /* We need to save these values, as otherwise there are races with hurdio_abandon_physical_output or hurdio_desert_dtr, which might overwrite the static variables. */ npending_output_copy = npending_output; ioport_copy = ioport; mach_port_mod_refs (mach_task_self (), ioport_copy, MACH_PORT_RIGHT_SEND, 1); while (size--) *bufp++ = dequeue (outputq); /* Submit all the outstanding characters to the I/O port. */ mutex_unlock (&global_lock); err = io_write (ioport_copy, pending_output, npending_output_copy, -1, &amount); mutex_lock (&global_lock); mach_port_mod_refs (mach_task_self (), ioport_copy, MACH_PORT_RIGHT_SEND, -1); if (err) hurdio_desert_dtr (); else { /* Note that npending_output might be set to null in the meantime by hurdio_abandon_physical_output. */ if (amount >= npending_output) { npending_output = 0; condition_broadcast (outputq->wait); } else { /* Copy the characters that didn't get output to the front of the array. */ npending_output -= amount; memmove (pending_output, pending_output + amount, npending_output); } } } #undef BUFFER_SIZE return 0; }
static error_t repeater_read (struct protid *cred, char **data, mach_msg_type_number_t *datalen, off_t offset, mach_msg_type_number_t amount) { /* Deny access if they have bad credentials. */ if (! cred) return EOPNOTSUPP; else if (! (cred->po->openstat & O_READ)) return EBADF; mutex_lock (&global_lock); while (!mousebuf.size) { if (cred->po->openstat & O_NONBLOCK && mousebuf.size == 0) { mutex_unlock (&global_lock); return EWOULDBLOCK; } if (hurd_condition_wait (&mousebuf.readcond, &global_lock)) { mutex_unlock (&global_lock); return EINTR; } } amount = (amount / sizeof (kd_event) - 1) * sizeof (kd_event); if (amount > mousebuf.size) amount = mousebuf.size; if (amount > 0) { char *mousedata; unsigned int i = 0; /* Allocate a buffer when this is required. */ if (*datalen < amount) { *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); if (*data == MAP_FAILED) { mutex_unlock (&global_lock); return ENOMEM; } } /* Copy the bytes to the user's buffer and remove them from the mouse events buffer. */ mousedata = *data; while (i != amount) { mousedata[i++] = mousebuf.evtbuffer[mousebuf.pos++]; mousebuf.pos = MOUSEBUF_POS (mousebuf.pos); } mousebuf.size -= amount; condition_broadcast (&mousebuf.writecond); } *datalen = amount; mutex_unlock (&global_lock); return 0; }