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

Last change on this file since 1454 was 1454, checked in by bird, 21 years ago

Joined with the fork() tree from netlabs.cvs.

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