xref: /netbsd/lib/libc/stdio/flockfile.c (revision 8744f75a)
1*8744f75aSchristos /*	$NetBSD: flockfile.c,v 1.11 2012/03/15 18:22:30 christos Exp $	*/
23fdac2b8Sthorpej 
33fdac2b8Sthorpej /*-
43fdac2b8Sthorpej  * Copyright (c) 2002 The NetBSD Foundation, Inc.
53fdac2b8Sthorpej  * All rights reserved.
63fdac2b8Sthorpej  *
73fdac2b8Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
83fdac2b8Sthorpej  * by Nathan J. Williams.
93fdac2b8Sthorpej  *
103fdac2b8Sthorpej  * Redistribution and use in source and binary forms, with or without
113fdac2b8Sthorpej  * modification, are permitted provided that the following conditions
123fdac2b8Sthorpej  * are met:
133fdac2b8Sthorpej  * 1. Redistributions of source code must retain the above copyright
143fdac2b8Sthorpej  *    notice, this list of conditions and the following disclaimer.
153fdac2b8Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
163fdac2b8Sthorpej  *    notice, this list of conditions and the following disclaimer in the
173fdac2b8Sthorpej  *    documentation and/or other materials provided with the distribution.
183fdac2b8Sthorpej  *
193fdac2b8Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
203fdac2b8Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
213fdac2b8Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223fdac2b8Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233fdac2b8Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
243fdac2b8Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253fdac2b8Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263fdac2b8Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
273fdac2b8Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283fdac2b8Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293fdac2b8Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
303fdac2b8Sthorpej  */
313fdac2b8Sthorpej 
323fdac2b8Sthorpej #include <sys/cdefs.h>
333fdac2b8Sthorpej #if defined(LIBC_SCCS) && !defined(lint)
34*8744f75aSchristos __RCSID("$NetBSD: flockfile.c,v 1.11 2012/03/15 18:22:30 christos Exp $");
353fdac2b8Sthorpej #endif /* LIBC_SCCS and not lint */
363fdac2b8Sthorpej 
373fdac2b8Sthorpej #include "namespace.h"
383fdac2b8Sthorpej 
393fdac2b8Sthorpej #include <assert.h>
403fdac2b8Sthorpej #include <errno.h>
413fdac2b8Sthorpej #include <stdio.h>
423fdac2b8Sthorpej #include <string.h>
433fdac2b8Sthorpej #include "reentrant.h"
443fdac2b8Sthorpej #include "local.h"
453fdac2b8Sthorpej 
463fdac2b8Sthorpej #ifdef __weak_alias
__weak_alias(flockfile,_flockfile)473fdac2b8Sthorpej __weak_alias(flockfile,_flockfile)
483fdac2b8Sthorpej __weak_alias(ftrylockfile,_ftrylockfile)
493fdac2b8Sthorpej __weak_alias(funlockfile,_funlockfile)
503fdac2b8Sthorpej #endif
513fdac2b8Sthorpej 
523fdac2b8Sthorpej #ifdef _REENTRANT
533fdac2b8Sthorpej /*
543fdac2b8Sthorpej  * XXX This code makes the assumption that a thr_t (pthread_t) is a
553fdac2b8Sthorpej  * XXX pointer.
563fdac2b8Sthorpej  */
573fdac2b8Sthorpej 
583fdac2b8Sthorpej void
593fdac2b8Sthorpej flockfile(FILE *fp)
603fdac2b8Sthorpej {
613fdac2b8Sthorpej 
62ad09d62fSnathanw 	__flockfile_internal(fp, 0);
633fdac2b8Sthorpej }
643fdac2b8Sthorpej 
653fdac2b8Sthorpej int
ftrylockfile(FILE * fp)663fdac2b8Sthorpej ftrylockfile(FILE *fp)
673fdac2b8Sthorpej {
6834c915ebSnathanw 	int retval;
693fdac2b8Sthorpej 
703fdac2b8Sthorpej 	if (__isthreaded == 0)
713fdac2b8Sthorpej 		return 0;
723fdac2b8Sthorpej 
7334c915ebSnathanw 	retval = 0;
7434c915ebSnathanw 	mutex_lock(&_LOCK(fp));
7534c915ebSnathanw 
7634c915ebSnathanw 	if (_LOCKOWNER(fp) == thr_self()) {
7734c915ebSnathanw 		_LOCKCOUNT(fp)++;
7834c915ebSnathanw 	} else if (_LOCKOWNER(fp) == NULL) {
7934c915ebSnathanw 		_LOCKOWNER(fp) = thr_self();
8034c915ebSnathanw 		_LOCKCOUNT(fp) = 1;
8134c915ebSnathanw 	} else
8234c915ebSnathanw 		retval = -1;
8334c915ebSnathanw 
8434c915ebSnathanw 	mutex_unlock(&_LOCK(fp));
8534c915ebSnathanw 
8634c915ebSnathanw 	return retval;
873fdac2b8Sthorpej }
883fdac2b8Sthorpej 
893fdac2b8Sthorpej void
funlockfile(FILE * fp)903fdac2b8Sthorpej funlockfile(FILE *fp)
913fdac2b8Sthorpej {
923fdac2b8Sthorpej 
93ad09d62fSnathanw 	__funlockfile_internal(fp, 0);
94ad09d62fSnathanw }
95ad09d62fSnathanw 
96ad09d62fSnathanw void
__flockfile_internal(FILE * fp,int internal)97ad09d62fSnathanw __flockfile_internal(FILE *fp, int internal)
98ad09d62fSnathanw {
99ad09d62fSnathanw 
1003fdac2b8Sthorpej 	if (__isthreaded == 0)
1013fdac2b8Sthorpej 		return;
1023fdac2b8Sthorpej 
10334c915ebSnathanw 	mutex_lock(&_LOCK(fp));
10434c915ebSnathanw 
105ad09d62fSnathanw 	if (_LOCKOWNER(fp) == thr_self()) {
106ad09d62fSnathanw 		_LOCKCOUNT(fp)++;
1076d30f1a3Snathanw 		if (internal)
108ad09d62fSnathanw 			_LOCKINTERNAL(fp)++;
109ad09d62fSnathanw 	} else {
1106d30f1a3Snathanw 		/* danger! cond_wait() is a cancellation point. */
1116d30f1a3Snathanw 		int oldstate;
1126d30f1a3Snathanw 		thr_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
113ad09d62fSnathanw 		while (_LOCKOWNER(fp) != NULL)
114ad09d62fSnathanw 			cond_wait(&_LOCKCOND(fp), &_LOCK(fp));
1156d30f1a3Snathanw 		thr_setcancelstate(oldstate, NULL);
116ad09d62fSnathanw 		_LOCKOWNER(fp) = thr_self();
117ad09d62fSnathanw 		_LOCKCOUNT(fp) = 1;
1185a5cd67fSnathanw 		if (internal)
1195a5cd67fSnathanw 			_LOCKINTERNAL(fp) = 1;
120ad09d62fSnathanw 	}
121ad09d62fSnathanw 
1226d30f1a3Snathanw 	if (_LOCKINTERNAL(fp) == 1)
1236d30f1a3Snathanw 		/* stash cancellation state and disable */
1246d30f1a3Snathanw 		thr_setcancelstate(PTHREAD_CANCEL_DISABLE,
1256d30f1a3Snathanw 		    &_LOCKCANCELSTATE(fp));
1266d30f1a3Snathanw 
127ad09d62fSnathanw 	mutex_unlock(&_LOCK(fp));
128ad09d62fSnathanw }
129ad09d62fSnathanw 
130ad09d62fSnathanw void
__funlockfile_internal(FILE * fp,int internal)131ad09d62fSnathanw __funlockfile_internal(FILE *fp, int internal)
132ad09d62fSnathanw {
133ad09d62fSnathanw 
134ad09d62fSnathanw 	if (__isthreaded == 0)
135ad09d62fSnathanw 		return;
136ad09d62fSnathanw 
137ad09d62fSnathanw 	mutex_lock(&_LOCK(fp));
138ad09d62fSnathanw 
139ad09d62fSnathanw 	if (internal) {
140ad09d62fSnathanw 		_LOCKINTERNAL(fp)--;
141ad09d62fSnathanw 		if (_LOCKINTERNAL(fp) == 0)
142d3ebb21eSnathanw 			thr_setcancelstate(_LOCKCANCELSTATE(fp), NULL);
143ad09d62fSnathanw 	}
144ad09d62fSnathanw 
14534c915ebSnathanw 	_LOCKCOUNT(fp)--;
14634c915ebSnathanw 	if (_LOCKCOUNT(fp) == 0) {
14734c915ebSnathanw 		_LOCKOWNER(fp) = NULL;
14834c915ebSnathanw 		cond_signal(&_LOCKCOND(fp));
14934c915ebSnathanw 	}
15034c915ebSnathanw 
1513fdac2b8Sthorpej 	mutex_unlock(&_LOCK(fp));
1523fdac2b8Sthorpej }
1533fdac2b8Sthorpej 
1543fdac2b8Sthorpej #else /* _REENTRANT */
1553fdac2b8Sthorpej 
1563fdac2b8Sthorpej void
1573fdac2b8Sthorpej flockfile(FILE *fp)
1583fdac2b8Sthorpej {
1593fdac2b8Sthorpej 	/* LINTED deliberate lack of effect */
1603fdac2b8Sthorpej 	(void)fp;
1613fdac2b8Sthorpej 
1623fdac2b8Sthorpej 	return;
1633fdac2b8Sthorpej }
1643fdac2b8Sthorpej 
1653fdac2b8Sthorpej int
1663fdac2b8Sthorpej ftrylockfile(FILE *fp)
1673fdac2b8Sthorpej {
1683fdac2b8Sthorpej 	/* LINTED deliberate lack of effect */
1693fdac2b8Sthorpej 	(void)fp;
1703fdac2b8Sthorpej 
171*8744f75aSchristos 	return 0;
1723fdac2b8Sthorpej }
1733fdac2b8Sthorpej 
1743fdac2b8Sthorpej void
1753fdac2b8Sthorpej funlockfile(FILE *fp)
1763fdac2b8Sthorpej {
1773fdac2b8Sthorpej 	/* LINTED deliberate lack of effect */
1783fdac2b8Sthorpej 	(void)fp;
1793fdac2b8Sthorpej 
1803fdac2b8Sthorpej 	return;
1813fdac2b8Sthorpej }
1823fdac2b8Sthorpej 
1833fdac2b8Sthorpej #endif /* _REENTRANT */
184