1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 4ec216c26SJohn Birrell * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>. 5ec216c26SJohn Birrell * All rights reserved. 6ec216c26SJohn Birrell * 7ec216c26SJohn Birrell * Redistribution and use in source and binary forms, with or without 8ec216c26SJohn Birrell * modification, are permitted provided that the following conditions 9ec216c26SJohn Birrell * are met: 10ec216c26SJohn Birrell * 1. Redistributions of source code must retain the above copyright 11ec216c26SJohn Birrell * notice, this list of conditions and the following disclaimer. 12ec216c26SJohn Birrell * 2. Redistributions in binary form must reproduce the above copyright 13ec216c26SJohn Birrell * notice, this list of conditions and the following disclaimer in the 14ec216c26SJohn Birrell * documentation and/or other materials provided with the distribution. 157dcf45c0SWarner Losh * 3. Neither the name of the author nor the names of any co-contributors 16ec216c26SJohn Birrell * may be used to endorse or promote products derived from this software 17ec216c26SJohn Birrell * without specific prior written permission. 18ec216c26SJohn Birrell * 19ec216c26SJohn Birrell * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 20ec216c26SJohn Birrell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21ec216c26SJohn Birrell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22ec216c26SJohn Birrell * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23ec216c26SJohn Birrell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24ec216c26SJohn Birrell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25ec216c26SJohn Birrell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26ec216c26SJohn Birrell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27ec216c26SJohn Birrell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28ec216c26SJohn Birrell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29ec216c26SJohn Birrell * SUCH DAMAGE. 30ec216c26SJohn Birrell */ 31ec216c26SJohn Birrell 3229ac6bd2SDaniel Eischen /* 3329ac6bd2SDaniel Eischen * POSIX stdio FILE locking functions. These assume that the locking 3429ac6bd2SDaniel Eischen * is only required at FILE structure level, not at file descriptor 3529ac6bd2SDaniel Eischen * level too. 3629ac6bd2SDaniel Eischen * 3729ac6bd2SDaniel Eischen */ 3829ac6bd2SDaniel Eischen 39333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 40333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 41333fc21eSDavid E. O'Brien 4229ac6bd2SDaniel Eischen #include "namespace.h" 43ec216c26SJohn Birrell #include <stdio.h> 4429ac6bd2SDaniel Eischen #include <stdlib.h> 4529ac6bd2SDaniel Eischen #include <string.h> 4629ac6bd2SDaniel Eischen #include <pthread.h> 4729ac6bd2SDaniel Eischen #include "un-namespace.h" 48ec216c26SJohn Birrell 4945d80087SDaniel Eischen #include "local.h" 5045d80087SDaniel Eischen 5145d80087SDaniel Eischen 52ec216c26SJohn Birrell /* 5329ac6bd2SDaniel Eischen * Weak symbols for externally visible functions in this file: 54ec216c26SJohn Birrell */ 5554fd7f68SDaniel Eischen __weak_reference(_flockfile, flockfile); 5654fd7f68SDaniel Eischen __weak_reference(_flockfile_debug_stub, _flockfile_debug); 5754fd7f68SDaniel Eischen __weak_reference(_ftrylockfile, ftrylockfile); 5854fd7f68SDaniel Eischen __weak_reference(_funlockfile, funlockfile); 5929ac6bd2SDaniel Eischen 607dcedc7aSCraig Rodrigues void _flockfile_debug_stub(FILE *, char *, int); 617dcedc7aSCraig Rodrigues int _ftrylockfile(FILE *); 62486828e8SCraig Rodrigues 6329ac6bd2SDaniel Eischen void 6429ac6bd2SDaniel Eischen _flockfile(FILE *fp) 6529ac6bd2SDaniel Eischen { 6629ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 6729ac6bd2SDaniel Eischen 681e98f887SJohn Baldwin if (fp->_fl_owner == curthread) 691e98f887SJohn Baldwin fp->_fl_count++; 7029ac6bd2SDaniel Eischen else { 7129ac6bd2SDaniel Eischen /* 7229ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 7329ac6bd2SDaniel Eischen * internal mutex: 7429ac6bd2SDaniel Eischen */ 751e98f887SJohn Baldwin _pthread_mutex_lock(&fp->_fl_mutex); 761e98f887SJohn Baldwin fp->_fl_owner = curthread; 771e98f887SJohn Baldwin fp->_fl_count = 1; 7829ac6bd2SDaniel Eischen } 7929ac6bd2SDaniel Eischen } 80ec216c26SJohn Birrell 81ec216c26SJohn Birrell /* 8229ac6bd2SDaniel Eischen * This can be overriden by the threads library if it is linked in. 83ec216c26SJohn Birrell */ 84ec216c26SJohn Birrell void 85ec216c26SJohn Birrell _flockfile_debug_stub(FILE *fp, char *fname, int lineno) 86ec216c26SJohn Birrell { 8729ac6bd2SDaniel Eischen _flockfile(fp); 88ec216c26SJohn Birrell } 89ec216c26SJohn Birrell 90ec216c26SJohn Birrell int 9129ac6bd2SDaniel Eischen _ftrylockfile(FILE *fp) 92ec216c26SJohn Birrell { 9329ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 9429ac6bd2SDaniel Eischen int ret = 0; 95ec216c26SJohn Birrell 961e98f887SJohn Baldwin if (fp->_fl_owner == curthread) 971e98f887SJohn Baldwin fp->_fl_count++; 9829ac6bd2SDaniel Eischen /* 9929ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 10029ac6bd2SDaniel Eischen * internal mutex: 10129ac6bd2SDaniel Eischen */ 1021e98f887SJohn Baldwin else if (_pthread_mutex_trylock(&fp->_fl_mutex) == 0) { 1031e98f887SJohn Baldwin fp->_fl_owner = curthread; 1041e98f887SJohn Baldwin fp->_fl_count = 1; 10529ac6bd2SDaniel Eischen } 10629ac6bd2SDaniel Eischen else 10729ac6bd2SDaniel Eischen ret = -1; 10829ac6bd2SDaniel Eischen return (ret); 10929ac6bd2SDaniel Eischen } 11029ac6bd2SDaniel Eischen 111ec216c26SJohn Birrell void 11229ac6bd2SDaniel Eischen _funlockfile(FILE *fp) 113ec216c26SJohn Birrell { 11429ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 11529ac6bd2SDaniel Eischen 11629ac6bd2SDaniel Eischen /* 11745d80087SDaniel Eischen * Check if this file is owned by the current thread: 11829ac6bd2SDaniel Eischen */ 1191e98f887SJohn Baldwin if (fp->_fl_owner == curthread) { 12029ac6bd2SDaniel Eischen /* 12129ac6bd2SDaniel Eischen * Check if this thread has locked the FILE 12229ac6bd2SDaniel Eischen * more than once: 12329ac6bd2SDaniel Eischen */ 1241e98f887SJohn Baldwin if (fp->_fl_count > 1) 12529ac6bd2SDaniel Eischen /* 12629ac6bd2SDaniel Eischen * Decrement the count of the number of 12729ac6bd2SDaniel Eischen * times the running thread has locked this 12829ac6bd2SDaniel Eischen * file: 12929ac6bd2SDaniel Eischen */ 1301e98f887SJohn Baldwin fp->_fl_count--; 13129ac6bd2SDaniel Eischen else { 13229ac6bd2SDaniel Eischen /* 13329ac6bd2SDaniel Eischen * The running thread will release the 13429ac6bd2SDaniel Eischen * lock now: 13529ac6bd2SDaniel Eischen */ 1361e98f887SJohn Baldwin fp->_fl_count = 0; 1371e98f887SJohn Baldwin fp->_fl_owner = NULL; 1381e98f887SJohn Baldwin _pthread_mutex_unlock(&fp->_fl_mutex); 13929ac6bd2SDaniel Eischen } 14029ac6bd2SDaniel Eischen } 141ec216c26SJohn Birrell } 142