/* * Find a free FILE for fopen et al. */ FILE * __sfp(void) { FILE *fp; int n; struct glue *g; if (!__sdidinit) __sinit(); /* * The list must be locked because a FILE may be updated. */ THREAD_LOCK(); for (g = &__sglue; g != NULL; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->pub._flags == 0) goto found; } THREAD_UNLOCK(); /* don't hold lock while malloc()ing. */ if ((g = moreglue(NDYNAMIC)) == NULL) return (NULL); THREAD_LOCK(); /* reacquire the lock */ SET_GLUE_PTR(lastglue->next, g); /* atomically append glue to list */ lastglue = g; /* not atomic; only accessed when locked */ fp = g->iobs; found: fp->pub._flags = 1; /* reserve this slot; caller sets real flags */ THREAD_UNLOCK(); fp->pub._p = NULL; /* no current pointer */ fp->pub._w = 0; /* nothing to read or write */ fp->pub._r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->pub._lbfsize = 0; /* not line buffered */ fp->pub._fileno = -1; /* no file */ /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ fp->_ub._base = NULL; /* no ungetc buffer */ fp->_ub._size = 0; fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; /* fp->_lock = NULL; */ /* once set always set (reused) */ memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (fp); }
/* * Find a free FILE for fopen et al. */ FILE * __sfp(void) { FILE *fp; int n; struct glue *g; if (!__sdidinit) __sinit(); _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); for (g = &__sglue; g != NULL; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->_flags == 0) goto found; } /* release lock while mallocing */ _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex); if ((g = moreglue(NDYNAMIC)) == NULL) return (NULL); _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); lastglue->next = g; lastglue = g; fp = g->iobs; found: fp->_flags = 1; /* reserve this slot; caller sets real flags */ _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex); fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ fp->_r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->_lbfsize = 0; /* not line buffered */ fp->_file = -1; /* no file */ /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; _FILEEXT_INIT(fp); return (fp); }
void f_prealloc(void) { struct glue *g; int n; n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */ /* * It should be safe to walk the list without locking it; * new nodes are only added to the end and none are ever * removed. */ for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) /* void */; if ((n > 0) && ((g = moreglue(n)) != NULL)) { STDIO_THREAD_LOCK(); SET_GLUE_PTR(lastglue->next, g); lastglue = g; STDIO_THREAD_UNLOCK(); } }
/* * Find a free FILE for fopen et al. */ FILE * __sfp() { FILE *fp; int n; struct glue *g; if (!__sdidinit) __sinit(); rwlock_wrlock(&__sfp_lock); for (g = &__sglue;; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->_flags == 0) goto found; if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL) break; } rwlock_unlock(&__sfp_lock); return (NULL); found: fp->_flags = 1; /* reserve this slot; caller sets real flags */ fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ fp->_r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->_lbfsize = 0; /* not line buffered */ fp->_file = -1; /* no file */ /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ _UB(fp)._base = NULL; /* no ungetc buffer */ _UB(fp)._size = 0; fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); rwlock_unlock(&__sfp_lock); return (fp); }