head	1.2;
access;
symbols
	version39-41:1.2;
locks;
comment	@ *  @;


1.2
date	92.07.04.19.17.31;	author mwild;	state Exp;
branches;
next	1.1;

1.1
date	92.05.14.19.55.40;	author mwild;	state Exp;
branches;
next	;


desc
@**IX like process synchronisation based on events
@


1.2
log
@store a textual wait-message ala BSD4.4 for use in ps/dump.
Make sure to check for SIGINT after returning from Wait
@
text
@#define KERNEL
#include "ixemul.h"

/* #undef DEBUG */
#ifdef DEBUG
#define DP(a) kprintf a
#else
#define DP(a)
#endif

extern struct ixemul_base *ixemulbase;

/* this is the `message' we queue on the sleep queues. */
struct sleep_msg {
  struct MinNode 	sm_node;
  short			sm_signal;
  struct Task*		sm_sigtask;
  u_int			sm_waitchan;
};


static inline u_short
ix_hash (u_int waitchan)
{
  unsigned short res;

  res = (waitchan >> 16) ^ (waitchan & 0xffff);
  res %= IX_NUM_SLEEP_QUEUES;
  return res; 
}

int
ix_sleep (u_int waitchan, char *wmesg)
{
  /* we run in the context of the calling task, we generate a sleep msg and
   * add it to the right sleep queue. wakeup() will do the rest.
   */
  struct sleep_msg sm;
  struct MinList *the_list;
  u_int wait_sigs;
  int res = -1;

#ifdef DEBUG
  if (u.p_stat == SSLEEP)
    {
      DP(("PANIC!! sleep recursion!\n"));
      while (1) ;
    }
#endif

  if (CURSIG (& u))
    {
      errno = EINTR;
      return -1;
    }

  sm.sm_sigtask = FindTask (0);
  sm.sm_waitchan = waitchan;

  u.p_stat = SSLEEP;	/* so that machdep.c can interrupt us */
  u.p_wchan = (caddr_t) waitchan;
  u.p_wmesg = wmesg;
  the_list = & ixemulbase->ix_sleep_queues [ix_hash (waitchan)];
  
  sm.sm_signal = u.u_sleep_sig;

  wait_sigs =  (1<< sm.sm_signal) | SIGBREAKF_CTRL_C;

  Disable ();
  AddTail ((struct List *) the_list, (struct Node *) &sm);

DP(("ix_sleep: $%lx ", waitchan));
  /* this will break the Disable () and reestablish it afterwards */
  res = Wait (wait_sigs);
  /* this conversion is inhibited in the Launch handler as long as we're
     in SSLEEP state. Since the SetSignal() below will remove all traces
     of a perhaps present SIGBREAKF_CTRL_C, we'll have to do the conversion
     here ourselves */
  if (((u.p_sigignore & sigmask(SIGMSG)) || !(u.p_sigcatch & sigmask(SIGMSG)))
      && (res & SIGBREAKF_CTRL_C))
    _psignal (FindTask (0), SIGINT);
  SetSignal (0, res);
  res = CURSIG (&u) ? -1 : 0;
DP(("ix_sleep: back.\n"));

  Remove ((struct Node *) &sm);
  Enable ();

ret:
  u.p_wchan = 0;
  u.p_wmesg = 0;
  u.p_stat = SRUN;
  errno = res == 0 ? 0 : EINTR;
  return res;
}

/*
 * ix_wakeup() can be called from an interrupt (and is called that way;-))
 */

void
ix_wakeup (u_int waitchan)
{
  struct MinList *the_list = & ixemulbase->ix_sleep_queues[ix_hash (waitchan)];
  struct sleep_msg *sm, *nsm;
  
  Disable ();

  for (sm  = (struct sleep_msg *)the_list->mlh_Head;
       nsm = (struct sleep_msg *)sm->sm_node.mln_Succ;
       sm  = nsm)
    if (sm->sm_waitchan == waitchan)
      Signal (sm->sm_sigtask, 1 << sm->sm_signal);

  Enable ();
}

@


1.1
log
@Initial revision
@
text
@d33 1
a33 1
ix_sleep (u_int waitchan)
d62 1
d75 7
d91 1
@
