Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | --- findfp.c.orig 2009-02-15 03:11:22.000000000 -0800 +++ findfp.c 2009-02-15 18:45:19.000000000 -0800 @@ -46,7 +46,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/f #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <libkern/OSAtomic.h> +#include <errno.h> +#include <pthread.h> #include <spinlock.h> #include "libc_private.h" @@ -62,12 +65,19 @@ int __sdidinit; {0}, __sFX + file} /* p r w flags file _bf z cookie close read seek write */ /* _ub _extra */ +#define __sFXInit {0, PTHREAD_MUTEX_INITIALIZER} + /* set counted */ +#define __sFXInit3 {0, PTHREAD_MUTEX_INITIALIZER, 0, 0, 0, 1} /* the usual - (stdin + stdout + stderr) */ + +static int __scounted; /* streams counted against STREAM_MAX */ +static int __stream_max; + static FILE usual[FOPEN_MAX - 3]; static struct __sFILEX usual_extra[FOPEN_MAX - 3]; static struct glue uglue = { NULL, FOPEN_MAX - 3, usual }; -static struct __sFILEX __sFX[3]; +static struct __sFILEX __sFX[3] = {__sFXInit3, __sFXInit3, __sFXInit3}; /* * We can't make this 'static' until 6.0-current due to binary @@ -113,7 +123,7 @@ moreglue(n) { struct glue *g; static FILE empty; - static struct __sFILEX emptyx; + static struct __sFILEX emptyx = __sFXInit; FILE *p; struct __sFILEX *fx; @@ -139,7 +149,7 @@ moreglue(n) * Find a free FILE for fopen et al. */ FILE * -__sfp() +__sfp(int count) { FILE *fp; int n; @@ -147,6 +157,15 @@ __sfp() if (!__sdidinit) __sinit(); + + if (count) { + if (__scounted >= __stream_max) { + THREAD_UNLOCK(); + errno = EMFILE; + return NULL; + } + OSAtomicIncrement32(&__scounted); + } /* * The list must be locked because a FILE may be updated. */ @@ -179,12 +198,27 @@ found: fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; /* fp->_lock = NULL; */ /* once set always set (reused) */ + fp->_extra->fl_mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; fp->_extra->orientation = 0; + fp->_extra->counted = count ? 1 : 0; memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t)); return (fp); } /* + * Mark as free and update count as needed + */ +__private_extern__ void +__sfprelease(FILE *fp) +{ + if (fp->_extra->counted) { + OSAtomicDecrement32(&__scounted); + fp->_extra->counted = 0; + } + fp->_flags = 0; +} + +/* * XXX. Force immediate allocation of internal memory. Not used by stdio, * but documented historically for certain applications. Bad applications. */ @@ -244,6 +278,8 @@ __sinit() /* Make sure we clean up on exit. */ __cleanup = _cleanup; /* conservative */ __sdidinit = 1; + __stream_max = sysconf(_SC_STREAM_MAX); + __scounted = 3; /* std{in,out,err} already exists */ } THREAD_UNLOCK(); } |