Annotation of libwww/Library/src/HTNet.c, revision 2.7.2.1
2.4 frystyk 1: /* HTThread.c
2: ** MULTIPLE THREAD SOCKET MANAGEMENT
2.1 frystyk 3: **
2.4 frystyk 4: ** (c) COPYRIGHT CERN 1994.
5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** This is the implementation of the internal library multithreading
2.1 frystyk 8: ** functions. This includes an interrupt handler and a event loop.
9: **
10: ** History:
11: ** 12 June 94 Written by Henrik Frystyk, frystyk@dxcern.cern.ch
12: */
13:
2.7.2.1 ! frystyk 14: /* Implemention dependent include files */
2.7 frystyk 15: #include "tcp.h"
2.7.2.1 ! frystyk 16:
! 17: /* Library include files */
2.1 frystyk 18: #include "HTUtils.h"
19: #include "HTAccess.h"
20: #include "HTError.h"
21: #include "HTThread.h" /* Implemented here */
22:
2.7.2.1 ! frystyk 23: #ifdef WIN32
! 24: #include <io.h>
! 25: #endif
! 26:
2.1 frystyk 27: /* Type definitions and global variables etc. local to this module */
28: PRIVATE fd_set HTfd_read; /* Bit array of sockets ready for read */
29: PRIVATE fd_set HTfd_write; /* Bit array of sockets ready for write */
30: PRIVATE int HTMaxfdpl = 0; /* Max number of sockets + 1 */
31:
32: PRIVATE fd_set HTfd_intr; /* All sockets currently interrupted */
33: PRIVATE fd_set HTfd_set; /* All sockets currently registered */
34:
2.7.2.1 ! frystyk 35:
2.1 frystyk 36: PRIVATE HTList *HTThreads = NULL; /* List of the HTNetInfo structures */
37:
38: /* ------------------------------------------------------------------------- */
39:
40: /* HTThreadInit
41: **
42: ** Initiates the thread socket registers. It is very important that
43: ** this function is called. It is currently done inside HTAccess in the
44: ** HTAccessInit function.
45: */
46: PUBLIC BOOL HTThreadInit NOARGS
47: {
48: static BOOL done=NO;
49:
50: if (done) {
51: if (THD_TRACE)
2.7 frystyk 52: fprintf(TDEST, "ThreadInit.. Already done\n");
2.1 frystyk 53: return NO;
54: }
55: done = YES;
56:
57: /* Initialize the other internal bit arrays */
2.7.2.1 ! frystyk 58: FD_ZERO(&HTfd_read);
2.1 frystyk 59: FD_ZERO(&HTfd_write);
60: FD_ZERO(&HTfd_set);
61: FD_ZERO(&HTfd_intr);
62: return YES;
63: }
64:
65:
66: /* HTThreadGetFDInfo
67: **
68: ** Returns the maximum bit width and the read and write bit array.
69: */
70: PUBLIC int HTThreadGetFDInfo ARGS2(fd_set *, read, fd_set *, write)
71: {
72: *read = HTfd_read;
73: *write = HTfd_write;
74: return HTMaxfdpl;
75: }
76:
77:
78: /* HTThreadState
79: **
80: ** This function registers a socket as waiting for the action given
81: ** (read or write etc.).
82: */
2.7 frystyk 83: PUBLIC void HTThreadState ARGS2(SOCKFD, sockfd, HTThreadAction, action)
2.1 frystyk 84: {
2.7.2.1 ! frystyk 85: #ifdef _WIN32
! 86: if (sockfd <= 2)
! 87: sockfd = _get_osfhandle(sockfd);
! 88: #endif
! 89:
2.1 frystyk 90: if (THD_TRACE) {
91: static char *actionmsg[] = {
92: "SET WRITE",
93: "CLEAR WRITE",
94: "SET READ",
95: "CLEAR READ",
2.4 frystyk 96: "SET INTERRUPT",
97: "CLEAR INTERRUPT",
2.1 frystyk 98: "CLOSE"
99: };
2.7 frystyk 100: fprintf(TDEST,
2.1 frystyk 101: "Thread...... Register socket number %d for action %s\n",
102: sockfd, *(actionmsg+action));
103: }
104: switch (action) {
105: case THD_SET_WRITE:
106: FD_CLR(sockfd, &HTfd_read);
2.7.2.1 ! frystyk 107: if (! FD_ISSET(sockfd, &HTfd_write))
! 108: FD_SET(sockfd, &HTfd_write);
! 109: if (! FD_ISSET(sockfd, &HTfd_set))
! 110: FD_SET(sockfd, &HTfd_set);
2.1 frystyk 111: break;
112:
113: case THD_CLR_WRITE:
114: FD_CLR(sockfd, &HTfd_read);
115: FD_CLR(sockfd, &HTfd_write);
116: FD_CLR(sockfd, &HTfd_set);
117: break;
118:
119: case THD_SET_READ:
120: FD_CLR(sockfd, &HTfd_write);
2.7.2.1 ! frystyk 121: if (! FD_ISSET(sockfd, &HTfd_read))
! 122: FD_SET(sockfd, &HTfd_read);
! 123: if (! FD_ISSET(sockfd, &HTfd_set))
! 124: FD_SET(sockfd, &HTfd_set);
2.1 frystyk 125: break;
126:
127: case THD_CLR_READ:
128: FD_CLR(sockfd, &HTfd_read);
129: FD_CLR(sockfd, &HTfd_write);
130: FD_CLR(sockfd, &HTfd_set);
131: break;
132:
133: case THD_CLOSE:
134: FD_CLR(sockfd, &HTfd_read);
135: FD_CLR(sockfd, &HTfd_write);
136: FD_CLR(sockfd, &HTfd_intr);
137: FD_CLR(sockfd, &HTfd_set);
138: break;
139:
2.2 frystyk 140: case THD_SET_INTR:
2.1 frystyk 141: FD_CLR(sockfd, &HTfd_read);
142: FD_CLR(sockfd, &HTfd_write);
2.7.2.1 ! frystyk 143: if (! FD_ISSET(sockfd, &HTfd_intr))
2.1 frystyk 144: FD_SET(sockfd, &HTfd_intr);
145: break;
146:
2.2 frystyk 147: case THD_CLR_INTR:
148: FD_CLR(sockfd, &HTfd_intr);
149: break;
150:
2.1 frystyk 151: default:
152: if (THD_TRACE)
2.7 frystyk 153: fprintf(TDEST, "Thread...... Illigal socket action\n");
2.1 frystyk 154: }
155:
156: /* Update max bit width. The method used ignores any other default
2.2 frystyk 157: opened file descriptors between 0 and the actual set of file
158: descriptors used. However, they are not registered anyway */
2.7.2.1 ! frystyk 159:
2.1 frystyk 160: if (action == THD_CLOSE) {
2.7.2.1 ! frystyk 161: #ifdef _WINSOCKAPI_
! 162: HTMaxfdpl = HTfd_set.fd_count ;
! 163: #else
2.1 frystyk 164: if (sockfd+1 >= HTMaxfdpl) {
2.2 frystyk 165: while (HTMaxfdpl > 0 && !FD_ISSET(HTMaxfdpl-1, &HTfd_set))
2.1 frystyk 166: HTMaxfdpl--;
167: }
2.7.2.1 ! frystyk 168: #endif
2.1 frystyk 169: } else {
2.7.2.1 ! frystyk 170: #ifdef _WINSOCKAPI_
! 171: HTMaxfdpl = HTfd_set.fd_count;
! 172: #else
2.1 frystyk 173: if (sockfd+1 > HTMaxfdpl)
174: HTMaxfdpl = sockfd+1;
2.7.2.1 ! frystyk 175: #endif
2.1 frystyk 176: }
177: if (THD_TRACE)
2.7 frystyk 178: fprintf(TDEST, "Thread...... Max bitwidth is %d\n", HTMaxfdpl);
2.1 frystyk 179: }
180:
181:
182: /* HTThreadIntr
183: **
184: ** This function returns YES or NO to the question
185: */
2.7 frystyk 186: PUBLIC BOOL HTThreadIntr ARGS1(SOCKFD, sockfd)
2.1 frystyk 187: {
188: return FD_ISSET(sockfd, &HTfd_intr) ? YES : NO;
189: }
190:
191:
192: /* HTThreadMarkIntrAll
193: **
2.2 frystyk 194: ** Marks all Library sockets as interrupted. User sockets can not be
195: ** interrupted
2.1 frystyk 196: */
2.2 frystyk 197: PUBLIC void HTThreadMarkIntrAll ARGS1(CONST fd_set *, fd_user)
2.1 frystyk 198: {
199: int cnt;
200: if (THD_TRACE)
2.7 frystyk 201: fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
2.7.2.1 ! frystyk 202: #ifdef _WINSOCKAPI_
! 203: {
! 204: int i;
! 205: for (i = 0 ; i < HTfd_set.fd_count; i++) {
! 206: cnt = HTfd_set.fd_array[i];
! 207: if (!FD_ISSET(cnt, fd_user))
! 208: FD_SET(cnt, &HTfd_intr);
! 209: }
! 210: }
! 211: #else
2.2 frystyk 212: for (cnt=0; cnt<HTMaxfdpl; cnt++) {
2.4 frystyk 213: if (FD_ISSET(cnt, &HTfd_set) && !FD_ISSET(cnt, fd_user))
214: FD_SET(cnt, &HTfd_intr);
2.2 frystyk 215: }
2.7.2.1 ! frystyk 216: #endif
2.1 frystyk 217: }
218:
219:
220: /* HTThreadActive
221: **
222: ** Returns yes as long as a socket other than stdin is registered in
223: ** the total set of sockets.
224: */
225: PUBLIC BOOL HTThreadActive NOARGS
226: {
227: int cnt;
2.7.2.1 ! frystyk 228: #ifdef _WINSOCKAPI_
! 229: if (HTfd_set.fd_count > 0)
! 230: return YES;
! 231: #else
2.1 frystyk 232: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
233: if (FD_ISSET(cnt, &HTfd_set))
234: return YES;
2.7.2.1 ! frystyk 235: #endif
2.1 frystyk 236: return NO;
237: }
238:
239:
240: /* HTThread_new
241: **
242: ** Register the HTNetInfo structure in a list so that we can find the
243: ** request which corresponds to a socket descriptor
244: */
245: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
246: {
247: if (!HTThreads)
248: HTThreads = HTList_new();
249: HTList_addObject(HTThreads, (void *) new_net);
250: }
251:
252:
253: /* HTThread_clear
254: **
255: ** Remove the HTNetInfo from the list of acrive threads.
256: */
257: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
258: {
259: if (HTThreads)
260: return HTList_removeObject(HTThreads, (void *) old_net);
261: return NO;
262: }
263:
264:
265: /* HTThread_getCallBack
266: **
267: ** Finds a socket and makes it the active thread. READ has a higher
268: ** priority than WRITE as it might influence (stop) the WRITE process.
269: ** Returns the request structure of the active thread, NULL on error.
270: ** A interrupted socket has the highest priority
271: */
272: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *, fd_read,
273: CONST fd_set *, fd_write)
274: {
275: HTList *cur = HTThreads;
276: HTNetInfo *pres;
2.7.2.1 ! frystyk 277: int cnt;
! 278: int ic = 0;
2.1 frystyk 279: BOOL found = NO;
2.7.2.1 ! frystyk 280:
! 281: #ifdef _WINSOCKAPI_
! 282: for (ic = 0; ic < HTfd_set.fd_count; ic++) {
! 283: cnt = HTfd_set.fd_array[ic];
! 284: #else
2.1 frystyk 285: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
2.7.2.1 ! frystyk 286: #endif
2.1 frystyk 287: if (FD_ISSET(cnt, &HTfd_intr)) {
288: if (THD_TRACE)
2.7 frystyk 289: fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
2.1 frystyk 290: found = YES;
291: break;
292: }
293: }
294: if (!found) {
2.7.2.1 ! frystyk 295: #ifdef _WINSOCKAPI_
! 296: for (ic = 0; ic < HTfd_set.fd_count; ic++) {
! 297: cnt = HTfd_set.fd_array[ic];
! 298: #else
! 299: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
! 300: #endif
2.1 frystyk 301: if (FD_ISSET(cnt, fd_read)) {
302: if (THD_TRACE)
2.7 frystyk 303: fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
2.1 frystyk 304: found = YES;
305: break;
306: }
307: }
308: }
309: if (!found) {
2.7.2.1 ! frystyk 310: #ifdef _WINSOCKAPI_
! 311: for (ic = 0; ic < HTfd_set.fd_count; ic++) {
! 312: cnt = HTfd_set.fd_array[ic];
! 313: #else
! 314: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
! 315: #endif
2.1 frystyk 316: if (FD_ISSET(cnt, fd_write)) {
317: if (THD_TRACE)
2.7 frystyk 318: fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
2.1 frystyk 319: found = YES;
320: break;
321: }
322: }
323: }
324: if (!found || cur == NULL)
325: return NULL;
326:
327: /* Find the corresponding HTNetInfo structure */
328: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
329: if (pres->sockfd == cnt) {
330: return pres->request;
331: }
332: }
333: return NULL;
334: }
Webmaster