OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [lib/] [select.c] - Blame information for rev 1254

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      lib/select.c
4
//
5
//      'select()' system call
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  eCos implementation of 'select()' system call
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
#include <sys/param.h>
33
#include <cyg/io/file.h>
34
#include <cyg/kernel/kapi.h>
35
#include <sys/select.h>
36
#include <sys/bsdselect.h>
37
 
38
static cyg_flag_t select_flag;
39
static cyg_bool   select_flag_init = false;
40
#define SELECT_WAKE  0x01
41
#define SELECT_ABORT 0x02
42
 
43
//
44
// Private function which does all the work for 'select()'
45
//
46
static int
47
_cyg_select(int nfd, fd_set *in, fd_set *out, fd_set *ex,
48
            struct timeval *tv, cyg_bool_t abortable)
49
{
50
    int fd, mode, num, ticks;
51
    struct file *fp;
52
    fd_set in_res, out_res, ex_res;  // Result sets
53
    fd_set *selection[3], *result[3];
54
    cyg_tick_count_t now, then;
55
    int mode_type[] = {FREAD, FWRITE, 0};
56
    cyg_flag_value_t flag, wait_flag;
57
 
58
    // Note: since this is called by application programs, it needs no protection
59
    if (!select_flag_init) {
60
        select_flag_init = true;
61
        cyg_flag_init(&select_flag);
62
    }
63
    wait_flag = SELECT_WAKE;
64
    if (abortable) wait_flag |= SELECT_ABORT;
65
    FD_ZERO(&in_res);
66
    FD_ZERO(&out_res);
67
    FD_ZERO(&ex_res);
68
    // Set up sets
69
    selection[0] = in;   result[0] = &in_res;
70
    selection[1] = out;  result[1] = &out_res;
71
    selection[2] = ex;   result[2] = &ex_res;
72
    // Compute end time
73
    if (tv) {
74
        now = cyg_current_time();
75
        ticks = (tv->tv_sec * 100) + (tv->tv_usec / 10000);
76
        then = now + ticks;
77
    } else {
78
        then = 0;  // Compiler warnings :-(
79
        ticks = 0;
80
    }
81
    // Scan sets for possible I/O until something found, timeout or error.
82
    while (true) {
83
        num = 0;  // Total file descriptors "ready"
84
 
85
        cyg_scheduler_lock(); // Scan the list atomically wrt electing to sleep
86
 
87
        for (mode = 0;  mode < 3;  mode++) {
88
            if (selection[mode]) {
89
                for (fd = 0;  fd < nfd;  fd++) {
90
                    if (FD_ISSET(fd, selection[mode])) {
91
                        if (getfp(fd, &fp)) {
92
                            cyg_scheduler_unlock(); // return.
93
                            errno = EBADF;
94
                            return -1;
95
                        }
96
                        if ((*fp->f_ops->fo_select)(fp, mode_type[mode])) {
97
                            FD_SET(fd, result[mode]);
98
                            num++;
99
                        }
100
                    }
101
                }
102
            }
103
        }
104
        if (num) {
105
 
106
            cyg_scheduler_unlock(); // Happy, about to return.
107
 
108
            // Found something, update user's sets
109
            if (in) {
110
                memcpy(in, &in_res, sizeof(in_res));
111
            }
112
            if (out) {
113
                memcpy(out, &out_res, sizeof(out_res));
114
            }
115
            if (ex) {
116
                memcpy(ex, &ex_res, sizeof(ex_res));
117
            }
118
            return num;
119
        }
120
        // Nothing found, see if we want to wait
121
        if (tv) {
122
            if (ticks == 0) {
123
                // Special case of "poll"
124
                cyg_scheduler_unlock(); // About to return.
125
                return 0;
126
            }
127
            flag = cyg_flag_timed_wait(&select_flag, wait_flag,
128
                                       CYG_FLAG_WAITMODE_OR,
129
                                       then);
130
        } else {
131
            // Wait forever (until something happens)
132
            flag = cyg_flag_wait(&select_flag, wait_flag,
133
                                 CYG_FLAG_WAITMODE_OR);
134
        }
135
 
136
        cyg_scheduler_unlock(); // waited atomically
137
 
138
        if (flag & SELECT_ABORT) {
139
            errno = EINTR;
140
            return -1;
141
        }
142
        if (!flag) {
143
            return 0; // meaning no activity, ergo timeout occurred
144
        }
145
    }
146
    errno = ENOSYS;
147
    return -1;
148
}
149
 
150
//
151
// This function is called by the lower layers to record the
152
// fact that a particular 'select' event is being requested.
153
//
154
void
155
selrecord(void *selector, struct selinfo *info)
156
{
157
    // Unused by this implementation
158
}
159
 
160
//
161
// This function is called to indicate that a 'select' event
162
// may have occurred.
163
//
164
void
165
selwakeup(struct selinfo *info)
166
{
167
    // Need these ops to be atomic to make sure the clear occurs -
168
    // otherwise a higher prio thread could hog the CPU when its fds are
169
    // not ready, but the flag is (already) set, or set for someone else.
170
    cyg_scheduler_lock();
171
    cyg_flag_setbits(&select_flag, SELECT_WAKE);
172
    cyg_flag_maskbits(&select_flag,    0      ); // clear all
173
    cyg_scheduler_unlock();
174
}
175
 
176
//
177
// The public function used by 'normal' programs.  This interface does not allow
178
// the 'select()' to be externally interrupted.
179
//
180
int
181
select(int nfd, fd_set *in, fd_set *out, fd_set *ex,
182
       struct timeval *tv)
183
{
184
    return _cyg_select(nfd, in, out, ex, tv, false);
185
}
186
 
187
//
188
// The public function used by programs which wish to allow interruption,
189
// using the 'cyg_select_abort()' function below.
190
//
191
int
192
cyg_select_with_abort(int nfd, fd_set *in, fd_set *out, fd_set *ex,
193
                      struct timeval *tv)
194
{
195
    return _cyg_select(nfd, in, out, ex, tv, true);
196
}
197
 
198
//
199
// This function can be called by the user to forceably abort any
200
// current selects.
201
//
202
void
203
cyg_select_abort(void)
204
{
205
    // See comments in selwakeup()...
206
    cyg_scheduler_lock();
207
    cyg_flag_setbits(&select_flag, SELECT_ABORT);
208
    cyg_flag_maskbits(&select_flag,    0       );
209
    cyg_scheduler_unlock();
210
}
211
 
212
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.