gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/stdio/findfp.cbare sourcepermlink (0.03 seconds)

Search this content:

    1: /* DYN_ALLOC_FILEBUF:
    2:  *      Dynamic allocate FILE structure using malloc, instead of static
    3:  *      declaration of FILEBUF[FOPEN_MAX] to reduce static memory size
    4:  */
    5: 
    6: /*      $OpenBSD: findfp.c,v 1.12 2009/11/09 00:18:27 kurt Exp $ */
    7: /*-
    8:  * Copyright (c) 1990, 1993
    9:  *      The Regents of the University of California.  All rights reserved.
   10:  *
   11:  * This code is derived from software contributed to Berkeley by
   12:  * Chris Torek.
   13:  *
   14:  * Redistribution and use in source and binary forms, with or without
   15:  * modification, are permitted provided that the following conditions
   16:  * are met:
   17:  * 1. Redistributions of source code must retain the above copyright
   18:  *    notice, this list of conditions and the following disclaimer.
   19:  * 2. Redistributions in binary form must reproduce the above copyright
   20:  *    notice, this list of conditions and the following disclaimer in the
   21:  *    documentation and/or other materials provided with the distribution.
   22:  * 3. Neither the name of the University nor the names of its contributors
   23:  *    may be used to endorse or promote products derived from this software
   24:  *    without specific prior written permission.
   25:  *
   26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36:  * SUCH DAMAGE.
   37:  */
   38: 
   39: #include <sys/param.h>
   40: #include <unistd.h>
   41: #include <stdio.h>
   42: #include <errno.h>
   43: #include <stdlib.h>
   44: #include <string.h>
   45: #include "local.h"
   46: #include "glue.h"
   47: #include "thread_private.h"
   48: 
   49: /* Dynamic allocate FILE structure using malloc. FOPEN_MAX is not used
   50:    because maximun number of open is limited in the file system */
   51: #define DYN_ALLOC_FILEBUF       1
   52: 
   53: 
   54: int     __sdidinit;
   55: 
   56: #define NDYNAMIC 10             /* add ten more whenever necessary */
   57: 
   58: #define std(flags, file) \
   59:         {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
   60:          {(unsigned char *)(__sFext+file), 0}}
   61: /*       p r w flags file _bf z  cookie      close    read    seek    write 
   62:          ext */
   63: 
   64: struct __sfileext __sFext[3];
   65: FILE __sF[3]; static const FILE sF[3] = {
   66:         std(__SRD, STDIN_FILENO),              /* stdin */
   67:         std(__SWR, STDOUT_FILENO),             /* stdout */
   68:         std(__SWR|__SNBF, STDERR_FILENO)       /* stderr */
   69: };
   70: 
   71: #if     DYN_ALLOC_FILEBUF
   72: struct filebuf {
   73:         struct glue            g;
   74:         FILE                   f;
   75:         struct __sfileext      fext;
   76: };
   77: struct glue __sglue = { NULL, 3, __sF };
   78: #else   /* DYN_ALLOC_FILEBUF */
   79:                                 /* the usual - (stdin + stdout + stderr) */
   80: static FILE usual[FOPEN_MAX - 3];
   81: static struct __sfileext usualext[FOPEN_MAX - 3];
   82: static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
   83: static struct glue *lastglue = &uglue;
   84: struct glue __sglue = { &uglue, 3, __sF };
   85: #endif  /* DYN_ALLOC_FILEBUF */
   86: 
   87: _THREAD_PRIVATE_MUTEX(__sfp_mutex);
   88: 
   89: #if 0
   90: static struct glue *moreglue(int n)
   91: {
   92:         struct glue *g;
   93:         FILE *p;
   94:         struct __sfileext *pext;
   95:         static FILE empty;
   96:         char *data;
   97: 
   98:         data = malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE)
   99:             + n * sizeof(struct __sfileext));
  100:         if (data == NULL)
  101:                 return (NULL);
  102:         g = (struct glue *)data;
  103:         p = (FILE *)ALIGN(data + sizeof(*g));
  104:         pext = (struct __sfileext *)
  105:             (ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
  106:         g->next = NULL;
  107:         g->niobs = n;
  108:         g->iobs = p;
  109:         while (--n >= 0) {
  110:                 *p = empty;
  111:                 _FILEEXT_SETUP(p, pext);
  112:                 p++;
  113:                 pext++;
  114:         }
  115:         return (g);
  116: }
  117: #endif
  118: /*
  119:  * Find a free FILE for fopen et al.
  120:  */
  121: FILE *
  122: __sfp(void)
  123: {
  124:         FILE *fp;
  125:         int n;
  126:         struct glue *g;
  127: 
  128:         if (!__sdidinit)
  129:                 __sinit();
  130: 
  131:         _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
  132:         for (g = &__sglue; g != NULL; g = g->next) {
  133:                 for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
  134:                         if (fp->_flags == 0)
  135:                                 goto found;
  136:         }
  137: 
  138:         /* release lock while mallocing */
  139:         _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
  140: #if     DYN_ALLOC_FILEBUF
  141:    {    struct filebuf *p;
  142:         p = (struct filebuf *)malloc(sizeof(struct filebuf));
  143:         if (p == NULL) return NULL;
  144:         _FILEEXT_SETUP(&p->f, &p->fext);
  145:         p->g.niobs = 1;
  146:         p->g.iobs = &p->f;
  147:         _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
  148:         p->g.next = __sglue.next;
  149:         __sglue.next = g = &p->g;
  150:     }
  151: #else   /* DYN_ALLOC_FILEBUF */
  152:         if ((g = /*moreglue(NDYNAMIC)*/NULL) == NULL)
  153:                 return (NULL);
  154:         _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
  155:         lastglue->next = g;
  156:         lastglue = g;
  157: #endif  /* DYN_ALLOC_FILEBUF */
  158:         fp = g->iobs;
  159: found:
  160:         fp->_flags = 1;                /* reserve this slot; caller sets real flags */
  161:         _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
  162:         fp->_p = NULL;         /* no current pointer */
  163:         fp->_w = 0;            /* nothing to read or write */
  164:         fp->_r = 0;
  165:         fp->_bf._base = NULL;  /* no buffer */
  166:         fp->_bf._size = 0;
  167:         fp->_lbfsize = 0;      /* not line buffered */
  168:         fp->_file = -1;                /* no file */
  169: /*      fp->_cookie = <any>; */      /* caller sets cookie, _read/_write etc */
  170:         fp->_lb._base = NULL;  /* no line buffer */
  171:         fp->_lb._size = 0;
  172:         _FILEEXT_INIT(fp);
  173:         return (fp);
  174: }
  175: 
  176: /*
  177:  * XXX.  Force immediate allocation of internal memory.  Not used by stdio,
  178:  * but documented historically for certain applications.  Bad applications.
  179:  */
  180: #if 0
  181: 
  182: #define getdtablesize() sysconf(_SC_OPEN_MAX)
  183: 
  184: void f_prealloc(void)
  185: {
  186:         struct glue *g;
  187:         int n;
  188: 
  189:         n = getdtablesize() - FOPEN_MAX + 20;          /* 20 for slop. */
  190:         for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
  191:                 /* void */;
  192:         if (n > 0 && ((g = moreglue(n)) != NULL)) {
  193:                 _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
  194:                 lastglue->next = g;
  195:                 lastglue = g;
  196:                 _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
  197:         }
  198: }
  199: #endif
  200: /*
  201:  * exit() and abort() call _cleanup() through the callback registered
  202:  * with __atexit_register_cleanup(), set whenever we open or buffer a
  203:  * file. This chicanery is done so that programs that do not use stdio
  204:  * need not link it all in.
  205:  *
  206:  * The name `_cleanup' is, alas, fairly well known outside stdio.
  207:  */
  208: void
  209: _cleanup(void)
  210: {
  211:         /* (void) _fwalk(fclose); */
  212:         (void) _fwalk(__sflush);               /* `cheating' */
  213: }
  214: 
  215: /*
  216:  * __sinit() is called whenever stdio's internal variables must be set up.
  217:  */
  218: void
  219: __sinit(void)
  220: {
  221:         _THREAD_PRIVATE_MUTEX(__sinit_mutex);
  222: 
  223:         _THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
  224:         if (__sdidinit)
  225:                 goto out;     /* bail out if caller lost the race */
  226: #if     ! DYN_ALLOC_FILEBUF
  227:     {
  228:         int i;
  229:         for (i = 0; i < FOPEN_MAX - 3; i++) {
  230:                 _FILEEXT_SETUP(usual+i, usualext+i);
  231:         }
  232:     }
  233: #endif  /* ! DYN_ALLOC_FILEBUF */
  234:         /* make sure we clean up on exit */
  235:         __atexit_register_cleanup(_cleanup); /* conservative */
  236:         __sF[0] = sF[0]; __sF[1] = sF[1]; __sF[2] = sF[2]; __sdidinit = 1;
  237: out: 
  238:         _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
  239: }