home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / kaffe-0.5p4-src.tgz / tar.out / contrib / kaffe / kaffevm / threadCalls.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  338 lines

  1. /*
  2.  * threadCalls.c
  3.  * Support for threaded ops which may block (read, write, connect, etc.).
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #define    DBG(s)
  15.  
  16. #include "config.h"
  17. #include <stdlib.h>
  18. #include <sys/types.h>
  19. #if defined(HAVE_UNISTD_H)
  20. #include <unistd.h>
  21. #endif
  22. #include "lerrno.h"
  23. #include <assert.h>
  24. #if defined(HAVE_SYS_SOCKET_H)
  25. #include <sys/socket.h>
  26. #endif
  27. #if defined(HAVE_SYS_TIME_H)
  28. #include <sys/time.h>
  29. #endif
  30. #if defined(HAVE_WINSOCK_H)
  31. #include <winsock.h>
  32. #endif
  33. #if defined(HAVE_SYS_IOCTL_H)
  34. #include <sys/ioctl.h>
  35. #endif
  36. #if defined(HAVE_IO_H)
  37. #include <io.h>
  38. #endif
  39. #if defined(HAVE_FCNTL_H)
  40. #include <fcntl.h>
  41. #endif
  42. #include "object.h"
  43. #include "thread.h"
  44. #include "md.h"
  45.  
  46. /*
  47.  * We only need this stuff is we are using the internal thread system.
  48.  */
  49. #if defined(USE_INTERNAL_THREADS)
  50.  
  51. #if !defined(HAVE_MEMCPY)
  52. void bcopy(void*, void*, size_t);
  53. #define memcpy(d, s, n) bcopy ((s), (d), (n))
  54. #endif
  55.  
  56. /* QUICK HACK!! */
  57. #if defined(__WIN32__)
  58. #define    ioctl    ioctlsocket
  59. #endif
  60.  
  61. #define    TH_READ        0
  62. #define    TH_WRITE    1
  63.  
  64. static int maxFd;
  65. static fd_set readsPending;
  66. static fd_set writesPending;
  67. static thread* readQ[FD_SETSIZE];
  68. static thread* writeQ[FD_SETSIZE];
  69. static struct timeval tm = { 0, 0 };
  70.  
  71. static void blockOnFile(int, int);
  72. void waitOnEvents(void);
  73.  
  74. extern thread* currentThread;
  75.  
  76. /* These are undefined because we do not yet support async I/O */
  77. #undef    F_SETOWN
  78. #undef    FIOSETOWN
  79. #undef    O_ASYNC
  80. #undef    FIOASYNC
  81.  
  82. /*
  83.  * QUICK HACK!!
  84.  * For the Amiga port we cannot thread writing.  Neither can we use
  85.  * select to thread writes (which will block anyway).
  86.  */
  87. #if defined(__amigaos__)
  88. #define    NO_WRITE_THREADING
  89. #endif
  90.  
  91. /*
  92.  * Create a threaded file descriptor.
  93.  */
  94. int
  95. threadedFileDescriptor(int fd)
  96. {
  97.     int r;
  98.     int on = 1;
  99.     int pid;
  100.  
  101.     /* Make non-blocking */
  102. #if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
  103.     r = fcntl(fd, F_GETFL, 0);
  104.     r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
  105. #elif defined(HAVE_IOCTL) && defined(FIONBIO)
  106.     r = ioctl(fd, FIONBIO, &on);
  107. #else
  108.     r = 0;
  109. #endif
  110.     if (r < 0) {
  111.         return (r);
  112.     }
  113.  
  114.     /* Allow socket to signal this process when new data is available */
  115.     pid = getpid();
  116. #if defined(HAVE_FCNTL) && defined(F_SETOWN)
  117.     r = fcntl(fd, F_SETOWN, pid);
  118. #elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
  119.     r = ioctl(fd, FIOSETOWN, &pid);
  120. #else
  121.     r = 0;
  122. #endif
  123.     if (r < 0) {
  124.         return (r);
  125.     }
  126.  
  127. #if defined(HAVE_FCNTL) && defined(O_ASYNC)
  128.     r = fcntl(fd, F_GETFL, 0);
  129.     r = fcntl(fd, F_SETFL, r|O_ASYNC);
  130. #elif defined(HAVE_IOCTL) && defined(FIOASYNC)
  131.     r = ioctl(fd, FIOASYNC, &on);
  132. #else
  133.     r = 0;
  134. #endif
  135.     if (r < 0) {
  136.         return (r);
  137.     }
  138.     return (fd);
  139. }
  140.  
  141. /*
  142.  * Threaded create socket.
  143.  */
  144. int
  145. threadedSocket(int af, int type, int proto)
  146. {
  147.     int fd;
  148.     int r;
  149.     int on = 1;
  150.     int pid;
  151.  
  152.     fd = socket(af, type, proto);
  153.     return (threadedFileDescriptor(fd));
  154. }
  155.  
  156. /*
  157.  * Threaded file open.
  158.  */
  159. int
  160. threadedOpen(char* path, int flags, int mode)
  161. {
  162.     int fd;
  163.     int r;
  164.     int on = 1;
  165.     int pid;
  166.  
  167.     fd = open(path, flags, mode);
  168.     return (threadedFileDescriptor(fd));
  169. }
  170.  
  171. /*
  172.  * Threaded socket connect.
  173.  */
  174. int
  175. threadedConnect(int fd, struct sockaddr* addr, int len)
  176. {
  177.     int r;
  178.  
  179.     r = connect(fd, addr, len);
  180.     if ((r < 0) && (errno == EINPROGRESS || errno == EALREADY || errno == EWOULDBLOCK)) {
  181.         blockOnFile(fd, TH_WRITE);
  182.         r = 0; /* Assume it's okay when we get released */
  183.     }
  184.  
  185.     return (r);
  186. }
  187.  
  188. /*
  189.  * Threaded socket accept.
  190.  */
  191. int
  192. threadedAccept(int fd, struct sockaddr* addr, int* len)
  193. {
  194.     int r;
  195.     int on = 1;
  196.  
  197.     for (;;) {
  198.         r = accept(fd, addr, len);
  199.         if (r >= 0 || !(errno == EINPROGRESS || errno == EALREADY || errno == EWOULDBLOCK)) {
  200.             break;
  201.         }
  202.         blockOnFile(fd, TH_READ);
  203.     }
  204.     return (threadedFileDescriptor(r));
  205. }
  206.  
  207. /*
  208.  * Read but only if we can.
  209.  */
  210. int
  211. threadedRead(int fd, char* buf, int len)
  212. {
  213.     int r;
  214.  
  215.     for (;;) {
  216. #if defined(NO_READ_THREADING)
  217.         blockOnFile(fd, TH_READ);
  218. #endif
  219.         r = read(fd, buf, len);
  220.         if (r >= 0 || errno != EAGAIN) {
  221.             return (r);
  222.         }
  223. #if !defined(NO_READ_THREADING)
  224.         blockOnFile(fd, TH_READ);
  225. #endif
  226.     }
  227. }
  228.  
  229. /*
  230.  * Write but only if we can.
  231.  */
  232. int
  233. threadedWrite(int fd, char* buf, int len)
  234. {
  235.     int r;
  236.     char* ptr;
  237.  
  238.     ptr = buf;
  239.     do {
  240. #if defined(NO_WRITE_THREADING)
  241.         blockOnFile(fd, TH_WRITE);
  242. #endif
  243.         r = write(fd, ptr, len);
  244.         if (r < 0 && errno == EAGAIN) {
  245. #if !defined(NO_WRITE_THREADING)
  246.             blockOnFile(fd, TH_WRITE);
  247. #endif
  248.             r = 1;
  249.             continue;
  250.         }
  251.         ptr += r;
  252.         len -= r;
  253.  
  254.     } while (len > 0 && r > 0);
  255.  
  256.     return (ptr - buf);
  257. }
  258.  
  259. /*
  260.  * An attempt to access a file would block, so suspend the thread until
  261.  * it will happen.
  262.  */
  263. static
  264. void
  265. blockOnFile(int fd, int op)
  266. {
  267. DBG(    printf("blockOnFile()\n");                    )
  268.  
  269.     intsDisable();
  270.  
  271.     if (fd > maxFd) {
  272.         maxFd = fd;
  273.     }
  274.     if (op == TH_READ) {
  275.         FD_SET(fd, &readsPending);
  276.         suspendOnQThread(currentThread, &readQ[fd]);
  277.         FD_CLR(fd, &readsPending);
  278.     }
  279.     else {
  280.         FD_SET(fd, &writesPending);
  281.         suspendOnQThread(currentThread, &writeQ[fd]);
  282.         FD_CLR(fd, &writesPending);
  283.     }
  284.  
  285.     intsRestore();
  286. }
  287.  
  288. /*
  289.  * Check if some file descriptor or other event to become ready.
  290.  *  Block if required.
  291.  */
  292. void
  293. checkEvents(bool block)
  294. {
  295.     int r;
  296.     fd_set rd;
  297.     fd_set wr;
  298.     thread* tid;
  299.     thread* ntid;
  300.     int i;
  301.  
  302. DBG(    printf("checkEvents block:%d\n", block);            )
  303.  
  304.     intsDisable();
  305.  
  306. #if defined(FD_COPY)
  307.     FD_COPY(&readsPending, &rd);
  308.     FD_COPY(&writesPending, &wr);
  309. #else
  310.     memcpy(&rd, &readsPending, sizeof(rd));
  311.     memcpy(&wr, &writesPending, sizeof(wr));
  312. #endif
  313.     r = select(maxFd+1, &rd, &wr, 0, (block ? 0 : &tm));
  314. DBG(    printf("Select returns %d\n", r);                )
  315.  
  316.     for (i = 0; r > 0 && i <= maxFd; i++) {
  317.         if (readQ[i] != 0 && FD_ISSET(i, &rd)) {
  318.             for (tid = readQ[i]; tid != 0; tid = ntid) {
  319.                 ntid = tid->next;
  320.                 resumeThread(tid);
  321.             }
  322.             readQ[i] = 0;
  323.             r--;
  324.         }
  325.         if (writeQ[i] != 0 && FD_ISSET(i, &wr)) {
  326.             for (tid = writeQ[i]; tid != 0; tid = ntid) {
  327.                 ntid = tid->next;
  328.                 resumeThread(tid);
  329.             }
  330.             writeQ[i] = 0;
  331.             r--;
  332.         }
  333.     }
  334.  
  335.     intsRestore();
  336. }
  337. #endif
  338.