Annotation of libwww/Library/src/HTNet.c, revision 2.7.2.2
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 */
58: FD_ZERO(&HTfd_write);
59: FD_ZERO(&HTfd_set);
60: FD_ZERO(&HTfd_intr);
2.7.2.2 ! cbrooks 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.7.2.1 frystyk 86: #ifdef _WIN32
2.7.2.2 ! cbrooks 87: if (sockfd <= 2)
! 88: sockfd = _get_osfhandle(sockfd) ;
2.7.2.1 frystyk 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.7.2.1 frystyk 108: if (! FD_ISSET(sockfd, &HTfd_write))
2.7.2.2 ! cbrooks 109: FD_SET(sockfd, &HTfd_write);
2.7.2.1 frystyk 110: if (! FD_ISSET(sockfd, &HTfd_set))
2.7.2.2 ! cbrooks 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.7.2.1 frystyk 121: if (! FD_ISSET(sockfd, &HTfd_read))
2.7.2.2 ! cbrooks 122: FD_SET(sockfd, &HTfd_read);
! 123: FD_CLR(sockfd, &HTfd_write);
2.7.2.1 frystyk 124: if (! FD_ISSET(sockfd, &HTfd_set))
2.7.2.2 ! cbrooks 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.7.2.1 frystyk 144: if (! FD_ISSET(sockfd, &HTfd_intr))
2.7.2.2 ! cbrooks 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.7.2.1 frystyk 160:
2.1 frystyk 161: if (action == THD_CLOSE) {
2.7.2.1 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.7.2.1 frystyk 169: #endif
2.1 frystyk 170: } else {
2.7.2.1 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.7.2.1 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: {
2.7.2.2 ! cbrooks 200: int cnt; int i;
2.1 frystyk 201: if (THD_TRACE)
2.7 frystyk 202: fprintf(TDEST, "Thread...... Mark ALL Library sockfd INTERRUPTED\n");
2.7.2.1 frystyk 203: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks 204: for (i = 0 ; i < HTfd_set.fd_count; i++) { cnt = HTfd_set.fd_array[i]; if (
2.7.2.1 frystyk 205: #else
2.7.2.2 ! cbrooks 206: for (cnt=0; cnt<HTMaxfdpl; cnt++) { if (FD_ISSET(cnt, &HTfd_set) &&
! 207: #endif
! 208: !FD_ISSET(cnt, fd_user))
2.4 frystyk 209: FD_SET(cnt, &HTfd_intr);
2.2 frystyk 210: }
2.1 frystyk 211: }
212:
213:
214: /* HTThreadActive
215: **
216: ** Returns yes as long as a socket other than stdin is registered in
217: ** the total set of sockets.
218: */
219: PUBLIC BOOL HTThreadActive NOARGS
220: {
221: int cnt;
2.7.2.1 frystyk 222: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks 223: if (HTfd_set.fd_count > 0)
! 224: return YES;
2.7.2.1 frystyk 225: #else
2.1 frystyk 226: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++)
227: if (FD_ISSET(cnt, &HTfd_set))
228: return YES;
2.7.2.1 frystyk 229: #endif
2.1 frystyk 230: return NO;
231: }
232:
233:
234: /* HTThread_new
235: **
236: ** Register the HTNetInfo structure in a list so that we can find the
237: ** request which corresponds to a socket descriptor
238: */
239: PUBLIC void HTThread_new ARGS1(HTNetInfo *, new_net)
240: {
241: if (!HTThreads)
2.7.2.2 ! cbrooks 242: HTThreads = HTList_new();
2.1 frystyk 243: HTList_addObject(HTThreads, (void *) new_net);
244: }
245:
246:
247: /* HTThread_clear
248: **
249: ** Remove the HTNetInfo from the list of acrive threads.
250: */
251: PUBLIC int HTThread_clear ARGS1(HTNetInfo *, old_net)
252: {
253: if (HTThreads)
2.7.2.2 ! cbrooks 254: return HTList_removeObject(HTThreads, (void *) old_net);
2.1 frystyk 255: return NO;
256: }
257:
258:
259: /* HTThread_getCallBack
260: **
261: ** Finds a socket and makes it the active thread. READ has a higher
262: ** priority than WRITE as it might influence (stop) the WRITE process.
263: ** Returns the request structure of the active thread, NULL on error.
264: ** A interrupted socket has the highest priority
265: */
266: PUBLIC HTRequest *HTThread_getRequest ARGS2(CONST fd_set *, fd_read,
267: CONST fd_set *, fd_write)
268: {
269: HTList *cur = HTThreads;
270: HTNetInfo *pres;
2.7.2.1 frystyk 271: int cnt;
2.7.2.2 ! cbrooks 272: int ic = 0 ;
2.1 frystyk 273: BOOL found = NO;
2.7.2.1 frystyk 274:
275: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks 276: for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic];
2.7.2.1 frystyk 277: #else
2.1 frystyk 278: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
2.7.2.1 frystyk 279: #endif
2.1 frystyk 280: if (FD_ISSET(cnt, &HTfd_intr)) {
281: if (THD_TRACE)
2.7 frystyk 282: fprintf(TDEST, "GetSocket... Socket %d INTERRUPTED\n", cnt);
2.1 frystyk 283: found = YES;
284: break;
285: }
286: }
287: if (!found) {
2.7.2.1 frystyk 288: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks 289: for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic];
2.7.2.1 frystyk 290: #else
2.7.2.2 ! cbrooks 291: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
2.7.2.1 frystyk 292: #endif
2.1 frystyk 293: if (FD_ISSET(cnt, fd_read)) {
294: if (THD_TRACE)
2.7 frystyk 295: fprintf(TDEST, "GetSocket... Socket %d for READ\n", cnt);
2.1 frystyk 296: found = YES;
297: break;
298: }
299: }
300: }
301: if (!found) {
2.7.2.1 frystyk 302: #ifdef _WINSOCKAPI_
2.7.2.2 ! cbrooks 303: for (ic = 0; ic < HTfd_set.fd_count; ic++) { cnt = HTfd_set.fd_array[ic];
2.7.2.1 frystyk 304: #else
2.7.2.2 ! cbrooks 305: for (cnt=STDIN_FILENO+1; cnt<HTMaxfdpl; cnt++) { /* INTERRUPT */
2.7.2.1 frystyk 306: #endif
2.1 frystyk 307: if (FD_ISSET(cnt, fd_write)) {
308: if (THD_TRACE)
2.7 frystyk 309: fprintf(TDEST, "GetSocket... Socket %d for WRITE\n", cnt);
2.1 frystyk 310: found = YES;
311: break;
312: }
313: }
314: }
315: if (!found || cur == NULL)
2.7.2.2 ! cbrooks 316: return NULL;
2.1 frystyk 317:
318: /* Find the corresponding HTNetInfo structure */
319: while ((pres = (HTNetInfo *) HTList_nextObject(cur)) != NULL) {
2.7.2.2 ! cbrooks 320: if (pres->sockfd == cnt) {
2.1 frystyk 321: return pres->request;
2.7.2.2 ! cbrooks 322: }
2.1 frystyk 323: }
324: return NULL;
325: }
Webmaster