예제 #1
0
파일: findfp.c 프로젝트: ngkaho1234/freebsd
/*
 * 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.
	 */
	STDIO_THREAD_LOCK();
	for (g = &__sglue; g != NULL; g = g->next) {
		for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
			if (fp->_flags == 0)
				goto found;
	}
	STDIO_THREAD_UNLOCK();	/* don't hold lock while malloc()ing. */
	if ((g = moreglue(NDYNAMIC)) == NULL)
		return (NULL);
	STDIO_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->_flags = 1;		/* reserve this slot; caller sets real flags */
	STDIO_THREAD_UNLOCK();
	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->_ub._base = NULL;	/* no ungetc buffer */
	fp->_ub._size = 0;
	fp->_lb._base = NULL;	/* no line buffer */
	fp->_lb._size = 0;
/*	fp->_fl_mutex = NULL; */ /* once set always set (reused) */
	fp->_orientation = 0;
	memset(&fp->_mbstate, 0, sizeof(mbstate_t));
	return (fp);
}
예제 #2
0
파일: findfp.c 프로젝트: ngkaho1234/freebsd
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();
	}
}
예제 #3
0
int
fclose(FILE *fp)
{
    int r;

    if (fp->_flags == 0) {	/* not open! */
        errno = EBADF;
        return (EOF);
    }
    FLOCKFILE(fp);
    r = fp->_flags & __SWR ? __sflush(fp) : 0;
    if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
        r = EOF;
    if (fp->_flags & __SMBF)
        free((char *)fp->_bf._base);
    if (HASUB(fp))
        FREEUB(fp);
    if (HASLB(fp))
        FREELB(fp);
    fp->_file = -1;
    fp->_r = fp->_w = 0;	/* Mess up if reaccessed. */

    /*
     * Lock the spinlock used to protect __sglue list walk in
     * __sfp().  The __sfp() uses fp->_flags == 0 test as an
     * indication of the unused FILE.
     *
     * Taking the lock prevents possible compiler or processor
     * reordering of the writes performed before the final _flags
     * cleanup, making sure that we are done with the FILE before
     * it is considered available.
     */
    STDIO_THREAD_LOCK();
    fp->_flags = 0;		/* Release this FILE for reuse. */
    STDIO_THREAD_UNLOCK();
    FUNLOCKFILE(fp);
    return (r);
}