]>
Commit | Line | Data |
---|---|---|
5580185e | 1 | /* |
2 | * $Source$ | |
3 | * $Header$ | |
4 | */ | |
5 | ||
6 | #ifndef lint | |
7 | static char *rcsid_gdb_trans_c = "$Header$"; | |
8 | #endif lint | |
9 | ||
10 | ||
11 | ||
12 | ||
13 | ||
14 | ||
15 | ||
16 | ||
17 | ||
18 | ||
19 | ||
20 | ||
21 | ||
22 | ||
23 | ||
24 | ||
25 | ||
26 | ||
27 | ||
28 | ||
29 | ||
30 | /************************************************************************/ | |
31 | /* | |
32 | /* gdb_trans.c | |
33 | /* | |
34 | /* GDB - Data Transport Services Routines (Part 1) | |
35 | /* | |
36 | /* Author: Noah Mendelsohn | |
37 | /* Copyright: 1986 MIT Project Athena | |
38 | /* | |
39 | /* These routines implement layer 6 of the Client Library | |
40 | /* Specification of the GDB system, as well as the facilities | |
41 | /* outlined in the GDB Protocol Specification. (Part 1 of 2) | |
42 | /* | |
43 | /* Some of the routines specified are actually implemented as | |
44 | /* macros defined in gdb.h. | |
45 | /* | |
46 | /************************************************************************/ | |
47 | ||
48 | #include <sys/types.h> | |
49 | #include <strings.h> | |
50 | #include <stdio.h> | |
51 | #include <varargs.h> | |
52 | #include <errno.h> | |
53 | extern int errno; | |
54 | #include "gdb.h" | |
55 | ||
56 | \f | |
57 | /************************************************************************/ | |
58 | /* | |
59 | /* OPERATION Manipulation | |
60 | /* | |
61 | /* The routines in this section provide services for creating | |
62 | /* and manipulating GDB queueable operations. | |
63 | /* | |
64 | /************************************************************************/ | |
65 | ||
66 | /*----------------------------------------------------------*/ | |
67 | /* | |
68 | /* create_operation (create_operation) | |
69 | /* | |
70 | /* Allocates space for an operation descriptor and | |
71 | /* returns a pointer to it. Initialize the eyecatcher | |
72 | /* so that in the future we can prove by inspection that | |
73 | /* this really is an operation descriptor. | |
74 | /* | |
75 | /*----------------------------------------------------------*/ | |
76 | ||
77 | OPERATION | |
78 | create_operation() | |
79 | { | |
80 | register OPERATION op; | |
81 | GDB_INIT_CHECK | |
82 | op = (OPERATION)db_alloc(sizeof(OPERATION_DATA)); | |
83 | op->status = OP_NOT_STARTED; /* things like */ | |
84 | /* reset_operation */ | |
85 | /* want valid status */ | |
86 | /* at all times*/ | |
87 | op->id = GDB_OP_ID; | |
88 | return op; | |
89 | } | |
90 | ||
91 | /*----------------------------------------------------------*/ | |
92 | /* | |
93 | /* reset_operation (reset_operation) | |
94 | /* | |
95 | /* Sets the status of an operation to OP_NOT_STARTED | |
96 | /* | |
97 | /*----------------------------------------------------------*/ | |
98 | ||
99 | int | |
100 | reset_operation(op) | |
101 | OPERATION op; | |
102 | { | |
103 | register int status; | |
104 | ||
105 | GDB_CHECK_OP(op, "reset_operation") | |
106 | ||
107 | status = OP_STATUS(op); | |
108 | if (status == OP_QUEUED || | |
109 | status == OP_RUNNING) | |
110 | GDB_GIVEUP("gdb:reset_operation invalid on running operation") | |
111 | op->status = OP_NOT_STARTED; | |
112 | } | |
113 | ||
114 | /*----------------------------------------------------------*/ | |
115 | /* | |
116 | /* delete_operation(delete_operation) | |
117 | /* | |
118 | /* Frees an operation descriptor. | |
119 | /* | |
120 | /*----------------------------------------------------------*/ | |
121 | ||
122 | int | |
123 | delete_operation(op) | |
124 | OPERATION op; | |
125 | { | |
126 | GDB_CHECK_OP(op, "delete_operation"); | |
127 | op->id = -1; | |
128 | db_free((char *)op, sizeof(OPERATION_DATA)); | |
129 | } | |
130 | ||
131 | /*----------------------------------------------------------*/ | |
132 | /* | |
133 | /* initialize_operation(initialize_operation) | |
134 | /* | |
135 | /* Initialize the data in an operation descriptor | |
136 | /* based on the supplied parameters. | |
137 | /* | |
138 | /*----------------------------------------------------------*/ | |
139 | ||
140 | int | |
141 | initialize_operation(operation, init_function, arg, cancel_function) | |
142 | OPERATION operation; /* initialize this */ | |
143 | int (*init_function)(); /* function to call when */ | |
144 | /* starting operation */ | |
145 | char *arg; /* arg to pass to init and */ | |
146 | /* continue routines */ | |
147 | int (*cancel_function)(); /* call this function */ | |
148 | /* when cancelling the op. */ | |
149 | /* may be NULL, may not */ | |
150 | /* be elided */ | |
151 | { | |
152 | register OPERATION op = operation; /* just for speed */ | |
153 | ||
154 | GDB_CHECK_OP(op, "initialize_operation") | |
155 | ||
156 | ||
157 | /* | |
158 | * Fill in boilerplate - same for all newly initialized ops. | |
159 | */ | |
160 | op->next = op->prev = NULL; /* it's not in a queue yet */ | |
161 | op->tag = (-1); /* not tagged until queued */ | |
162 | op->status = OP_NOT_STARTED; | |
163 | op->flags = 0; | |
164 | op->result = (-1); /* result is not valid until */ | |
165 | /* status is OP_COMPLETE. */ | |
166 | /* All users of result field */ | |
167 | /* are expected to treat -1 */ | |
168 | /* invalid */ | |
169 | op->halfcon = NULL; /* not queued yet */ | |
170 | ||
171 | /* | |
172 | * Fill in supplied parameters | |
173 | */ | |
174 | op->arg = arg; | |
175 | op->fcn.init = init_function; | |
176 | op->cancel = cancel_function; | |
177 | ||
178 | return; | |
179 | } | |
180 | ||
181 | /*----------------------------------------------------------*/ | |
182 | /* | |
183 | /* create_list_of_operations (create_list_of_operations) | |
184 | /* | |
185 | /* Allocates and fills in a data structure which | |
186 | /* contains a list of operations. This list is | |
187 | /* suitable for passing to op_select. | |
188 | /* | |
189 | /* The facilities of <varargs.h> are used to parse | |
190 | /* the variable length parameter list to this function. | |
191 | /* See "man 3 varargs" for details. | |
192 | /* | |
193 | /*----------------------------------------------------------*/ | |
194 | ||
195 | /*VARARGS1*/ | |
196 | ||
197 | LIST_OF_OPERATIONS | |
198 | create_list_of_operations(count, va_alist) | |
199 | int count; | |
200 | va_dcl | |
201 | { | |
202 | va_list ap; /* the control structure */ | |
203 | /* for varargs parsing */ | |
204 | ||
205 | register int i; | |
206 | register LIST_OF_OPERATIONS newlist; /* newly allocated list */ | |
207 | ||
208 | /* | |
209 | * Allocate the new list of operations, initialize its count. | |
210 | */ | |
211 | newlist = (LIST_OF_OPERATIONS) | |
212 | db_alloc(size_of_list_of_operations(count)); | |
213 | newlist->count = count; | |
214 | ||
215 | /* | |
216 | * Using the facilities of varargs.h, pick up the operations | |
217 | * and put them in the list. | |
218 | */ | |
219 | va_start(ap); | |
220 | for (i=0; i<count; i++) { | |
221 | newlist->op[i] = va_arg(ap, OPERATION); | |
222 | GDB_CHECK_OP((newlist->op[i]), "create_list_of_operations") | |
223 | } | |
224 | va_end(ap); | |
225 | ||
226 | return newlist; | |
227 | } | |
228 | ||
229 | /*----------------------------------------------------------*/ | |
230 | /* | |
231 | /* delete_list_of_operations(delete_list_of_operations) | |
232 | /* | |
233 | /* Deallocate the space for a list of operations. | |
234 | /* | |
235 | /*----------------------------------------------------------*/ | |
236 | ||
237 | int | |
238 | delete_list_of_operations(op_list) | |
239 | LIST_OF_OPERATIONS op_list; | |
240 | { | |
241 | db_free((char *)op_list, size_of_list_of_operations(op_list->count)); | |
242 | } | |
243 | \f | |
244 | /************************************************************************/ | |
245 | /* | |
246 | /* OPERATION QUEUE MANIPULATION | |
247 | /* | |
248 | /* Routines to queue (initiate) and track completion of GDB | |
249 | /* operations. | |
250 | /* | |
251 | /************************************************************************/ | |
252 | ||
253 | /*----------------------------------------------------------*/ | |
254 | /* | |
255 | /* op_select(op_select) | |
256 | /* | |
257 | /* This function is an analog of the standard Berkeley | |
258 | /* select system call. It provides all the functions | |
259 | /* of select, but in addition, it awaits completion | |
260 | /* of a specified list of queued gdb operations. | |
261 | /* | |
262 | /* This function returns when any combination of the | |
263 | /* following are found to be true: | |
264 | /* | |
265 | /* 1) Any of the designated operations has completed | |
266 | /* or terminated prematurely. | |
267 | /* | |
268 | /* 2) Activity is detected on any of the explictly supplied | |
269 | /* file descriptors or the supplied timer has expired. | |
270 | /* | |
271 | /* The count returned is only for file descriptors | |
272 | /* explicitly listed. Completed operatons may be detected | |
273 | /* by checking OP_STATUS for each of the operations in | |
274 | /* the list. File descriptors controlled by CONNECTIONS | |
275 | /* should never be passed explictly in the bit maps to | |
276 | /* this routine. Only user controlled file descriptors | |
277 | /* may be explictly selected. | |
278 | /* | |
279 | /* Return code summary: | |
280 | /* | |
281 | /* -2 One or more listed operations completed. | |
282 | /* Timer did not ring (as far as we could | |
283 | /* tell), other fd's did not complete, or | |
284 | /* we didn't get far enough to bother | |
285 | /* looking. (see fairness below.) | |
286 | /* | |
287 | /* -1 An error was returned on select of a | |
288 | /* user supplied socket. errno has the | |
289 | /* error code. | |
290 | /* | |
291 | /* 0 The timer rang. Some operations may | |
292 | /* be complete, but it's unlikely. | |
293 | /* | |
294 | /* >0 This many user supplied fd's were | |
295 | /* satisfied--same as for select. | |
296 | /* Operations in the list may also have | |
297 | /* completed. | |
298 | /* | |
299 | /* Fairness is not guaranteed. This routine tends to | |
300 | /* favor activity on CONNECTIONs. In particular, if | |
301 | /* some operation(s) in the list can be completed | |
302 | /* synchronously, a real select is never done to | |
303 | /* check on the file descriptors. | |
304 | /* | |
305 | /*----------------------------------------------------------*/ | |
306 | ||
307 | int | |
308 | op_select(op_list, nfds, readfds, writefds, exceptfds, timeout) | |
309 | LIST_OF_OPERATIONS op_list; | |
310 | int nfds; | |
311 | fd_set *readfds, *writefds, *exceptfds; | |
312 | struct timeval *timeout; | |
313 | { | |
314 | int rc; /* return code holder */ | |
315 | fd_set rfds, wfds, efds; /* local copys of read */ | |
316 | /* write, and exception */ | |
317 | /* fd's */ | |
318 | ||
319 | /* | |
320 | * Make sure that any activity which can be done immediately is | |
321 | * indeed done now--we may not have to wait at all. | |
322 | */ | |
323 | (void) gdb_fastprogress(); /*<==FIX (check to make sure this is OK)*/ | |
324 | ||
325 | /* | |
326 | * Loop checking for termination conditions, and if none arise, | |
327 | * use con_select to make wait for one or more of the | |
328 | * connections to wake up and do the appropriate processing. | |
329 | */ | |
330 | while (TRUE) { | |
331 | /* | |
332 | * If any of the queue operations have completed, | |
333 | * then just return now. | |
334 | */ | |
335 | if (gdb_list_complete(op_list)) | |
336 | return (-2); /* no fd's satisfied here */ | |
337 | ||
338 | /* | |
339 | * Use con_select to await all the appropriate events | |
340 | */ | |
341 | g_fd_copy(nfds, readfds, &rfds); | |
342 | g_fd_copy(nfds, writefds, &wfds); | |
343 | g_fd_copy(nfds, exceptfds, &efds); | |
344 | ||
345 | rc = con_select(nfds, &rfds, &wfds, &efds, timeout); | |
346 | ||
347 | /* | |
348 | * At this point, either some of the supplied fd's have | |
349 | * been satisfied(rc>0), or the timer has rung (rc=0), | |
350 | * an error was returned from select on a user specified socket | |
351 | * (-1) or none of these (-2). In any case, there may | |
352 | * have been progress on one of the connections, and | |
353 | * con_select will already have progressed as far as | |
354 | * possible before returning. Now, decide what to | |
355 | * do, given the return code. | |
356 | */ | |
357 | if (rc>= (-1)) { | |
358 | /* | |
359 | * Return updated bit-maps to caller. | |
360 | */ | |
361 | g_fd_copy(nfds, &rfds, readfds); | |
362 | g_fd_copy(nfds, &wfds, writefds); | |
363 | g_fd_copy(nfds, &efds, exceptfds); | |
364 | return rc; | |
365 | } | |
366 | } | |
367 | } | |
368 | \f | |
369 | /*----------------------------------------------------------*/ | |
370 | /* | |
371 | /* op_select_all(op_select_all) | |
372 | /* | |
373 | /* Similar to op_select_any, but returns (-1) only | |
374 | /* in the case that all of the designated descriptors | |
375 | /* are OP_COMPLETE or OP_CANCELLED. | |
376 | /* | |
377 | /*----------------------------------------------------------*/ | |
378 | ||
379 | int | |
380 | op_select_all(op_list, nfds, readfds, writefds, exceptfds, timeout) | |
381 | LIST_OF_OPERATIONS op_list; | |
382 | int nfds; | |
383 | fd_set *readfds, *writefds, *exceptfds; | |
384 | struct timeval *timeout; | |
385 | { | |
386 | register int i; | |
387 | int rc = -1; | |
388 | register int left = op_list->count; | |
389 | ||
390 | /* | |
391 | * take care of those which are already complete by decrementing | |
392 | * and reseting them | |
393 | */ | |
394 | ||
395 | for (i=0; i<op_list->count; i++) { | |
396 | if (op_list->op[i]->status==OP_COMPLETE) { | |
397 | op_list->op[i]->flags |= OPF_MARKED_COMPLETE; | |
398 | op_list->op[i]->status = OP_MARKED; | |
399 | /* so op_select_any won't */ | |
400 | /* fall right through*/ | |
401 | ||
402 | left--; | |
403 | continue; | |
404 | } | |
405 | if (op_list->op[i]->status==OP_CANCELLED) { | |
406 | op_list->op[i]->flags |= OPF_MARKED_CANCELLED; | |
407 | op_list->op[i]->status = OP_MARKED; | |
408 | /* so op_select_any won't */ | |
409 | /* fall right through*/ | |
410 | ||
411 | left--; | |
412 | } | |
413 | } | |
414 | ||
415 | ||
416 | /* | |
417 | * As long as there are incomplete operations left in the list, | |
418 | * keep calling op_select_any | |
419 | */ | |
420 | while (left) { | |
421 | rc = op_select(op_list, nfds, readfds, writefds, exceptfds, | |
422 | timeout); | |
423 | if (rc>=0) | |
424 | break; | |
425 | for (i=0; i<op_list->count; i++) { | |
426 | if (op_list->op[i]->status==OP_COMPLETE) { | |
427 | op_list->op[i]->flags |= OPF_MARKED_COMPLETE; | |
428 | op_list->op[i]->status = OP_MARKED; | |
429 | /* so op_select_any won't */ | |
430 | /* fall right through*/ | |
431 | ||
432 | left--; | |
433 | continue; | |
434 | } | |
435 | if (op_list->op[i]->status==OP_CANCELLED) { | |
436 | op_list->op[i]->flags |= OPF_MARKED_CANCELLED; | |
437 | op_list->op[i]->status = OP_MARKED; | |
438 | /* so op_select_any won't */ | |
439 | /* fall right through*/ | |
440 | ||
441 | left--; | |
442 | } | |
443 | } | |
444 | } | |
445 | ||
446 | /* | |
447 | * Clean up the marked operations and return | |
448 | */ | |
449 | for (i=0; i<op_list->count; i++) { | |
450 | if (op_list->op[i]->status==OP_MARKED) { | |
451 | op_list->op[i]->status = (op_list->op[i]->flags & | |
452 | OPF_MARKED_COMPLETE) ? | |
453 | OP_COMPLETE : | |
454 | OP_CANCELLED; | |
455 | op_list->op[i]->flags &= ~(OPF_MARKED_COMPLETE | | |
456 | OPF_MARKED_CANCELLED); | |
457 | } | |
458 | } | |
459 | ||
460 | return rc; | |
461 | ||
462 | } | |
463 | \f | |
464 | /************************************************************************/ | |
465 | /* | |
466 | /* Internal transport layer routines, not called directly | |
467 | /* from client library. | |
468 | /* | |
469 | /************************************************************************/ | |
470 | ||
471 | /*----------------------------------------------------------*/ | |
472 | /* | |
473 | /* gdb_list_complete | |
474 | /* | |
475 | /* Given a list of gdb operations, return TRUE if any | |
476 | /* of them are complete, otherwise return FALSE. | |
477 | /* | |
478 | /*----------------------------------------------------------*/ | |
479 | ||
480 | int | |
481 | gdb_list_complete(op_list) | |
482 | LIST_OF_OPERATIONS op_list; | |
483 | { | |
484 | register int i; | |
485 | register int status; | |
486 | register LIST_OF_OPERATIONS oplist = op_list; /* for speed */ | |
487 | int count = oplist -> count; | |
488 | ||
489 | for (i=0; i<count; i++) { | |
490 | status = OP_STATUS(oplist->op[i]); | |
491 | if (status == OP_COMPLETE || | |
492 | status == OP_CANCELLED) | |
493 | return TRUE; | |
494 | } | |
495 | ||
496 | return FALSE; | |
497 | } | |
498 | ||
499 | /*----------------------------------------------------------*/ | |
500 | /* | |
501 | /* g_fd_copy | |
502 | /* | |
503 | /* Copy one set of fd masks to another. | |
504 | /* | |
505 | /*----------------------------------------------------------*/ | |
506 | ||
507 | g_fd_copy(nfds, source, targ) | |
508 | int nfds; | |
509 | fd_set *source, *targ; | |
510 | { | |
511 | register int i; | |
512 | register int n = howmany(nfds, NFDBITS); /* number of words for */ | |
513 | /* this many fd's */ | |
514 | ||
515 | for (i=0; i<n; i++) | |
516 | targ->fds_bits[i] = source->fds_bits[i]; | |
517 | } | |
518 | /*----------------------------------------------------------*/ | |
519 | /* | |
520 | /* g_fd_or_and_copy | |
521 | /* | |
522 | /* Or two sets of file descriptor masks together and | |
523 | /* copy to a third. Parameters are: | |
524 | /* | |
525 | /* 1) First mask count | |
526 | /* 2) Second mask count | |
527 | /* 3) pointer to first mask | |
528 | /* 4) Pointer to second mask | |
529 | /* 5) Pointer to output mask | |
530 | /* | |
531 | /*----------------------------------------------------------*/ | |
532 | ||
533 | g_fd_or_and_copy(nfds1, nfds2 , source1, source2, targ) | |
534 | int nfds1, nfds2; | |
535 | fd_set *source1, *source2, *targ; | |
536 | { | |
537 | register int i; | |
538 | fd_set *longer; /* points to whichever */ | |
539 | /* of the two masks is */ | |
540 | /* longer */ | |
541 | int tot_words = howmany(max(nfds1,nfds2), NFDBITS); | |
542 | int shared_words = howmany(min(nfds1,nfds2), NFDBITS); | |
543 | ||
544 | ||
545 | /* | |
546 | * For words which exist in both masks, or the bits together | |
547 | */ | |
548 | for (i=0; i<shared_words; i++) | |
549 | targ->fds_bits[i] = source1->fds_bits[i] | | |
550 | source2->fds_bits[i]; | |
551 | /* | |
552 | * Copy the rest of whichever is longer | |
553 | */ | |
554 | longer = (nfds1>nfds2) ? source1 : source2; | |
555 | ||
556 | while (i<tot_words) { | |
557 | targ->fds_bits[i] = longer->fds_bits[i]; | |
558 | i++; | |
559 | } | |
560 | ||
561 | return; | |
562 | } | |
563 | ||
564 | /*----------------------------------------------------------*/ | |
565 | /* | |
566 | /* g_compute_return_fds | |
567 | /* | |
568 | /* When con_select returns, the count it gives back | |
569 | /* applies only to user supplied fd's, not those | |
570 | /* relating to connections. Unfortunately, select | |
571 | /* gives back both in the masks it returns. Here we | |
572 | /* fix only the count to reflect the fact that we will be | |
573 | /* turning off bits when and if they are returned. | |
574 | /* | |
575 | /* We can assume here that the masks provided are as long | |
576 | /* as merged_nfds, which means they are at least as long | |
577 | /* as gdb_mfd. | |
578 | /* | |
579 | /*----------------------------------------------------------*/ | |
580 | ||
581 | int | |
582 | g_compute_return_fds(select_count, rfds, wfds, efds) | |
583 | int select_count; /* count of 1 bits as */ | |
584 | /* returned from select */ | |
585 | fd_set *rfds, *wfds, *efds; /* read, write, and except */ | |
586 | /* maps as returned from */ | |
587 | /* select */ | |
588 | { | |
589 | register int i; | |
590 | register int return_count = select_count; /* the value we'll return */ | |
591 | register int words; /* number of words in each */ | |
592 | /* of the connection masks */ | |
593 | ||
594 | ||
595 | /* | |
596 | * Since we can only decrement the count, there's no sense doing | |
597 | * any work if it's already 0; | |
598 | */ | |
599 | if (return_count == 0) | |
600 | return 0; | |
601 | /* | |
602 | * Figure out how many words we have to look at to get all the | |
603 | * bits covered by connection masks. | |
604 | */ | |
605 | words = howmany(gdb_mfd, NFDBITS); | |
606 | ||
607 | /* | |
608 | * For words which are involved in the connection masks, check | |
609 | * for matches and decrement the count accordingly. Stop when | |
610 | * the count hits 0 or we're out of words. | |
611 | */ | |
612 | for (i=0; i<words && (return_count>0) ; i++) { | |
613 | return_count -= g_bitcount((unsigned int) | |
614 | (gdb_crfds.fds_bits[i] & | |
615 | rfds->fds_bits[i])); | |
616 | return_count -= g_bitcount((unsigned int) | |
617 | (gdb_cwfds.fds_bits[i] & | |
618 | wfds->fds_bits[i])); | |
619 | return_count -= g_bitcount((unsigned int) | |
620 | (gdb_cefds.fds_bits[i] & | |
621 | efds->fds_bits[i])); | |
622 | } | |
623 | ||
624 | return return_count; | |
625 | } | |
626 | ||
627 | /*----------------------------------------------------------*/ | |
628 | /* | |
629 | /* g_fd_reset_conbits | |
630 | /* | |
631 | /* Given a user supplied fd bit mask and a connection | |
632 | /* related bit mask, turn off any of the connection related | |
633 | /* bits in the user mask, and copy the result to a supplied | |
634 | /* target. | |
635 | /* | |
636 | /* 1) User mask count | |
637 | /* 2) Connection mask count | |
638 | /* 3) Pointer to user mask | |
639 | /* 4) Pointer to connection mask | |
640 | /* 5) Pointer to output mask | |
641 | /* | |
642 | /* Output is always the same length as the user mask. | |
643 | /* | |
644 | /*----------------------------------------------------------*/ | |
645 | ||
646 | ||
647 | g_fd_reset_conbits(nfds, con_nfds , source, conbits, targ) | |
648 | int nfds, con_nfds; | |
649 | fd_set *source, *conbits, *targ; | |
650 | { | |
651 | register int i; | |
652 | register int tot_words = howmany(nfds, NFDBITS); /* this rtn never*/ | |
653 | /* returns a mask longer */ | |
654 | /* than nfds */ | |
655 | register int shared_words = howmany(min(nfds, con_nfds), NFDBITS); | |
656 | ||
657 | ||
658 | /* | |
659 | * For words which exist in both masks, turn off bits from conmask | |
660 | */ | |
661 | for (i=0; i<shared_words; i++) | |
662 | targ->fds_bits[i] = source->fds_bits[i] & | |
663 | ~(conbits->fds_bits[i]); | |
664 | /* | |
665 | * Copy the rest of source, if any | |
666 | */ | |
667 | if (tot_words > shared_words) | |
668 | while (i<tot_words) { | |
669 | targ->fds_bits[i] = source->fds_bits[i]; | |
670 | i++; | |
671 | } | |
672 | ||
673 | return; | |
674 | } | |
675 | ||
676 | \f | |
677 | /************************************************************************/ | |
678 | /* | |
679 | /* CONNECTION MANIPULATION | |
680 | /* | |
681 | /* Routines to control data transmission on gdb connections. | |
682 | /* | |
683 | /************************************************************************/ | |
684 | ||
685 | /*----------------------------------------------------------*/ | |
686 | /* | |
687 | /* con_select (con_select) | |
688 | /* | |
689 | /* This operation has exactly the same semantics as the select | |
690 | /* system call, except that (1) it implicitly selects all file | |
691 | /* descriptors controlled by connections, as well as those | |
692 | /* explictly specified and (2) it allows transmission and | |
693 | /* receipt to progress on all connections and (3) it considers | |
694 | /* a connection to be selected iff a transmission operation | |
695 | /* which had been pending becomes complete. One may consider | |
696 | /* that con_select turns the fd's controlled by sockets into | |
697 | /* packet streams rather than byte streams. Note also that | |
698 | /* this operation differs from a traditional select and an | |
699 | /* op_select in that it is not robust against waiting for | |
700 | /* connections with pre-completed activity. This could be | |
701 | /* added, but since it's an internal routine anyway, it seems | |
702 | /* not to be worthwhile. Also, this routine presumes that all | |
703 | /* possible progress has been made before con_select is invoked. | |
704 | /* | |
705 | /* This operation hangs in a select. If activity is | |
706 | /* discovered on any of the sockets controlled by the database | |
707 | /* library, then the corresponding input is read and | |
708 | /* appropriate processing is done. If any of the transmission | |
709 | /* operations which had been pending on one of these | |
710 | /* connections completes, then con_select may return. In | |
711 | /* fact, con_select attempts to complete any further | |
712 | /* connection related activity which can be done without | |
713 | /* blocking, but con_select never blocks AFTER a transmission | |
714 | /* operation has gone complete. | |
715 | /* | |
716 | /* If activity is detected on any of the file descriptors | |
717 | /* supplied by the user, then a count and bit fields are | |
718 | /* returned just as for select. (Activity on database sockets | |
719 | /* is never reflected in either count or bitfields.) Timeout | |
720 | /* causes a return, as with select. Upon return, the program | |
721 | /* must check for competion or termination on all of the | |
722 | /* connections in which he/she is interested, for activity on | |
723 | /* the selected file descriptors, and for timeouts, if | |
724 | /* requested, since any or all of these may be reported | |
725 | /* together. | |
726 | /* | |
727 | /* Return values for con_select: >0 same as for select, 0 time | |
728 | /* expired, -1, error in select on user fd, -2, connections | |
729 | /* have progressed but nothing else of interest. | |
730 | /* | |
731 | /* | |
732 | /*----------------------------------------------------------*/ | |
733 | ||
734 | int | |
735 | con_select(nfds, readfds, writefds, exceptfds, timeout) | |
736 | int nfds; | |
737 | fd_set *readfds, *writefds, *exceptfds; | |
738 | struct timeval *timeout; | |
739 | { | |
740 | int merged_nfds; /* the index of the last */ | |
741 | /* file desc we care about.*/ | |
742 | int select_fds; /* number of file */ | |
743 | /* returned from select */ | |
744 | /* descriptors */ | |
745 | int return_fds; /* fds count to be returned */ | |
746 | /* to the user */ | |
747 | int complete_count; /* number of connections on */ | |
748 | /* which operations have */ | |
749 | ||
750 | /* completed */ | |
751 | ||
752 | /* | |
753 | * figure out highest number file descriptor to worry about | |
754 | */ | |
755 | merged_nfds = max(nfds, gdb_mfd); /* the number we control */ | |
756 | /* or last one the user */ | |
757 | /* supplied, whichevere is */ | |
758 | /* higher */ | |
759 | /* | |
760 | * Loop waiting for activity to occur and processing it as appropriate. | |
761 | * Note that the order of the tests, calls to select, and gdb_progress | |
762 | * in this code is critical. Think it through before you change it | |
763 | * to make sure that progress is always made when possible, and that | |
764 | * returns are always made when needed. | |
765 | */ | |
766 | while (TRUE) { | |
767 | /* | |
768 | * Prepare working copies of the file descriptor maps | |
769 | * based on the ones supplied by the caller, as well as | |
770 | * all the descriptors used by connections. The latter | |
771 | * are mapped in the gdb_c?fds global variables. | |
772 | */ | |
773 | g_fd_or_and_copy(nfds,gdb_mfd,readfds,&gdb_crfds,&last_crfds); | |
774 | g_fd_or_and_copy(nfds,gdb_mfd,writefds,&gdb_cwfds,&last_cwfds); | |
775 | g_fd_or_and_copy(nfds,gdb_mfd,exceptfds,&gdb_cefds,&last_cefds); | |
776 | /* | |
777 | * Use select to wait for something to happen. Compute | |
778 | * number select would have returned if connection related | |
779 | * fd's had not been supplied. | |
780 | */ | |
781 | select_fds = select(merged_nfds, &last_crfds, &last_cwfds, &last_cefds, | |
782 | timeout); | |
783 | /* | |
784 | * There are some messy things we have to worry about here: | |
785 | * | |
786 | * 1) Select could return an error. In particular, some | |
787 | * versions of Unix will return -1 with EBADF if one | |
788 | * of the sockets has closed. We should call a | |
789 | * procedure here to see if this has happened to one | |
790 | * of ours. | |
791 | * | |
792 | * 2) Other versions of Unix will claim that there is activity | |
793 | * on our socket when in fact the other end is closed. | |
794 | * We will leave it to gdb_move_data to try the select | |
795 | * and make the appropriate decision. | |
796 | * | |
797 | * Yes folks, messy but true. If we got an error (case 1), | |
798 | * then let's see if we get the same error when we're only | |
799 | * looking at the caller's fd's. | |
800 | * | |
801 | */ | |
802 | return_fds = 0; | |
803 | if (select_fds < 0) | |
804 | if ( errno != EBADF) | |
805 | return -1; | |
806 | else { | |
807 | g_fd_or_and_copy(nfds,0,readfds,&gdb_crfds,&last_crfds); | |
808 | g_fd_or_and_copy(nfds,0,writefds,&gdb_cwfds,&last_cwfds); | |
809 | g_fd_or_and_copy(nfds,0,exceptfds,&gdb_cefds,&last_cefds); | |
810 | if (select(nfds, &last_crfds, &last_cwfds, &last_cefds, | |
811 | &gdb_notime)<0) { | |
812 | g_fd_copy(nfds, &last_crfds, readfds); | |
813 | g_fd_copy(nfds, &last_cwfds, writefds); | |
814 | g_fd_copy(nfds, &last_cefds, exceptfds); | |
815 | return -1; /* select EBADF */ | |
816 | } else { | |
817 | /* | |
818 | * We should close the connection here | |
819 | */ | |
820 | GDB_GIVEUP("con_select: EBADF on GDB controlled file.") | |
821 | } | |
822 | } | |
823 | else { | |
824 | return_fds = g_compute_return_fds(select_fds, | |
825 | &last_crfds, &last_cwfds, &last_cefds); | |
826 | } | |
827 | /* | |
828 | * If some connection related descriptors were selected, then | |
829 | * try to make progress on them. Find out if any new operations | |
830 | * could be completed. | |
831 | */ | |
832 | if (select_fds != return_fds) | |
833 | complete_count = gdb_fastprogress(); | |
834 | else | |
835 | complete_count = 0; | |
836 | /* | |
837 | * Now, based on the number of operations complete, | |
838 | * the number of user file descriptors satisfied, and | |
839 | * the possible return of a timeout from select, decide | |
840 | * whether to return to the caller. Note that timeout | |
841 | * is identified by select_fds == 0. | |
842 | */ | |
843 | if (complete_count > 0 || /* operations are complete */ | |
844 | return_fds >0 || /* user files satisfied */ | |
845 | select_fds ==0) { /* timeout in select */ | |
846 | /* | |
847 | * Connection related fd bits are never returned | |
848 | * to the caller. Reset them. The count of bits | |
849 | * was already adjusted appropriately above. I don't | |
850 | * think there's too much wasted effort in this, | |
851 | * but we should watch it if profiling indicates | |
852 | * lots of time being spent computing in con_select. | |
853 | * Put the updated bit masks in the caller supplied | |
854 | * maps. | |
855 | */ | |
856 | g_fd_reset_conbits(nfds,gdb_mfd,&last_crfds,&gdb_crfds, | |
857 | readfds); | |
858 | g_fd_reset_conbits(nfds,gdb_mfd,&last_cwfds,&gdb_cwfds, | |
859 | writefds); | |
860 | g_fd_reset_conbits(nfds,gdb_mfd,&last_cefds,&gdb_cefds, | |
861 | exceptfds); | |
862 | if (select_fds ==0) | |
863 | return 0; /* real timeout */ | |
864 | if (return_fds ==0) /* something must have */ | |
865 | /* completed, but our */ | |
866 | /* count looks like a */ | |
867 | /* timeout*/ | |
868 | return (-2); /* only connections have */ | |
869 | /* somethine complete */ | |
870 | else | |
871 | return return_fds; | |
872 | } | |
873 | } | |
874 | } |