#include <types/pipe.h>
/* socket functions used when running a stream interface as a task */
-static void stream_int_update_embedded(struct stream_interface *si);
static void stream_int_shutr(struct stream_interface *si);
static void stream_int_shutw(struct stream_interface *si);
static void stream_int_chk_rcv(struct stream_interface *si);
/* stream-interface operations for embedded tasks */
struct si_ops si_embedded_ops = {
- .update = stream_int_update_embedded,
.chk_rcv = stream_int_chk_rcv,
.chk_snd = stream_int_chk_snd,
.shutr = stream_int_shutr,
channel_shutr_now(oc);
}
-/* default update function for embedded tasks, to be used at the end of the i/o handler */
-static void stream_int_update_embedded(struct stream_interface *si)
-{
- int old_flags = si->flags;
- struct channel *ic = si_ic(si);
- struct channel *oc = si_oc(si);
-
- DPRINTF(stderr, "%s: si=%p, si->state=%d ic->flags=%08x oc->flags=%08x\n",
- __FUNCTION__,
- si, si->state, ic->flags, oc->flags);
-
- if (si->state != SI_ST_EST)
- return;
-
- if ((oc->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
- channel_is_empty(oc))
- si_shutw(si);
-
- if ((oc->flags & (CF_SHUTW|CF_SHUTW_NOW)) == 0 && channel_may_recv(oc))
- si->flags |= SI_FL_WAIT_DATA;
-
- /* we're almost sure that we need some space if the buffer is not
- * empty, even if it's not full, because the applets can't fill it.
- */
- if ((ic->flags & (CF_SHUTR|CF_DONT_READ)) == 0 && !channel_is_empty(ic))
- si->flags |= SI_FL_WAIT_ROOM;
-
- if (oc->flags & CF_WRITE_ACTIVITY) {
- if (tick_isset(oc->wex))
- oc->wex = tick_add_ifset(now_ms, oc->wto);
- }
-
- if (ic->flags & CF_READ_ACTIVITY ||
- (oc->flags & CF_WRITE_ACTIVITY && !(si->flags & SI_FL_INDEP_STR))) {
- if (tick_isset(ic->rex))
- ic->rex = tick_add_ifset(now_ms, ic->rto);
- }
-
- /* save flags to detect changes */
- old_flags = si->flags;
- if (likely((oc->flags & (CF_SHUTW|CF_WRITE_PARTIAL|CF_DONT_READ)) == CF_WRITE_PARTIAL &&
- channel_may_recv(oc) &&
- (si_opposite(si)->flags & SI_FL_WAIT_ROOM)))
- si_chk_rcv(si_opposite(si));
-
- if (((ic->flags & CF_READ_PARTIAL) && !channel_is_empty(ic)) &&
- (ic->pipe /* always try to send spliced data */ ||
- (ic->buf->i == 0 && (si_opposite(si)->flags & SI_FL_WAIT_DATA)))) {
- si_chk_snd(si_opposite(si));
- /* check if the consumer has freed some space */
- if (channel_may_recv(ic) && !ic->pipe)
- si->flags &= ~SI_FL_WAIT_ROOM;
- }
-
- /* Note that we're trying to wake up in two conditions here :
- * - special event, which needs the holder task attention
- * - status indicating that the applet can go on working. This
- * is rather hard because we might be blocking on output and
- * don't want to wake up on input and vice-versa. The idea is
- * to only rely on the changes the chk_* might have performed.
- */
- if (/* check stream interface changes */
- ((old_flags & ~si->flags) & (SI_FL_WAIT_ROOM|SI_FL_WAIT_DATA)) ||
-
- /* changes on the production side */
- (ic->flags & (CF_READ_NULL|CF_READ_ERROR)) ||
- si->state != SI_ST_EST ||
- (si->flags & SI_FL_ERR) ||
- ((ic->flags & CF_READ_PARTIAL) &&
- (!ic->to_forward || si_opposite(si)->state != SI_ST_EST)) ||
-
- /* changes on the consumption side */
- (oc->flags & (CF_WRITE_NULL|CF_WRITE_ERROR)) ||
- ((oc->flags & CF_WRITE_ACTIVITY) &&
- ((oc->flags & CF_SHUTW) ||
- ((oc->flags & CF_WAKE_WRITE) &&
- (si_opposite(si)->state != SI_ST_EST ||
- (channel_is_empty(oc) && !oc->to_forward)))))) {
- if (!(si->flags & SI_FL_DONT_WAKE))
- task_wakeup(si_task(si), TASK_WOKEN_IO);
- }
- if (ic->flags & CF_READ_ACTIVITY)
- ic->flags &= ~CF_READ_DONTWAIT;
-}
-
/*
* This function performs a shutdown-read on a detached stream interface in a
* connected or init state (it does nothing for other states). It either shuts