home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / library / ix_sleep.c < prev    next >
C/C++ Source or Header  |  1996-10-01  |  4KB  |  160 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: ix_sleep.c,v 1.4 1994/06/19 15:13:19 rluebbert Exp $
  21.  *
  22.  *  $Log: ix_sleep.c,v $
  23.  *  Revision 1.4  1994/06/19  15:13:19  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  * 
  27.  * 
  28.  */
  29.  
  30. #define _KERNEL
  31. #include "ixemul.h"
  32. #include "kprintf.h"
  33.  
  34. #define __time_req (u.u_time_req)
  35. #define __tport    (u.u_sync_mp)
  36.  
  37. /* this is the `message' we queue on the sleep queues. */
  38. struct sleep_msg {
  39.   struct MinNode     sm_node;
  40.   short            sm_signal;
  41.   struct Task*        sm_sigtask;
  42.   u_int            sm_waitchan;
  43. };
  44.  
  45.  
  46. static inline u_short
  47. ix_hash (u_int waitchan)
  48. {
  49.   unsigned short res;
  50.  
  51.   res = (waitchan >> 16) ^ (waitchan & 0xffff);
  52.   res %= IX_NUM_SLEEP_QUEUES;
  53.   return res; 
  54. }
  55.  
  56. int
  57. tsleep(caddr_t waitchan, char *wmesg, int timo)
  58. {
  59.   /* we run in the context of the calling task, we generate a sleep msg and
  60.    * add it to the right sleep queue. wakeup() will do the rest.
  61.    */
  62.   struct sleep_msg sm;
  63.   struct MinList *the_list;
  64.   u_int wait_sigs;
  65.   int res = -1;
  66.  
  67.   if (CURSIG (& u))
  68.     {
  69.       errno = EINTR;
  70.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  71.       return -1;
  72.     }
  73.  
  74.   sm.sm_sigtask = FindTask (0);
  75.   sm.sm_waitchan = (u_int)waitchan;
  76.  
  77.   u.p_stat = SSLEEP;    /* so that machdep.c can interrupt us */
  78.   u.p_wchan = (caddr_t) waitchan;
  79.   u.p_wmesg = wmesg;
  80.   the_list = &ixemulbase->ix_sleep_queues[ix_hash((u_int)waitchan)];
  81.   
  82.   sm.sm_signal = u.u_sleep_sig;
  83.  
  84.   wait_sigs =  (1 << sm.sm_signal) | SIGBREAKF_CTRL_C;
  85.   
  86.   if (timo)
  87.     {
  88.       __time_req->tr_time.tv_sec = timo % 60;
  89.       __time_req->tr_time.tv_usec = timo / 60;
  90.       __time_req->tr_node.io_Command = TR_ADDREQUEST;
  91.       SetSignal (0, 1 << __tport->mp_SigBit);
  92.       SendIO((struct IORequest *)__time_req);
  93.       wait_sigs |= 1 << __tport->mp_SigBit;
  94.     }
  95.  
  96.   Forbid();
  97.   AddTail ((struct List *) the_list, (struct Node *) &sm);
  98.  
  99.   /* this will break the Disable () and reestablish it afterwards */
  100.   res = Wait (wait_sigs);
  101.   /* this conversion is inhibited in the Launch handler as long as we're
  102.      in SSLEEP state. Since the SetSignal() below will remove all traces
  103.      of a perhaps present SIGBREAKF_CTRL_C, we'll have to do the conversion
  104.      here ourselves */
  105.   if (((u.p_sigignore & sigmask(SIGMSG)) || !(u.p_sigcatch & sigmask(SIGMSG)))
  106.       && (res & SIGBREAKF_CTRL_C))
  107.     {
  108.       struct Process *proc = (struct Process *)(u.u_session ? u.u_session->pgrp : getpid());
  109.       _psignalgrp(proc, SIGINT);
  110.     }
  111.   SetSignal (0, res);
  112.   res = CURSIG (&u) ? -1 : 0;
  113.  
  114.   Remove ((struct Node *) &sm);
  115.   Permit();
  116.  
  117.   if (timo)
  118.     {
  119.       if (! CheckIO ((struct IORequest *)__time_req))
  120.         AbortIO ((struct IORequest *)__time_req);
  121.       WaitIO ((struct IORequest *)__time_req);
  122.     }
  123.  
  124.   u.p_wchan = 0;
  125.   u.p_wmesg = 0;
  126.   u.p_stat = SRUN;
  127.   if (res)
  128.     errno = EINTR;
  129.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  130.   return res;
  131. }
  132.  
  133. int
  134. ix_sleep (caddr_t chan, char *wmesg)
  135. {
  136.   return tsleep (chan, wmesg, 0);
  137. }
  138.  
  139.  
  140. /*
  141.  * ix_wakeup() can be called from an interrupt (and is called that way;-))
  142.  */
  143.  
  144. void
  145. ix_wakeup (u_int waitchan)
  146. {
  147.   struct MinList *the_list = & ixemulbase->ix_sleep_queues[ix_hash (waitchan)];
  148.   struct sleep_msg *sm, *nsm;
  149.   
  150.   Forbid();
  151.  
  152.   for (sm  = (struct sleep_msg *)the_list->mlh_Head;
  153.        (nsm = (struct sleep_msg *)sm->sm_node.mln_Succ);
  154.        sm  = nsm)
  155.     if (sm->sm_waitchan == waitchan)
  156.       Signal (sm->sm_sigtask, 1 << sm->sm_signal);
  157.  
  158.   Permit();
  159. }
  160.