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