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