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