1ec216c26SJohn Birrell /* 2ec216c26SJohn Birrell * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>. 3ec216c26SJohn Birrell * All rights reserved. 4ec216c26SJohn Birrell * 5ec216c26SJohn Birrell * Redistribution and use in source and binary forms, with or without 6ec216c26SJohn Birrell * modification, are permitted provided that the following conditions 7ec216c26SJohn Birrell * are met: 8ec216c26SJohn Birrell * 1. Redistributions of source code must retain the above copyright 9ec216c26SJohn Birrell * notice, this list of conditions and the following disclaimer. 10ec216c26SJohn Birrell * 2. Redistributions in binary form must reproduce the above copyright 11ec216c26SJohn Birrell * notice, this list of conditions and the following disclaimer in the 12ec216c26SJohn Birrell * documentation and/or other materials provided with the distribution. 137dcf45c0SWarner Losh * 3. Neither the name of the author nor the names of any co-contributors 14ec216c26SJohn Birrell * may be used to endorse or promote products derived from this software 15ec216c26SJohn Birrell * without specific prior written permission. 16ec216c26SJohn Birrell * 17ec216c26SJohn Birrell * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 18ec216c26SJohn Birrell * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19ec216c26SJohn Birrell * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20ec216c26SJohn Birrell * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21ec216c26SJohn Birrell * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22ec216c26SJohn Birrell * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23ec216c26SJohn Birrell * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24ec216c26SJohn Birrell * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25ec216c26SJohn Birrell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26ec216c26SJohn Birrell * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27ec216c26SJohn Birrell * SUCH DAMAGE. 28ec216c26SJohn Birrell */ 29ec216c26SJohn Birrell 3029ac6bd2SDaniel Eischen /* 3129ac6bd2SDaniel Eischen * POSIX stdio FILE locking functions. These assume that the locking 3229ac6bd2SDaniel Eischen * is only required at FILE structure level, not at file descriptor 3329ac6bd2SDaniel Eischen * level too. 3429ac6bd2SDaniel Eischen * 3529ac6bd2SDaniel Eischen */ 3629ac6bd2SDaniel Eischen 37333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 38333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 39333fc21eSDavid E. O'Brien 4029ac6bd2SDaniel Eischen #include "namespace.h" 41ec216c26SJohn Birrell #include <stdio.h> 4229ac6bd2SDaniel Eischen #include <stdlib.h> 4329ac6bd2SDaniel Eischen #include <string.h> 4429ac6bd2SDaniel Eischen #include <pthread.h> 4529ac6bd2SDaniel Eischen #include "un-namespace.h" 46ec216c26SJohn Birrell 4745d80087SDaniel Eischen #include "local.h" 4845d80087SDaniel Eischen 4945d80087SDaniel Eischen 50ec216c26SJohn Birrell /* 5129ac6bd2SDaniel Eischen * Weak symbols for externally visible functions in this file: 52ec216c26SJohn Birrell */ 5354fd7f68SDaniel Eischen __weak_reference(_flockfile, flockfile); 5454fd7f68SDaniel Eischen __weak_reference(_flockfile_debug_stub, _flockfile_debug); 5554fd7f68SDaniel Eischen __weak_reference(_ftrylockfile, ftrylockfile); 5654fd7f68SDaniel Eischen __weak_reference(_funlockfile, funlockfile); 5729ac6bd2SDaniel Eischen 58*486828e8SCraig Rodrigues void _flockfile_debug_stub(FILE *fp, char *fname, int lineno); 59*486828e8SCraig Rodrigues int _ftrylockfile(FILE *fp); 60*486828e8SCraig Rodrigues 6129ac6bd2SDaniel Eischen void 6229ac6bd2SDaniel Eischen _flockfile(FILE *fp) 6329ac6bd2SDaniel Eischen { 6429ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 6529ac6bd2SDaniel Eischen 661e98f887SJohn Baldwin if (fp->_fl_owner == curthread) 671e98f887SJohn Baldwin fp->_fl_count++; 6829ac6bd2SDaniel Eischen else { 6929ac6bd2SDaniel Eischen /* 7029ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 7129ac6bd2SDaniel Eischen * internal mutex: 7229ac6bd2SDaniel Eischen */ 731e98f887SJohn Baldwin _pthread_mutex_lock(&fp->_fl_mutex); 741e98f887SJohn Baldwin fp->_fl_owner = curthread; 751e98f887SJohn Baldwin fp->_fl_count = 1; 7629ac6bd2SDaniel Eischen } 7729ac6bd2SDaniel Eischen } 78ec216c26SJohn Birrell 79ec216c26SJohn Birrell /* 8029ac6bd2SDaniel Eischen * This can be overriden by the threads library if it is linked in. 81ec216c26SJohn Birrell */ 82ec216c26SJohn Birrell void 83ec216c26SJohn Birrell _flockfile_debug_stub(FILE *fp, char *fname, int lineno) 84ec216c26SJohn Birrell { 8529ac6bd2SDaniel Eischen _flockfile(fp); 86ec216c26SJohn Birrell } 87ec216c26SJohn Birrell 88ec216c26SJohn Birrell int 8929ac6bd2SDaniel Eischen _ftrylockfile(FILE *fp) 90ec216c26SJohn Birrell { 9129ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 9229ac6bd2SDaniel Eischen int ret = 0; 93ec216c26SJohn Birrell 941e98f887SJohn Baldwin if (fp->_fl_owner == curthread) 951e98f887SJohn Baldwin fp->_fl_count++; 9629ac6bd2SDaniel Eischen /* 9729ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 9829ac6bd2SDaniel Eischen * internal mutex: 9929ac6bd2SDaniel Eischen */ 1001e98f887SJohn Baldwin else if (_pthread_mutex_trylock(&fp->_fl_mutex) == 0) { 1011e98f887SJohn Baldwin fp->_fl_owner = curthread; 1021e98f887SJohn Baldwin fp->_fl_count = 1; 10329ac6bd2SDaniel Eischen } 10429ac6bd2SDaniel Eischen else 10529ac6bd2SDaniel Eischen ret = -1; 10629ac6bd2SDaniel Eischen return (ret); 10729ac6bd2SDaniel Eischen } 10829ac6bd2SDaniel Eischen 109ec216c26SJohn Birrell void 11029ac6bd2SDaniel Eischen _funlockfile(FILE *fp) 111ec216c26SJohn Birrell { 11229ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 11329ac6bd2SDaniel Eischen 11429ac6bd2SDaniel Eischen /* 11545d80087SDaniel Eischen * Check if this file is owned by the current thread: 11629ac6bd2SDaniel Eischen */ 1171e98f887SJohn Baldwin if (fp->_fl_owner == curthread) { 11829ac6bd2SDaniel Eischen /* 11929ac6bd2SDaniel Eischen * Check if this thread has locked the FILE 12029ac6bd2SDaniel Eischen * more than once: 12129ac6bd2SDaniel Eischen */ 1221e98f887SJohn Baldwin if (fp->_fl_count > 1) 12329ac6bd2SDaniel Eischen /* 12429ac6bd2SDaniel Eischen * Decrement the count of the number of 12529ac6bd2SDaniel Eischen * times the running thread has locked this 12629ac6bd2SDaniel Eischen * file: 12729ac6bd2SDaniel Eischen */ 1281e98f887SJohn Baldwin fp->_fl_count--; 12929ac6bd2SDaniel Eischen else { 13029ac6bd2SDaniel Eischen /* 13129ac6bd2SDaniel Eischen * The running thread will release the 13229ac6bd2SDaniel Eischen * lock now: 13329ac6bd2SDaniel Eischen */ 1341e98f887SJohn Baldwin fp->_fl_count = 0; 1351e98f887SJohn Baldwin fp->_fl_owner = NULL; 1361e98f887SJohn Baldwin _pthread_mutex_unlock(&fp->_fl_mutex); 13729ac6bd2SDaniel Eischen } 13829ac6bd2SDaniel Eischen } 139ec216c26SJohn Birrell } 140