unix.c (buf_write): Return early if there is nothing to write.
[gcc.git] / libgfortran / io / unit.c
1 /* Copyright (C) 2002-2017 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 F2003 I/O support contributed by Jerry DeLisle
4
5 This file is part of the GNU Fortran runtime library (libgfortran).
6
7 Libgfortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
25
26 #include "io.h"
27 #include "fbuf.h"
28 #include "format.h"
29 #include "unix.h"
30 #include <string.h>
31 #include <assert.h>
32
33
34 /* IO locking rules:
35 UNIT_LOCK is a master lock, protecting UNIT_ROOT tree and UNIT_CACHE.
36 Concurrent use of different units should be supported, so
37 each unit has its own lock, LOCK.
38 Open should be atomic with its reopening of units and list_read.c
39 in several places needs find_unit another unit while holding stdin
40 unit's lock, so it must be possible to acquire UNIT_LOCK while holding
41 some unit's lock. Therefore to avoid deadlocks, it is forbidden
42 to acquire unit's private locks while holding UNIT_LOCK, except
43 for freshly created units (where no other thread can get at their
44 address yet) or when using just trylock rather than lock operation.
45 In addition to unit's private lock each unit has a WAITERS counter
46 and CLOSED flag. WAITERS counter must be either only
47 atomically incremented/decremented in all places (if atomic builtins
48 are supported), or protected by UNIT_LOCK in all places (otherwise).
49 CLOSED flag must be always protected by unit's LOCK.
50 After finding a unit in UNIT_CACHE or UNIT_ROOT with UNIT_LOCK held,
51 WAITERS must be incremented to avoid concurrent close from freeing
52 the unit between unlocking UNIT_LOCK and acquiring unit's LOCK.
53 Unit freeing is always done under UNIT_LOCK. If close_unit sees any
54 WAITERS, it doesn't free the unit but instead sets the CLOSED flag
55 and the thread that decrements WAITERS to zero while CLOSED flag is
56 set is responsible for freeing it (while holding UNIT_LOCK).
57 flush_all_units operation is iterating over the unit tree with
58 increasing UNIT_NUMBER while holding UNIT_LOCK and attempting to
59 flush each unit (and therefore needs the unit's LOCK held as well).
60 To avoid deadlocks, it just trylocks the LOCK and if unsuccessful,
61 remembers the current unit's UNIT_NUMBER, unlocks UNIT_LOCK, acquires
62 unit's LOCK and after flushing reacquires UNIT_LOCK and restarts with
63 the smallest UNIT_NUMBER above the last one flushed.
64
65 If find_unit/find_or_create_unit/find_file/get_unit routines return
66 non-NULL, the returned unit has its private lock locked and when the
67 caller is done with it, it must call either unlock_unit or close_unit
68 on it. unlock_unit or close_unit must be always called only with the
69 private lock held. */
70
71
72
73 /* Table of allocated newunit values. A simple solution would be to
74 map OS file descriptors (fd's) to unit numbers, e.g. with newunit =
75 -fd - 2, however that doesn't work since Fortran allows an existing
76 unit number to be reassociated with a new file. Thus the simple
77 approach may lead to a situation where we'd try to assign a
78 (negative) unit number which already exists. Hence we must keep
79 track of allocated newunit values ourselves. This is the purpose of
80 the newunits array. The indices map to newunit values as newunit =
81 -index + NEWUNIT_FIRST. E.g. newunits[0] having the value true
82 means that a unit with number NEWUNIT_FIRST exists. Similar to
83 POSIX file descriptors, we always allocate the lowest (in absolute
84 value) available unit number.
85 */
86 static bool *newunits;
87 static int newunit_size; /* Total number of elements in the newunits array. */
88 /* Low water indicator for the newunits array. Below the LWI all the
89 units are allocated, above and equal to the LWI there may be both
90 allocated and free units. */
91 static int newunit_lwi;
92 static void newunit_free (int);
93
94 /* Unit numbers assigned with NEWUNIT start from here. */
95 #define NEWUNIT_START -10
96
97
98 #define NEWUNIT_STACK_SIZE 16
99
100 /* A stack to save previously used newunit-assigned unit numbers to
101 allow them to be reused without reallocating the gfc_unit structure
102 which is still in the treap. */
103 static gfc_saved_unit newunit_stack[NEWUNIT_STACK_SIZE];
104 static int newunit_tos = 0; /* Index to Top of Stack. */
105
106
107 #define CACHE_SIZE 3
108 static gfc_unit *unit_cache[CACHE_SIZE];
109 gfc_offset max_offset;
110 gfc_unit *unit_root;
111 #ifdef __GTHREAD_MUTEX_INIT
112 __gthread_mutex_t unit_lock = __GTHREAD_MUTEX_INIT;
113 #else
114 __gthread_mutex_t unit_lock;
115 #endif
116
117 /* We use these filenames for error reporting. */
118
119 static char stdin_name[] = "stdin";
120 static char stdout_name[] = "stdout";
121 static char stderr_name[] = "stderr";
122
123
124 #ifdef HAVE_NEWLOCALE
125 locale_t c_locale;
126 #else
127 /* If we don't have POSIX 2008 per-thread locales, we need to use the
128 traditional setlocale(). To prevent multiple concurrent threads
129 doing formatted I/O from messing up the locale, we need to store a
130 global old_locale, and a counter keeping track of how many threads
131 are currently doing formatted I/O. The first thread saves the old
132 locale, and the last one restores it. */
133 char *old_locale;
134 int old_locale_ctr;
135 #ifdef __GTHREAD_MUTEX_INIT
136 __gthread_mutex_t old_locale_lock = __GTHREAD_MUTEX_INIT;
137 #else
138 __gthread_mutex_t old_locale_lock;
139 #endif
140 #endif
141
142
143 /* This implementation is based on Stefan Nilsson's article in the
144 July 1997 Doctor Dobb's Journal, "Treaps in Java". */
145
146 /* pseudo_random()-- Simple linear congruential pseudorandom number
147 generator. The period of this generator is 44071, which is plenty
148 for our purposes. */
149
150 static int
151 pseudo_random (void)
152 {
153 static int x0 = 5341;
154
155 x0 = (22611 * x0 + 10) % 44071;
156 return x0;
157 }
158
159
160 /* rotate_left()-- Rotate the treap left */
161
162 static gfc_unit *
163 rotate_left (gfc_unit *t)
164 {
165 gfc_unit *temp;
166
167 temp = t->right;
168 t->right = t->right->left;
169 temp->left = t;
170
171 return temp;
172 }
173
174
175 /* rotate_right()-- Rotate the treap right */
176
177 static gfc_unit *
178 rotate_right (gfc_unit *t)
179 {
180 gfc_unit *temp;
181
182 temp = t->left;
183 t->left = t->left->right;
184 temp->right = t;
185
186 return temp;
187 }
188
189
190 static int
191 compare (int a, int b)
192 {
193 if (a < b)
194 return -1;
195 if (a > b)
196 return 1;
197
198 return 0;
199 }
200
201
202 /* insert()-- Recursive insertion function. Returns the updated treap. */
203
204 static gfc_unit *
205 insert (gfc_unit *new, gfc_unit *t)
206 {
207 int c;
208
209 if (t == NULL)
210 return new;
211
212 c = compare (new->unit_number, t->unit_number);
213
214 if (c < 0)
215 {
216 t->left = insert (new, t->left);
217 if (t->priority < t->left->priority)
218 t = rotate_right (t);
219 }
220
221 if (c > 0)
222 {
223 t->right = insert (new, t->right);
224 if (t->priority < t->right->priority)
225 t = rotate_left (t);
226 }
227
228 if (c == 0)
229 internal_error (NULL, "insert(): Duplicate key found!");
230
231 return t;
232 }
233
234
235 /* insert_unit()-- Create a new node, insert it into the treap. */
236
237 static gfc_unit *
238 insert_unit (int n)
239 {
240 gfc_unit *u = xcalloc (1, sizeof (gfc_unit));
241 u->unit_number = n;
242 #ifdef __GTHREAD_MUTEX_INIT
243 {
244 __gthread_mutex_t tmp = __GTHREAD_MUTEX_INIT;
245 u->lock = tmp;
246 }
247 #else
248 __GTHREAD_MUTEX_INIT_FUNCTION (&u->lock);
249 #endif
250 __gthread_mutex_lock (&u->lock);
251 u->priority = pseudo_random ();
252 unit_root = insert (u, unit_root);
253 return u;
254 }
255
256
257 /* destroy_unit_mutex()-- Destroy the mutex and free memory of unit. */
258
259 static void
260 destroy_unit_mutex (gfc_unit *u)
261 {
262 __gthread_mutex_destroy (&u->lock);
263 free (u);
264 }
265
266
267 static gfc_unit *
268 delete_root (gfc_unit *t)
269 {
270 gfc_unit *temp;
271
272 if (t->left == NULL)
273 return t->right;
274 if (t->right == NULL)
275 return t->left;
276
277 if (t->left->priority > t->right->priority)
278 {
279 temp = rotate_right (t);
280 temp->right = delete_root (t);
281 }
282 else
283 {
284 temp = rotate_left (t);
285 temp->left = delete_root (t);
286 }
287
288 return temp;
289 }
290
291
292 /* delete_treap()-- Delete an element from a tree. The 'old' value
293 does not necessarily have to point to the element to be deleted, it
294 must just point to a treap structure with the key to be deleted.
295 Returns the new root node of the tree. */
296
297 static gfc_unit *
298 delete_treap (gfc_unit *old, gfc_unit *t)
299 {
300 int c;
301
302 if (t == NULL)
303 return NULL;
304
305 c = compare (old->unit_number, t->unit_number);
306
307 if (c < 0)
308 t->left = delete_treap (old, t->left);
309 if (c > 0)
310 t->right = delete_treap (old, t->right);
311 if (c == 0)
312 t = delete_root (t);
313
314 return t;
315 }
316
317
318 /* delete_unit()-- Delete a unit from a tree */
319
320 static void
321 delete_unit (gfc_unit *old)
322 {
323 unit_root = delete_treap (old, unit_root);
324 }
325
326
327 /* get_gfc_unit()-- Given an integer, return a pointer to the unit
328 structure. Returns NULL if the unit does not exist,
329 otherwise returns a locked unit. */
330
331 static gfc_unit *
332 get_gfc_unit (int n, int do_create)
333 {
334 gfc_unit *p;
335 int c, created = 0;
336
337 __gthread_mutex_lock (&unit_lock);
338 retry:
339 for (c = 0; c < CACHE_SIZE; c++)
340 if (unit_cache[c] != NULL && unit_cache[c]->unit_number == n)
341 {
342 p = unit_cache[c];
343 goto found;
344 }
345
346 p = unit_root;
347 while (p != NULL)
348 {
349 c = compare (n, p->unit_number);
350 if (c < 0)
351 p = p->left;
352 if (c > 0)
353 p = p->right;
354 if (c == 0)
355 break;
356 }
357
358 if (p == NULL && do_create)
359 {
360 p = insert_unit (n);
361 created = 1;
362 }
363
364 if (p != NULL)
365 {
366 for (c = 0; c < CACHE_SIZE - 1; c++)
367 unit_cache[c] = unit_cache[c + 1];
368
369 unit_cache[CACHE_SIZE - 1] = p;
370 }
371
372 if (created)
373 {
374 /* Newly created units have their lock held already
375 from insert_unit. Just unlock UNIT_LOCK and return. */
376 __gthread_mutex_unlock (&unit_lock);
377 return p;
378 }
379
380 found:
381 if (p != NULL && (p->child_dtio == 0))
382 {
383 /* Fast path. */
384 if (! __gthread_mutex_trylock (&p->lock))
385 {
386 /* assert (p->closed == 0); */
387 __gthread_mutex_unlock (&unit_lock);
388 return p;
389 }
390
391 inc_waiting_locked (p);
392 }
393
394
395 __gthread_mutex_unlock (&unit_lock);
396
397 if (p != NULL && (p->child_dtio == 0))
398 {
399 __gthread_mutex_lock (&p->lock);
400 if (p->closed)
401 {
402 __gthread_mutex_lock (&unit_lock);
403 __gthread_mutex_unlock (&p->lock);
404 if (predec_waiting_locked (p) == 0)
405 destroy_unit_mutex (p);
406 goto retry;
407 }
408
409 dec_waiting_unlocked (p);
410 }
411 return p;
412 }
413
414
415 gfc_unit *
416 find_unit (int n)
417 {
418 return get_gfc_unit (n, 0);
419 }
420
421
422 gfc_unit *
423 find_or_create_unit (int n)
424 {
425 return get_gfc_unit (n, 1);
426 }
427
428
429 /* Helper function to check rank, stride, format string, and namelist.
430 This is used for optimization. You can't trim out blanks or shorten
431 the string if trailing spaces are significant. */
432 static bool
433 is_trim_ok (st_parameter_dt *dtp)
434 {
435 /* Check rank and stride. */
436 if (dtp->internal_unit_desc)
437 return false;
438 /* Format strings can not have 'BZ' or '/'. */
439 if (dtp->common.flags & IOPARM_DT_HAS_FORMAT)
440 {
441 char *p = dtp->format;
442 off_t i;
443 if (dtp->common.flags & IOPARM_DT_HAS_BLANK)
444 return false;
445 for (i = 0; i < dtp->format_len; i++)
446 {
447 if (p[i] == '/') return false;
448 if (p[i] == 'b' || p[i] == 'B')
449 if (p[i+1] == 'z' || p[i+1] == 'Z')
450 return false;
451 }
452 }
453 if (dtp->u.p.ionml) /* A namelist. */
454 return false;
455 return true;
456 }
457
458
459 gfc_unit *
460 set_internal_unit (st_parameter_dt *dtp, gfc_unit *iunit, int kind)
461 {
462 gfc_offset start_record = 0;
463
464 iunit->unit_number = dtp->common.unit;
465 iunit->recl = dtp->internal_unit_len;
466 iunit->internal_unit = dtp->internal_unit;
467 iunit->internal_unit_len = dtp->internal_unit_len;
468 iunit->internal_unit_kind = kind;
469
470 /* As an optimization, adjust the unit record length to not
471 include trailing blanks. This will not work under certain conditions
472 where trailing blanks have significance. */
473 if (dtp->u.p.mode == READING && is_trim_ok (dtp))
474 {
475 int len;
476 if (kind == 1)
477 len = string_len_trim (iunit->internal_unit_len,
478 iunit->internal_unit);
479 else
480 len = string_len_trim_char4 (iunit->internal_unit_len,
481 (const gfc_char4_t*) iunit->internal_unit);
482 iunit->internal_unit_len = len;
483 iunit->recl = iunit->internal_unit_len;
484 }
485
486 /* Set up the looping specification from the array descriptor, if any. */
487
488 if (is_array_io (dtp))
489 {
490 iunit->rank = GFC_DESCRIPTOR_RANK (dtp->internal_unit_desc);
491 iunit->ls = (array_loop_spec *)
492 xmallocarray (iunit->rank, sizeof (array_loop_spec));
493 iunit->internal_unit_len *=
494 init_loop_spec (dtp->internal_unit_desc, iunit->ls, &start_record);
495
496 start_record *= iunit->recl;
497 }
498
499 /* Set initial values for unit parameters. */
500 if (kind == 4)
501 iunit->s = open_internal4 (iunit->internal_unit - start_record,
502 iunit->internal_unit_len, -start_record);
503 else
504 iunit->s = open_internal (iunit->internal_unit - start_record,
505 iunit->internal_unit_len, -start_record);
506
507 iunit->bytes_left = iunit->recl;
508 iunit->last_record=0;
509 iunit->maxrec=0;
510 iunit->current_record=0;
511 iunit->read_bad = 0;
512 iunit->endfile = NO_ENDFILE;
513
514 /* Set flags for the internal unit. */
515
516 iunit->flags.access = ACCESS_SEQUENTIAL;
517 iunit->flags.action = ACTION_READWRITE;
518 iunit->flags.blank = BLANK_NULL;
519 iunit->flags.form = FORM_FORMATTED;
520 iunit->flags.pad = PAD_YES;
521 iunit->flags.status = STATUS_UNSPECIFIED;
522 iunit->flags.sign = SIGN_UNSPECIFIED;
523 iunit->flags.decimal = DECIMAL_POINT;
524 iunit->flags.delim = DELIM_UNSPECIFIED;
525 iunit->flags.encoding = ENCODING_DEFAULT;
526 iunit->flags.async = ASYNC_NO;
527 iunit->flags.round = ROUND_UNSPECIFIED;
528
529 /* Initialize the data transfer parameters. */
530
531 dtp->u.p.advance_status = ADVANCE_YES;
532 dtp->u.p.seen_dollar = 0;
533 dtp->u.p.skips = 0;
534 dtp->u.p.pending_spaces = 0;
535 dtp->u.p.max_pos = 0;
536 dtp->u.p.at_eof = 0;
537 return iunit;
538 }
539
540
541 /* stash_internal_unit()-- Push the internal unit number onto the
542 avaialble stack. */
543 void
544 stash_internal_unit (st_parameter_dt *dtp)
545 {
546 __gthread_mutex_lock (&unit_lock);
547 newunit_tos++;
548 if (newunit_tos >= NEWUNIT_STACK_SIZE)
549 internal_error (&dtp->common, "stash_internal_unit(): Stack Size Exceeded");
550 newunit_stack[newunit_tos].unit_number = dtp->common.unit;
551 newunit_stack[newunit_tos].unit = dtp->u.p.current_unit;
552 __gthread_mutex_unlock (&unit_lock);
553 }
554
555
556
557 /* get_unit()-- Returns the unit structure associated with the integer
558 unit or the internal file. */
559
560 gfc_unit *
561 get_unit (st_parameter_dt *dtp, int do_create)
562 {
563 gfc_unit *unit;
564
565 if ((dtp->common.flags & IOPARM_DT_HAS_INTERNAL_UNIT) != 0)
566 {
567 int kind;
568 if (dtp->common.unit == GFC_INTERNAL_UNIT)
569 kind = 1;
570 else if (dtp->common.unit == GFC_INTERNAL_UNIT4)
571 kind = 4;
572 else
573 internal_error (&dtp->common, "get_unit(): Bad internal unit KIND");
574
575 if ((dtp->common.flags & IOPARM_DT_HAS_UDTIO) != 0)
576 {
577 dtp->u.p.unit_is_internal = 1;
578 dtp->common.unit = newunit_alloc ();
579 unit = get_gfc_unit (dtp->common.unit, do_create);
580 set_internal_unit (dtp, unit, kind);
581 fbuf_init (unit, 128);
582 return unit;
583 }
584 else
585 {
586 __gthread_mutex_lock (&unit_lock);
587 if (newunit_tos)
588 {
589 dtp->common.unit = newunit_stack[newunit_tos].unit_number;
590 unit = newunit_stack[newunit_tos--].unit;
591 __gthread_mutex_unlock (&unit_lock);
592 unit->fbuf->act = unit->fbuf->pos = 0;
593 }
594 else
595 {
596 __gthread_mutex_unlock (&unit_lock);
597 dtp->common.unit = newunit_alloc ();
598 unit = xcalloc (1, sizeof (gfc_unit));
599 fbuf_init (unit, 128);
600 }
601 set_internal_unit (dtp, unit, kind);
602 return unit;
603 }
604 }
605
606 /* If an internal unit number is passed from the parent to the child
607 it should have been stashed on the newunit_stack ready to be used.
608 Check for it now and return the internal unit if found. */
609 __gthread_mutex_lock (&unit_lock);
610 if (newunit_tos && (dtp->common.unit <= NEWUNIT_START)
611 && (dtp->common.unit == newunit_stack[newunit_tos].unit_number))
612 {
613 unit = newunit_stack[newunit_tos--].unit;
614 __gthread_mutex_unlock (&unit_lock);
615 return unit;
616 }
617 __gthread_mutex_unlock (&unit_lock);
618
619 /* Has to be an external unit. */
620 dtp->u.p.unit_is_internal = 0;
621 dtp->internal_unit = NULL;
622 dtp->internal_unit_desc = NULL;
623
624 /* For an external unit with unit number < 0 creating it on the fly
625 is not allowed, such units must be created with
626 OPEN(NEWUNIT=...). */
627 if (dtp->common.unit < 0)
628 return get_gfc_unit (dtp->common.unit, 0);
629
630 return get_gfc_unit (dtp->common.unit, do_create);
631 }
632
633
634 /*************************/
635 /* Initialize everything. */
636
637 void
638 init_units (void)
639 {
640 gfc_unit *u;
641 unsigned int i;
642
643 #ifdef HAVE_NEWLOCALE
644 c_locale = newlocale (0, "C", 0);
645 #else
646 #ifndef __GTHREAD_MUTEX_INIT
647 __GTHREAD_MUTEX_INIT_FUNCTION (&old_locale_lock);
648 #endif
649 #endif
650
651 #ifndef __GTHREAD_MUTEX_INIT
652 __GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
653 #endif
654
655 if (options.stdin_unit >= 0)
656 { /* STDIN */
657 u = insert_unit (options.stdin_unit);
658 u->s = input_stream ();
659
660 u->flags.action = ACTION_READ;
661
662 u->flags.access = ACCESS_SEQUENTIAL;
663 u->flags.form = FORM_FORMATTED;
664 u->flags.status = STATUS_OLD;
665 u->flags.blank = BLANK_NULL;
666 u->flags.pad = PAD_YES;
667 u->flags.position = POSITION_ASIS;
668 u->flags.sign = SIGN_UNSPECIFIED;
669 u->flags.decimal = DECIMAL_POINT;
670 u->flags.delim = DELIM_UNSPECIFIED;
671 u->flags.encoding = ENCODING_DEFAULT;
672 u->flags.async = ASYNC_NO;
673 u->flags.round = ROUND_UNSPECIFIED;
674 u->flags.share = SHARE_UNSPECIFIED;
675 u->flags.cc = CC_LIST;
676
677 u->recl = options.default_recl;
678 u->endfile = NO_ENDFILE;
679
680 u->filename = strdup (stdin_name);
681
682 fbuf_init (u, 0);
683
684 __gthread_mutex_unlock (&u->lock);
685 }
686
687 if (options.stdout_unit >= 0)
688 { /* STDOUT */
689 u = insert_unit (options.stdout_unit);
690 u->s = output_stream ();
691
692 u->flags.action = ACTION_WRITE;
693
694 u->flags.access = ACCESS_SEQUENTIAL;
695 u->flags.form = FORM_FORMATTED;
696 u->flags.status = STATUS_OLD;
697 u->flags.blank = BLANK_NULL;
698 u->flags.position = POSITION_ASIS;
699 u->flags.sign = SIGN_UNSPECIFIED;
700 u->flags.decimal = DECIMAL_POINT;
701 u->flags.delim = DELIM_UNSPECIFIED;
702 u->flags.encoding = ENCODING_DEFAULT;
703 u->flags.async = ASYNC_NO;
704 u->flags.round = ROUND_UNSPECIFIED;
705 u->flags.share = SHARE_UNSPECIFIED;
706 u->flags.cc = CC_LIST;
707
708 u->recl = options.default_recl;
709 u->endfile = AT_ENDFILE;
710
711 u->filename = strdup (stdout_name);
712
713 fbuf_init (u, 0);
714
715 __gthread_mutex_unlock (&u->lock);
716 }
717
718 if (options.stderr_unit >= 0)
719 { /* STDERR */
720 u = insert_unit (options.stderr_unit);
721 u->s = error_stream ();
722
723 u->flags.action = ACTION_WRITE;
724
725 u->flags.access = ACCESS_SEQUENTIAL;
726 u->flags.form = FORM_FORMATTED;
727 u->flags.status = STATUS_OLD;
728 u->flags.blank = BLANK_NULL;
729 u->flags.position = POSITION_ASIS;
730 u->flags.sign = SIGN_UNSPECIFIED;
731 u->flags.decimal = DECIMAL_POINT;
732 u->flags.encoding = ENCODING_DEFAULT;
733 u->flags.async = ASYNC_NO;
734 u->flags.round = ROUND_UNSPECIFIED;
735 u->flags.share = SHARE_UNSPECIFIED;
736 u->flags.cc = CC_LIST;
737
738 u->recl = options.default_recl;
739 u->endfile = AT_ENDFILE;
740
741 u->filename = strdup (stderr_name);
742
743 fbuf_init (u, 256); /* 256 bytes should be enough, probably not doing
744 any kind of exotic formatting to stderr. */
745
746 __gthread_mutex_unlock (&u->lock);
747 }
748
749 /* Calculate the maximum file offset in a portable manner.
750 max will be the largest signed number for the type gfc_offset.
751 set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
752 max_offset = 0;
753 for (i = 0; i < sizeof (max_offset) * 8 - 1; i++)
754 max_offset = max_offset + ((gfc_offset) 1 << i);
755
756 /* Initialize the newunit stack. */
757 memset (newunit_stack, 0, NEWUNIT_STACK_SIZE * sizeof(gfc_saved_unit));
758 newunit_tos = 0;
759 }
760
761
762 static int
763 close_unit_1 (gfc_unit *u, int locked)
764 {
765 int i, rc;
766
767 /* If there are previously written bytes from a write with ADVANCE="no"
768 Reposition the buffer before closing. */
769 if (u->previous_nonadvancing_write)
770 finish_last_advance_record (u);
771
772 rc = (u->s == NULL) ? 0 : sclose (u->s) == -1;
773
774 u->closed = 1;
775 if (!locked)
776 __gthread_mutex_lock (&unit_lock);
777
778 for (i = 0; i < CACHE_SIZE; i++)
779 if (unit_cache[i] == u)
780 unit_cache[i] = NULL;
781
782 delete_unit (u);
783
784 free (u->filename);
785 u->filename = NULL;
786
787 free_format_hash_table (u);
788 fbuf_destroy (u);
789
790 if (u->unit_number <= NEWUNIT_START)
791 newunit_free (u->unit_number);
792
793 if (!locked)
794 __gthread_mutex_unlock (&u->lock);
795
796 /* If there are any threads waiting in find_unit for this unit,
797 avoid freeing the memory, the last such thread will free it
798 instead. */
799 if (u->waiting == 0)
800 destroy_unit_mutex (u);
801
802 if (!locked)
803 __gthread_mutex_unlock (&unit_lock);
804
805 return rc;
806 }
807
808 void
809 unlock_unit (gfc_unit *u)
810 {
811 __gthread_mutex_unlock (&u->lock);
812 }
813
814 /* close_unit()-- Close a unit. The stream is closed, and any memory
815 associated with the stream is freed. Returns nonzero on I/O error.
816 Should be called with the u->lock locked. */
817
818 int
819 close_unit (gfc_unit *u)
820 {
821 return close_unit_1 (u, 0);
822 }
823
824
825 /* close_units()-- Delete units on completion. We just keep deleting
826 the root of the treap until there is nothing left.
827 Not sure what to do with locking here. Some other thread might be
828 holding some unit's lock and perhaps hold it indefinitely
829 (e.g. waiting for input from some pipe) and close_units shouldn't
830 delay the program too much. */
831
832 void
833 close_units (void)
834 {
835 __gthread_mutex_lock (&unit_lock);
836 while (unit_root != NULL)
837 close_unit_1 (unit_root, 1);
838 __gthread_mutex_unlock (&unit_lock);
839
840 while (newunit_tos != 0)
841 if (newunit_stack[newunit_tos].unit)
842 {
843 fbuf_destroy (newunit_stack[newunit_tos].unit);
844 free (newunit_stack[newunit_tos].unit->s);
845 free (newunit_stack[newunit_tos--].unit);
846 }
847
848 free (newunits);
849
850 #ifdef HAVE_FREELOCALE
851 freelocale (c_locale);
852 #endif
853 }
854
855
856 /* High level interface to truncate a file, i.e. flush format buffers,
857 and generate an error or set some flags. Just like POSIX
858 ftruncate, returns 0 on success, -1 on failure. */
859
860 int
861 unit_truncate (gfc_unit *u, gfc_offset pos, st_parameter_common *common)
862 {
863 int ret;
864
865 /* Make sure format buffer is flushed. */
866 if (u->flags.form == FORM_FORMATTED)
867 {
868 if (u->mode == READING)
869 pos += fbuf_reset (u);
870 else
871 fbuf_flush (u, u->mode);
872 }
873
874 /* struncate() should flush the stream buffer if necessary, so don't
875 bother calling sflush() here. */
876 ret = struncate (u->s, pos);
877
878 if (ret != 0)
879 generate_error (common, LIBERROR_OS, NULL);
880 else
881 {
882 u->endfile = AT_ENDFILE;
883 u->flags.position = POSITION_APPEND;
884 }
885
886 return ret;
887 }
888
889
890 /* filename_from_unit()-- If the unit_number exists, return a pointer to the
891 name of the associated file, otherwise return the empty string. The caller
892 must free memory allocated for the filename string. */
893
894 char *
895 filename_from_unit (int n)
896 {
897 gfc_unit *u;
898 int c;
899
900 /* Find the unit. */
901 u = unit_root;
902 while (u != NULL)
903 {
904 c = compare (n, u->unit_number);
905 if (c < 0)
906 u = u->left;
907 if (c > 0)
908 u = u->right;
909 if (c == 0)
910 break;
911 }
912
913 /* Get the filename. */
914 if (u != NULL && u->filename != NULL)
915 return strdup (u->filename);
916 else
917 return (char *) NULL;
918 }
919
920 void
921 finish_last_advance_record (gfc_unit *u)
922 {
923
924 if (u->saved_pos > 0)
925 fbuf_seek (u, u->saved_pos, SEEK_CUR);
926
927 if (!(u->unit_number == options.stdout_unit
928 || u->unit_number == options.stderr_unit))
929 {
930 #ifdef HAVE_CRLF
931 const int len = 2;
932 #else
933 const int len = 1;
934 #endif
935 char *p = fbuf_alloc (u, len);
936 if (!p)
937 os_error ("Completing record after ADVANCE_NO failed");
938 #ifdef HAVE_CRLF
939 *(p++) = '\r';
940 #endif
941 *p = '\n';
942 }
943
944 fbuf_flush (u, u->mode);
945 }
946
947
948 /* Assign a negative number for NEWUNIT in OPEN statements or for
949 internal units. */
950 int
951 newunit_alloc (void)
952 {
953 __gthread_mutex_lock (&unit_lock);
954 if (!newunits)
955 {
956 newunits = xcalloc (16, 1);
957 newunit_size = 16;
958 }
959
960 /* Search for the next available newunit. */
961 for (int ii = newunit_lwi; ii < newunit_size; ii++)
962 {
963 if (!newunits[ii])
964 {
965 newunits[ii] = true;
966 newunit_lwi = ii + 1;
967 __gthread_mutex_unlock (&unit_lock);
968 return -ii + NEWUNIT_START;
969 }
970 }
971
972 /* Search failed, bump size of array and allocate the first
973 available unit. */
974 int old_size = newunit_size;
975 newunit_size *= 2;
976 newunits = xrealloc (newunits, newunit_size);
977 memset (newunits + old_size, 0, old_size);
978 newunits[old_size] = true;
979 newunit_lwi = old_size + 1;
980 __gthread_mutex_unlock (&unit_lock);
981 return -old_size + NEWUNIT_START;
982 }
983
984
985 /* Free a previously allocated newunit= unit number. unit_lock must
986 be held when calling. */
987
988 static void
989 newunit_free (int unit)
990 {
991 int ind = -unit + NEWUNIT_START;
992 assert(ind >= 0 && ind < newunit_size);
993 newunits[ind] = false;
994 if (ind < newunit_lwi)
995 newunit_lwi = ind;
996 }