source: trunk/src/emx/src/lib/io/_fdinit.c@ 871

Last change on this file since 871 was 871, checked in by bird, 22 years ago

#697: Filehandle rewrite - first step.

  • Property cvs2svn:cvs-rev set to 1.4
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 3.0 KB
Line 
1#if 0 /* dead */
2/* _fdinit.c (emx+gcc) -- Copyright (c) 1996-1997 by Eberhard Mattes */
3
4#include "libc-alias.h"
5#include <stdlib.h>
6#include <emx/io.h>
7#include <sys/builtin.h> /* For <sys/fmutex.h> */
8#include <sys/fmutex.h> /* For <sys/rmutex.h> */
9#include <sys/rmutex.h>
10#include <emx/startup.h>
11
12/* See app/iodata.c. */
13
14extern int _nfiles;
15extern int _files[];
16extern int _lookahead[];
17
18/* This semaphore protects a critical region in _fd_init(). */
19
20static _rmutex _fdinit_rmutex;
21
22
23/* Initialize the semaphore -- this function will be called by
24 _CRT_init() via the __crtinit1__ set vector. */
25
26void _init1_fdinit (void);
27void _init1_fdinit (void)
28{
29 _rmutex_checked_create (&_fdinit_rmutex, 0);
30}
31
32_CRT_INIT1 (_init1_fdinit)
33
34
35/* Return pointer to flags word for the new file descriptor HANDLE and
36 initialize lookahead. Return NULL on error. */
37
38int *_fd_init (int handle)
39{
40 struct fdvec *p, *last;
41 int i, n;
42
43 if (handle < 0)
44 return NULL;
45
46 p = &_fdvec_head; last = NULL;
47 while (p != NULL && handle >= p->n)
48 {
49 handle -= p->n;
50 last = p;
51 p = p->next;
52 }
53 if (p == NULL)
54 {
55 n = handle + 1;
56 if (n < 32) n = 32;
57
58 p = malloc (sizeof (*p));
59 if (p == NULL)
60 return NULL;
61 p->flags = malloc (n * sizeof (int));
62 if (p->flags == NULL)
63 {
64 free (p);
65 return NULL;
66 }
67 p->lookahead = malloc (n * sizeof (int));
68 if (p->lookahead == NULL)
69 {
70 free (p->flags);
71 free (p);
72 return NULL;
73 }
74 for (i = 0; i < n; ++i)
75 {
76 p->flags[i] = 0;
77 p->lookahead[i] = -1;
78 }
79 p->n = n;
80 p->next = NULL;
81
82 /* Prevent other threads from updating last->next. */
83
84 _rmutex_checked_request (&_fdinit_rmutex, _FMR_IGNINT);
85
86 /* Now that we have locked other threads out of this critical
87 region, update last->next unless another thread has updated
88 last->next before this thread entered the critical region. */
89
90 if (last->next == NULL)
91 last->next = p;
92
93 /* End of critical region. From now on, last->next is non-NULL
94 and therefore won't be changed by other threads. */
95
96 _rmutex_checked_release (&_fdinit_rmutex);
97
98 /* If another thread updated last->next, back out and retry,
99 using the elements added by the other threads. As we keep p
100 pointing to malloc()ed memory around the critical region,
101 other threads may not happen to use the same value of p. */
102
103 if (last->next != p)
104 {
105 /* Another thread did the work. */
106
107 free (p->flags);
108 free (p->lookahead);
109 free (p);
110
111 /* The other thread might have requested fewer new elements
112 than this thread, therefore we do not assign last->next
113 to p! We start over, instead. */
114
115 return _fd_init (handle);
116 }
117 }
118
119 p->lookahead[handle] = -1;
120 return &p->flags[handle];
121}
122#endif
Note: See TracBrowser for help on using the repository browser.