~nexulockr-dev/nexulockr/android-tools

« back to all changes in this revision

Viewing changes to core/adb/fdevent.c

  • Committer: Ian Santopietro
  • Date: 2014-05-30 17:55:06 UTC
  • Revision ID: isantop@gmail.com-20140530175506-7irb6lx626i8d2j8
Set up proper function for all nexus devices in the Udev rule.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
 
2
**
 
3
** Copyright 2006, Brian Swetland <swetland@frotz.net>
 
4
**
 
5
** Licensed under the Apache License, Version 2.0 (the "License"); 
 
6
** you may not use this file except in compliance with the License. 
 
7
** You may obtain a copy of the License at 
 
8
**
 
9
**     http://www.apache.org/licenses/LICENSE-2.0 
 
10
**
 
11
** Unless required by applicable law or agreed to in writing, software 
 
12
** distributed under the License is distributed on an "AS IS" BASIS, 
 
13
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 
14
** See the License for the specific language governing permissions and 
 
15
** limitations under the License.
 
16
*/
 
17
 
 
18
#include <sys/ioctl.h>
 
19
 
 
20
#include <stdlib.h>
 
21
#include <stdio.h>
 
22
#include <string.h>
 
23
#include <unistd.h>
 
24
#include <errno.h>
 
25
 
 
26
#include <fcntl.h>
 
27
 
 
28
#include <stdarg.h>
 
29
#include <stddef.h>
 
30
 
 
31
#include "fdevent.h"
 
32
#include "transport.h"
 
33
#include "sysdeps.h"
 
34
 
 
35
 
 
36
/* !!! Do not enable DEBUG for the adb that will run as the server:
 
37
** both stdout and stderr are used to communicate between the client
 
38
** and server. Any extra output will cause failures.
 
39
*/
 
40
#define DEBUG 0   /* non-0 will break adb server */
 
41
 
 
42
// This socket is used when a subproc shell service exists.
 
43
// It wakes up the fdevent_loop() and cause the correct handling
 
44
// of the shell's pseudo-tty master. I.e. force close it.
 
45
int SHELL_EXIT_NOTIFY_FD = -1;
 
46
 
 
47
static void fatal(const char *fn, const char *fmt, ...)
 
48
{
 
49
    va_list ap;
 
50
    va_start(ap, fmt);
 
51
    fprintf(stderr, "%s:", fn);
 
52
    vfprintf(stderr, fmt, ap);
 
53
    va_end(ap);
 
54
    abort();
 
55
}
 
56
 
 
57
#define FATAL(x...) fatal(__FUNCTION__, x)
 
58
 
 
59
#if DEBUG
 
60
#define D(...) \
 
61
    do { \
 
62
        adb_mutex_lock(&D_lock);               \
 
63
        int save_errno = errno;                \
 
64
        fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__);  \
 
65
        errno = save_errno;                    \
 
66
        fprintf(stderr, __VA_ARGS__);          \
 
67
        adb_mutex_unlock(&D_lock);             \
 
68
        errno = save_errno;                    \
 
69
    } while(0)
 
70
static void dump_fde(fdevent *fde, const char *info)
 
71
{
 
72
    adb_mutex_lock(&D_lock);
 
73
    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
 
74
            fde->state & FDE_READ ? 'R' : ' ',
 
75
            fde->state & FDE_WRITE ? 'W' : ' ',
 
76
            fde->state & FDE_ERROR ? 'E' : ' ',
 
77
            info);
 
78
    adb_mutex_unlock(&D_lock);
 
79
}
 
80
#else
 
81
#define D(...) ((void)0)
 
82
#define dump_fde(fde, info) do { } while(0)
 
83
#endif
 
84
 
 
85
#define FDE_EVENTMASK  0x00ff
 
86
#define FDE_STATEMASK  0xff00
 
87
 
 
88
#define FDE_ACTIVE     0x0100
 
89
#define FDE_PENDING    0x0200
 
90
#define FDE_CREATED    0x0400
 
91
 
 
92
static void fdevent_plist_enqueue(fdevent *node);
 
93
static void fdevent_plist_remove(fdevent *node);
 
94
static fdevent *fdevent_plist_dequeue(void);
 
95
static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
 
96
 
 
97
static fdevent list_pending = {
 
98
    .next = &list_pending,
 
99
    .prev = &list_pending,
 
100
};
 
101
 
 
102
static fdevent **fd_table = 0;
 
103
static int fd_table_max = 0;
 
104
 
 
105
#ifdef CRAPTASTIC
 
106
//HAVE_EPOLL
 
107
 
 
108
#include <sys/epoll.h>
 
109
 
 
110
static int epoll_fd = -1;
 
111
 
 
112
static void fdevent_init()
 
113
{
 
114
        /* XXX: what's a good size for the passed in hint? */
 
115
    epoll_fd = epoll_create(256);
 
116
 
 
117
    if(epoll_fd < 0) {
 
118
        perror("epoll_create() failed");
 
119
        exit(1);
 
120
    }
 
121
 
 
122
        /* mark for close-on-exec */
 
123
    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
 
124
}
 
125
 
 
126
static void fdevent_connect(fdevent *fde)
 
127
{
 
128
    struct epoll_event ev;
 
129
 
 
130
    memset(&ev, 0, sizeof(ev));
 
131
    ev.events = 0;
 
132
    ev.data.ptr = fde;
 
133
 
 
134
#if 0
 
135
    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
 
136
        perror("epoll_ctl() failed\n");
 
137
        exit(1);
 
138
    }
 
139
#endif
 
140
}
 
141
 
 
142
static void fdevent_disconnect(fdevent *fde)
 
143
{
 
144
    struct epoll_event ev;
 
145
 
 
146
    memset(&ev, 0, sizeof(ev));
 
147
    ev.events = 0;
 
148
    ev.data.ptr = fde;
 
149
 
 
150
        /* technically we only need to delete if we
 
151
        ** were actively monitoring events, but let's
 
152
        ** be aggressive and do it anyway, just in case
 
153
        ** something's out of sync
 
154
        */
 
155
    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
 
156
}
 
157
 
 
158
static void fdevent_update(fdevent *fde, unsigned events)
 
159
{
 
160
    struct epoll_event ev;
 
161
    int active;
 
162
 
 
163
    active = (fde->state & FDE_EVENTMASK) != 0;
 
164
 
 
165
    memset(&ev, 0, sizeof(ev));
 
166
    ev.events = 0;
 
167
    ev.data.ptr = fde;
 
168
 
 
169
    if(events & FDE_READ) ev.events |= EPOLLIN;
 
170
    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
 
171
    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
 
172
 
 
173
    fde->state = (fde->state & FDE_STATEMASK) | events;
 
174
 
 
175
    if(active) {
 
176
            /* we're already active. if we're changing to *no*
 
177
            ** events being monitored, we need to delete, otherwise
 
178
            ** we need to just modify
 
179
            */
 
180
        if(ev.events) {
 
181
            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
 
182
                perror("epoll_ctl() failed\n");
 
183
                exit(1);
 
184
            }
 
185
        } else {
 
186
            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
 
187
                perror("epoll_ctl() failed\n");
 
188
                exit(1);
 
189
            }
 
190
        }
 
191
    } else {
 
192
            /* we're not active.  if we're watching events, we need
 
193
            ** to add, otherwise we can just do nothing
 
194
            */
 
195
        if(ev.events) {
 
196
            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
 
197
                perror("epoll_ctl() failed\n");
 
198
                exit(1);
 
199
            }
 
200
        }
 
201
    }
 
202
}
 
203
 
 
204
static void fdevent_process()
 
205
{
 
206
    struct epoll_event events[256];
 
207
    fdevent *fde;
 
208
    int i, n;
 
209
 
 
210
    n = epoll_wait(epoll_fd, events, 256, -1);
 
211
 
 
212
    if(n < 0) {
 
213
        if(errno == EINTR) return;
 
214
        perror("epoll_wait");
 
215
        exit(1);
 
216
    }
 
217
 
 
218
    for(i = 0; i < n; i++) {
 
219
        struct epoll_event *ev = events + i;
 
220
        fde = ev->data.ptr;
 
221
 
 
222
        if(ev->events & EPOLLIN) {
 
223
            fde->events |= FDE_READ;
 
224
        }
 
225
        if(ev->events & EPOLLOUT) {
 
226
            fde->events |= FDE_WRITE;
 
227
        }
 
228
        if(ev->events & (EPOLLERR | EPOLLHUP)) {
 
229
            fde->events |= FDE_ERROR;
 
230
        }
 
231
        if(fde->events) {
 
232
            if(fde->state & FDE_PENDING) continue;
 
233
            fde->state |= FDE_PENDING;
 
234
            fdevent_plist_enqueue(fde);
 
235
        }
 
236
    }
 
237
}
 
238
 
 
239
#else /* USE_SELECT */
 
240
 
 
241
#ifdef HAVE_WINSOCK
 
242
#include <winsock2.h>
 
243
#else
 
244
#include <sys/select.h>
 
245
#endif
 
246
 
 
247
static fd_set read_fds;
 
248
static fd_set write_fds;
 
249
static fd_set error_fds;
 
250
 
 
251
static int select_n = 0;
 
252
 
 
253
static void fdevent_init(void)
 
254
{
 
255
    FD_ZERO(&read_fds);
 
256
    FD_ZERO(&write_fds);
 
257
    FD_ZERO(&error_fds);
 
258
}
 
259
 
 
260
static void fdevent_connect(fdevent *fde)
 
261
{
 
262
    if(fde->fd >= select_n) {
 
263
        select_n = fde->fd + 1;
 
264
    }
 
265
}
 
266
 
 
267
static void fdevent_disconnect(fdevent *fde)
 
268
{
 
269
    int i, n;
 
270
 
 
271
    FD_CLR(fde->fd, &read_fds);
 
272
    FD_CLR(fde->fd, &write_fds);
 
273
    FD_CLR(fde->fd, &error_fds);
 
274
 
 
275
    for(n = 0, i = 0; i < select_n; i++) {
 
276
        if(fd_table[i] != 0) n = i;
 
277
    }
 
278
    select_n = n + 1;
 
279
}
 
280
 
 
281
static void fdevent_update(fdevent *fde, unsigned events)
 
282
{
 
283
    if(events & FDE_READ) {
 
284
        FD_SET(fde->fd, &read_fds);
 
285
    } else {
 
286
        FD_CLR(fde->fd, &read_fds);
 
287
    }
 
288
    if(events & FDE_WRITE) {
 
289
        FD_SET(fde->fd, &write_fds);
 
290
    } else {
 
291
        FD_CLR(fde->fd, &write_fds);
 
292
    }
 
293
    if(events & FDE_ERROR) {
 
294
        FD_SET(fde->fd, &error_fds);
 
295
    } else {
 
296
        FD_CLR(fde->fd, &error_fds);
 
297
    }
 
298
 
 
299
    fde->state = (fde->state & FDE_STATEMASK) | events;
 
300
}
 
301
 
 
302
/* Looks at fd_table[] for bad FDs and sets bit in fds.
 
303
** Returns the number of bad FDs.
 
304
*/
 
305
static int fdevent_fd_check(fd_set *fds)
 
306
{
 
307
    int i, n = 0;
 
308
    fdevent *fde;
 
309
 
 
310
    for(i = 0; i < select_n; i++) {
 
311
        fde = fd_table[i];
 
312
        if(fde == 0) continue;
 
313
        if(fcntl(i, F_GETFL, NULL) < 0) {
 
314
            FD_SET(i, fds);
 
315
            n++;
 
316
            // fde->state |= FDE_DONT_CLOSE;
 
317
 
 
318
        }
 
319
    }
 
320
    return n;
 
321
}
 
322
 
 
323
#if !DEBUG
 
324
static inline void dump_all_fds(const char *extra_msg) {}
 
325
#else
 
326
static void dump_all_fds(const char *extra_msg)
 
327
{
 
328
int i;
 
329
    fdevent *fde;
 
330
    // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
 
331
    char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
 
332
    size_t max_chars = FD_SETSIZE * 6 + 1;
 
333
    int printed_out;
 
334
#define SAFE_SPRINTF(...)                                                    \
 
335
    do {                                                                     \
 
336
        printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
 
337
        if (printed_out <= 0) {                                              \
 
338
            D("... snprintf failed.\n");                                     \
 
339
            return;                                                          \
 
340
        }                                                                    \
 
341
        if (max_chars < (unsigned int)printed_out) {                         \
 
342
            D("... snprintf out of space.\n");                               \
 
343
            return;                                                          \
 
344
        }                                                                    \
 
345
        pb += printed_out;                                                   \
 
346
        max_chars -= printed_out;                                            \
 
347
    } while(0)
 
348
 
 
349
    for(i = 0; i < select_n; i++) {
 
350
        fde = fd_table[i];
 
351
        SAFE_SPRINTF("%d", i);
 
352
        if(fde == 0) {
 
353
            SAFE_SPRINTF("? ");
 
354
            continue;
 
355
        }
 
356
        if(fcntl(i, F_GETFL, NULL) < 0) {
 
357
            SAFE_SPRINTF("b");
 
358
        }
 
359
        SAFE_SPRINTF(" ");
 
360
    }
 
361
    D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
 
362
}
 
363
#endif
 
364
 
 
365
static void fdevent_process()
 
366
{
 
367
    int i, n;
 
368
    fdevent *fde;
 
369
    unsigned events;
 
370
    fd_set rfd, wfd, efd;
 
371
 
 
372
    memcpy(&rfd, &read_fds, sizeof(fd_set));
 
373
    memcpy(&wfd, &write_fds, sizeof(fd_set));
 
374
    memcpy(&efd, &error_fds, sizeof(fd_set));
 
375
 
 
376
    dump_all_fds("pre select()");
 
377
 
 
378
    n = select(select_n, &rfd, &wfd, &efd, NULL);
 
379
    int saved_errno = errno;
 
380
    D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
 
381
 
 
382
    dump_all_fds("post select()");
 
383
 
 
384
    if(n < 0) {
 
385
        switch(saved_errno) {
 
386
        case EINTR: return;
 
387
        case EBADF:
 
388
            // Can't trust the FD sets after an error.
 
389
            FD_ZERO(&wfd);
 
390
            FD_ZERO(&efd);
 
391
            FD_ZERO(&rfd);
 
392
            break;
 
393
        default:
 
394
            D("Unexpected select() error=%d\n", saved_errno);
 
395
            return;
 
396
        }
 
397
    }
 
398
    if(n <= 0) {
 
399
        // We fake a read, as the rest of the code assumes
 
400
        // that errors will be detected at that point.
 
401
        n = fdevent_fd_check(&rfd);
 
402
    }
 
403
 
 
404
    for(i = 0; (i < select_n) && (n > 0); i++) {
 
405
        events = 0;
 
406
        if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
 
407
        if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
 
408
        if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
 
409
 
 
410
        if(events) {
 
411
            fde = fd_table[i];
 
412
            if(fde == 0)
 
413
              FATAL("missing fde for fd %d\n", i);
 
414
 
 
415
            fde->events |= events;
 
416
 
 
417
            D("got events fde->fd=%d events=%04x, state=%04x\n",
 
418
                fde->fd, fde->events, fde->state);
 
419
            if(fde->state & FDE_PENDING) continue;
 
420
            fde->state |= FDE_PENDING;
 
421
            fdevent_plist_enqueue(fde);
 
422
        }
 
423
    }
 
424
}
 
425
 
 
426
#endif
 
427
 
 
428
static void fdevent_register(fdevent *fde)
 
429
{
 
430
    if(fde->fd < 0) {
 
431
        FATAL("bogus negative fd (%d)\n", fde->fd);
 
432
    }
 
433
 
 
434
    if(fde->fd >= fd_table_max) {
 
435
        int oldmax = fd_table_max;
 
436
        if(fde->fd > 32000) {
 
437
            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
 
438
        }
 
439
        if(fd_table_max == 0) {
 
440
            fdevent_init();
 
441
            fd_table_max = 256;
 
442
        }
 
443
        while(fd_table_max <= fde->fd) {
 
444
            fd_table_max *= 2;
 
445
        }
 
446
        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
 
447
        if(fd_table == 0) {
 
448
            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
 
449
        }
 
450
        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
 
451
    }
 
452
 
 
453
    fd_table[fde->fd] = fde;
 
454
}
 
455
 
 
456
static void fdevent_unregister(fdevent *fde)
 
457
{
 
458
    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
 
459
        FATAL("fd out of range (%d)\n", fde->fd);
 
460
    }
 
461
 
 
462
    if(fd_table[fde->fd] != fde) {
 
463
        FATAL("fd_table out of sync [%d]\n", fde->fd);
 
464
    }
 
465
 
 
466
    fd_table[fde->fd] = 0;
 
467
 
 
468
    if(!(fde->state & FDE_DONT_CLOSE)) {
 
469
        dump_fde(fde, "close");
 
470
        adb_close(fde->fd);
 
471
    }
 
472
}
 
473
 
 
474
static void fdevent_plist_enqueue(fdevent *node)
 
475
{
 
476
    fdevent *list = &list_pending;
 
477
 
 
478
    node->next = list;
 
479
    node->prev = list->prev;
 
480
    node->prev->next = node;
 
481
    list->prev = node;
 
482
}
 
483
 
 
484
static void fdevent_plist_remove(fdevent *node)
 
485
{
 
486
    node->prev->next = node->next;
 
487
    node->next->prev = node->prev;
 
488
    node->next = 0;
 
489
    node->prev = 0;
 
490
}
 
491
 
 
492
static fdevent *fdevent_plist_dequeue(void)
 
493
{
 
494
    fdevent *list = &list_pending;
 
495
    fdevent *node = list->next;
 
496
 
 
497
    if(node == list) return 0;
 
498
 
 
499
    list->next = node->next;
 
500
    list->next->prev = list;
 
501
    node->next = 0;
 
502
    node->prev = 0;
 
503
 
 
504
    return node;
 
505
}
 
506
 
 
507
static void fdevent_call_fdfunc(fdevent* fde)
 
508
{
 
509
    unsigned events = fde->events;
 
510
    fde->events = 0;
 
511
    if(!(fde->state & FDE_PENDING)) return;
 
512
    fde->state &= (~FDE_PENDING);
 
513
    dump_fde(fde, "callback");
 
514
    fde->func(fde->fd, events, fde->arg);
 
515
}
 
516
 
 
517
static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
 
518
{
 
519
 
 
520
    D("subproc handling on fd=%d ev=%04x\n", fd, ev);
 
521
 
 
522
    // Hook oneself back into the fde's suitable for select() on read.
 
523
    if((fd < 0) || (fd >= fd_table_max)) {
 
524
        FATAL("fd %d out of range for fd_table \n", fd);
 
525
    }
 
526
    fdevent *fde = fd_table[fd];
 
527
    fdevent_add(fde, FDE_READ);
 
528
 
 
529
    if(ev & FDE_READ){
 
530
      int subproc_fd;
 
531
 
 
532
      if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
 
533
          FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
 
534
      }
 
535
      if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
 
536
          D("subproc_fd %d out of range 0, fd_table_max=%d\n",
 
537
            subproc_fd, fd_table_max);
 
538
          return;
 
539
      }
 
540
      fdevent *subproc_fde = fd_table[subproc_fd];
 
541
      if(!subproc_fde) {
 
542
          D("subproc_fd %d cleared from fd_table\n", subproc_fd);
 
543
          return;
 
544
      }
 
545
      if(subproc_fde->fd != subproc_fd) {
 
546
          // Already reallocated?
 
547
          D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
 
548
          return;
 
549
      }
 
550
 
 
551
      subproc_fde->force_eof = 1;
 
552
 
 
553
      int rcount = 0;
 
554
      ioctl(subproc_fd, FIONREAD, &rcount);
 
555
      D("subproc with fd=%d  has rcount=%d err=%d\n",
 
556
        subproc_fd, rcount, errno);
 
557
 
 
558
      if(rcount) {
 
559
        // If there is data left, it will show up in the select().
 
560
        // This works because there is no other thread reading that
 
561
        // data when in this fd_func().
 
562
        return;
 
563
      }
 
564
 
 
565
      D("subproc_fde.state=%04x\n", subproc_fde->state);
 
566
      subproc_fde->events |= FDE_READ;
 
567
      if(subproc_fde->state & FDE_PENDING) {
 
568
        return;
 
569
      }
 
570
      subproc_fde->state |= FDE_PENDING;
 
571
      fdevent_call_fdfunc(subproc_fde);
 
572
    }
 
573
}
 
574
 
 
575
fdevent *fdevent_create(int fd, fd_func func, void *arg)
 
576
{
 
577
    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
 
578
    if(fde == 0) return 0;
 
579
    fdevent_install(fde, fd, func, arg);
 
580
    fde->state |= FDE_CREATED;
 
581
    return fde;
 
582
}
 
583
 
 
584
void fdevent_destroy(fdevent *fde)
 
585
{
 
586
    if(fde == 0) return;
 
587
    if(!(fde->state & FDE_CREATED)) {
 
588
        FATAL("fde %p not created by fdevent_create()\n", fde);
 
589
    }
 
590
    fdevent_remove(fde);
 
591
}
 
592
 
 
593
void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
 
594
{
 
595
    memset(fde, 0, sizeof(fdevent));
 
596
    fde->state = FDE_ACTIVE;
 
597
    fde->fd = fd;
 
598
    fde->force_eof = 0;
 
599
    fde->func = func;
 
600
    fde->arg = arg;
 
601
 
 
602
#ifndef HAVE_WINSOCK
 
603
    fcntl(fd, F_SETFL, O_NONBLOCK);
 
604
#endif
 
605
    fdevent_register(fde);
 
606
    dump_fde(fde, "connect");
 
607
    fdevent_connect(fde);
 
608
    fde->state |= FDE_ACTIVE;
 
609
}
 
610
 
 
611
void fdevent_remove(fdevent *fde)
 
612
{
 
613
    if(fde->state & FDE_PENDING) {
 
614
        fdevent_plist_remove(fde);
 
615
    }
 
616
 
 
617
    if(fde->state & FDE_ACTIVE) {
 
618
        fdevent_disconnect(fde);
 
619
        dump_fde(fde, "disconnect");
 
620
        fdevent_unregister(fde);
 
621
    }
 
622
 
 
623
    fde->state = 0;
 
624
    fde->events = 0;
 
625
}
 
626
 
 
627
 
 
628
void fdevent_set(fdevent *fde, unsigned events)
 
629
{
 
630
    events &= FDE_EVENTMASK;
 
631
 
 
632
    if((fde->state & FDE_EVENTMASK) == events) return;
 
633
 
 
634
    if(fde->state & FDE_ACTIVE) {
 
635
        fdevent_update(fde, events);
 
636
        dump_fde(fde, "update");
 
637
    }
 
638
 
 
639
    fde->state = (fde->state & FDE_STATEMASK) | events;
 
640
 
 
641
    if(fde->state & FDE_PENDING) {
 
642
            /* if we're pending, make sure
 
643
            ** we don't signal an event that
 
644
            ** is no longer wanted.
 
645
            */
 
646
        fde->events &= (~events);
 
647
        if(fde->events == 0) {
 
648
            fdevent_plist_remove(fde);
 
649
            fde->state &= (~FDE_PENDING);
 
650
        }
 
651
    }
 
652
}
 
653
 
 
654
void fdevent_add(fdevent *fde, unsigned events)
 
655
{
 
656
    fdevent_set(
 
657
        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
 
658
}
 
659
 
 
660
void fdevent_del(fdevent *fde, unsigned events)
 
661
{
 
662
    fdevent_set(
 
663
        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
 
664
}
 
665
 
 
666
void fdevent_subproc_setup()
 
667
{
 
668
    int s[2];
 
669
 
 
670
    if(adb_socketpair(s)) {
 
671
        FATAL("cannot create shell-exit socket-pair\n");
 
672
    }
 
673
    SHELL_EXIT_NOTIFY_FD = s[0];
 
674
    fdevent *fde;
 
675
    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
 
676
    if(!fde)
 
677
      FATAL("cannot create fdevent for shell-exit handler\n");
 
678
    fdevent_add(fde, FDE_READ);
 
679
}
 
680
 
 
681
void fdevent_loop()
 
682
{
 
683
    fdevent *fde;
 
684
    fdevent_subproc_setup();
 
685
 
 
686
    for(;;) {
 
687
        D("--- ---- waiting for events\n");
 
688
 
 
689
        fdevent_process();
 
690
 
 
691
        while((fde = fdevent_plist_dequeue())) {
 
692
            fdevent_call_fdfunc(fde);
 
693
        }
 
694
    }
 
695
}