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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [fileio/] [v2_0/] [src/] [fd.cxx] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      fd.cxx
4
//
5
//      Fileio file descriptor implementation
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):           nickg
44
// Contributors:        nickg
45
// Date:                2000-05-25
46
// Purpose:             Fileio file descriptor implementation
47
// Description:         This file contains the implementation of the file
48
//                      descriptor functions.
49
//              
50
//              
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include <pkgconf/hal.h>
57
#include <pkgconf/kernel.h>
58
#include <pkgconf/io_fileio.h>
59
 
60
#include <cyg/kernel/ktypes.h>         // base kernel types
61
#include <cyg/infra/cyg_trac.h>        // tracing macros
62
#include <cyg/infra/cyg_ass.h>         // assertion macros
63
 
64
#include "fio.h"                       // Private header
65
 
66
//-----------------------------------------------------------------------------
67
// File data structures
68
 
69
#ifdef CYGPKG_KERNEL
70
// Mutex for controlling access to file desriptor arrays
71
Cyg_Mutex fdlock CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
72
 
73
// Array of per-file mutexes
74
static Cyg_Mutex file_lock[CYGNUM_FILEIO_NFILE] \
75
    CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
76
#endif // ifdef CYGPKG_KERNEL
77
 
78
// Array of open file objects
79
static cyg_file file[CYGNUM_FILEIO_NFILE];
80
 
81
// Descriptor array
82
static cyg_file *desc[CYGNUM_FILEIO_NFD];
83
 
84
#define FD_ALLOCATED ((cyg_file *)1)
85
 
86
//==========================================================================
87
// Initialization
88
 
89
__externC void cyg_fd_init()
90
{
91
    int i;
92
 
93
    for( i = 0; i < CYGNUM_FILEIO_NFILE; i++ )
94
        file[i].f_flag = 0;
95
 
96
    for( i = 0; i < CYGNUM_FILEIO_NFD; i++ )
97
        desc[i] = NULL;
98
}
99
 
100
//==========================================================================
101
// File object allocation 
102
 
103
//--------------------------------------------------------------------------
104
// Locate and allocate a free file object.
105
 
106
__externC cyg_file *cyg_file_alloc()
107
{
108
    int i;
109
    cyg_file *fp = NULL;
110
 
111
    FILEIO_MUTEX_LOCK(fdlock);
112
 
113
    for( i = 0; i < CYGNUM_FILEIO_NFILE; i++ )
114
    {
115
        if( (file[i].f_flag & CYG_FALLOC) == 0 )
116
        {
117
            fp = &file[i];
118
            fp->f_flag = CYG_FALLOC;
119
            fp->f_ucount = 0;
120
            break;
121
        }
122
    }
123
 
124
    FILEIO_MUTEX_UNLOCK(fdlock);
125
 
126
    return fp;
127
}
128
 
129
//--------------------------------------------------------------------------
130
// Free a file object. This is a straightforward freeing, usually used
131
// during error recovery. File objects are normally freed as a side
132
// effect of cyg_fd_assign() or cyg_fd_free().
133
 
134
__externC void cyg_file_free(cyg_file * fp)
135
{
136
    FILEIO_MUTEX_LOCK(fdlock);
137
 
138
    fp->f_flag = 0;
139
 
140
    FILEIO_MUTEX_UNLOCK(fdlock);
141
}
142
 
143
//==========================================================================
144
// Internal routines for handling descriptor deallocation
145
// These must all be called with the fdlock already locked.
146
 
147
//--------------------------------------------------------------------------
148
// Decrement the use count on a file object and if it goes to zero,
149
// close the file and deallocate the file object.
150
 
151
static int fp_ucount_dec( cyg_file *fp )
152
{
153
    int error = 0;
154
    if( (--fp->f_ucount) <= 0 )
155
    {
156
        cyg_file_lock( fp, fp->f_syncmode );
157
 
158
        error = fp->f_ops->fo_close(fp);
159
 
160
        cyg_file_unlock( fp, fp->f_syncmode );
161
 
162
        if( error == 0 )
163
            fp->f_flag = 0;
164
    }
165
 
166
    return error;
167
}
168
 
169
//--------------------------------------------------------------------------
170
// Clear out a descriptor. If this is the last reference to the file
171
// object, then that will be closed and deallocated.
172
 
173
static int fd_close( int fd )
174
{
175
    int error = 0;
176
    cyg_file *fp = desc[fd];
177
 
178
    if( fp != FD_ALLOCATED && fp != NULL)
179
    {
180
        // The descriptor is occupied, decrement its usecount and
181
        // close the file if it goes zero.
182
 
183
        error = fp_ucount_dec( fp );
184
    }
185
 
186
    desc[fd] = FD_ALLOCATED;
187
 
188
    return error;
189
}
190
 
191
 
192
//==========================================================================
193
// File descriptor allocation
194
 
195
//--------------------------------------------------------------------------
196
// Allocate a file descriptor. The allocated descriptor is set to the value
197
// FD_ALLOCATED to prevent it being reallocated by another thread.
198
 
199
__externC int cyg_fd_alloc(int low)
200
{
201
    int fd;
202
 
203
    FILEIO_MUTEX_LOCK(fdlock);
204
 
205
    for( fd = low; fd < CYGNUM_FILEIO_NFD; fd++ )
206
    {
207
        if( desc[fd] == NULL )
208
        {
209
            desc[fd] = FD_ALLOCATED;
210
            FILEIO_MUTEX_UNLOCK(fdlock);
211
            return fd;
212
        }
213
    }
214
 
215
    FILEIO_MUTEX_UNLOCK(fdlock);
216
 
217
    return -1;
218
}
219
 
220
//--------------------------------------------------------------------------
221
// Assign a file object to a descriptor. If the descriptor is already
222
// occupied, the occupying files usecount is decrement and it may be
223
// closed.
224
 
225
__externC void cyg_fd_assign(int fd, cyg_file *fp)
226
{
227
    FILEIO_MUTEX_LOCK(fdlock);
228
 
229
    fd_close( fd );
230
 
231
    fp->f_ucount++;
232
    desc[fd] = fp;
233
 
234
    FILEIO_MUTEX_UNLOCK(fdlock);
235
}
236
 
237
//--------------------------------------------------------------------------
238
// Free a descriptor. Any occupying files usecount is decremented and
239
// it may be closed.
240
 
241
__externC int cyg_fd_free(int fd)
242
{
243
    int error;
244
 
245
    FILEIO_MUTEX_LOCK(fdlock);
246
 
247
    error = fd_close( fd );
248
 
249
    desc[fd] = NULL;
250
 
251
    FILEIO_MUTEX_UNLOCK(fdlock);
252
 
253
    return error;
254
}
255
 
256
//==========================================================================
257
// Descriptor to file object mapping
258
 
259
 
260
//--------------------------------------------------------------------------
261
// Map a descriptor to a file object. This is just a straightforward index
262
// into the descriptor array complicated by the need to lock the mutex and
263
// increment the usecount.
264
 
265
__externC cyg_file *cyg_fp_get( int fd )
266
{
267
    FILEIO_MUTEX_LOCK(fdlock);
268
 
269
    cyg_file *fp = desc[fd];
270
 
271
    if( fp != FD_ALLOCATED && fp != NULL)
272
    {
273
        // Increment use count while we work on this file
274
 
275
        fp->f_ucount++;
276
    }
277
    else fp = NULL;
278
 
279
    FILEIO_MUTEX_UNLOCK(fdlock);
280
 
281
    return fp;
282
}
283
 
284
//--------------------------------------------------------------------------
285
// Free the usecount reference we acquired in cyg_fp_get(). If the usecount
286
// is zeroed, the file will be closed.
287
 
288
__externC void cyg_fp_free( cyg_file *fp )
289
{
290
    FILEIO_MUTEX_LOCK(fdlock);
291
 
292
    fp_ucount_dec( fp );
293
 
294
    FILEIO_MUTEX_UNLOCK(fdlock);
295
}
296
 
297
//==========================================================================
298
// File locking protocol
299
 
300
void cyg_file_lock( cyg_file *fp , cyg_uint32 syncmode )
301
{
302
    cyg_fs_lock( fp->f_mte, syncmode>>CYG_SYNCMODE_IO_SHIFT);
303
 
304
    if( syncmode & CYG_SYNCMODE_IO_FILE )
305
    {
306
        fp->f_flag |= CYG_FLOCKED;
307
        FILEIO_MUTEX_LOCK(file_lock[fp-&file[0]]);
308
    }
309
}
310
 
311
void cyg_file_unlock( cyg_file *fp, cyg_uint32 syncmode )
312
{
313
    cyg_fs_unlock( fp->f_mte, syncmode>>CYG_SYNCMODE_IO_SHIFT);
314
 
315
    if( syncmode & CYG_SYNCMODE_IO_FILE )
316
    {
317
        fp->f_flag &= ~CYG_FLOCKED;
318
        FILEIO_MUTEX_UNLOCK(file_lock[fp-&file[0]]);
319
    }
320
}
321
 
322
 
323
//==========================================================================
324
// POSIX API routines
325
 
326
//--------------------------------------------------------------------------
327
// dup() - duplicate an FD into a random descriptor
328
 
329
__externC int dup( int fd )
330
{
331
    cyg_file *fp = cyg_fp_get( fd );
332
 
333
    if( fp == NULL )
334
    {
335
        errno = EBADF;
336
        return -1;
337
    }
338
 
339
    int fd2 = cyg_fd_alloc(0);
340
 
341
    if( fd2 == -1 )
342
    {
343
        errno = EMFILE;
344
        return -1;
345
    }
346
 
347
    cyg_fd_assign( fd2, fp );
348
 
349
    cyg_fp_free(fp);
350
 
351
    return fd2;
352
}
353
 
354
//--------------------------------------------------------------------------
355
// dup2() - duplicate an FD into a chosen descriptor
356
 
357
__externC int dup2( int fd, int fd2 )
358
{
359
    if( fd2 == fd ) return fd2;
360
 
361
    if( fd2 < 0 || fd2 >= OPEN_MAX )
362
    {
363
        errno = EBADF;
364
        return -1;
365
    }
366
 
367
    cyg_file *fp = cyg_fp_get( fd );
368
 
369
    if( fp == NULL )
370
    {
371
        errno = EBADF;
372
        return -1;
373
    }
374
 
375
    cyg_fd_assign( fd2, fp );
376
 
377
    cyg_fp_free(fp);
378
 
379
    return fd2;
380
}
381
 
382
// -------------------------------------------------------------------------
383
// EOF fd.cxx

powered by: WebSVN 2.1.0

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