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 5829ac6bd2SDaniel Eischen /* 5991e1be28SWarner Losh * We need to retain binary compatibility for a while. So pretend 6091e1be28SWarner Losh * that _lock is part of FILE * even though it is dereferenced off 6191e1be28SWarner Losh * _extra now. When we stop encoding the size of FILE into binaries 6291e1be28SWarner Losh * this can be changed in stdio.h. This will reduce the amount of 6391e1be28SWarner Losh * code that has to change in the future (just remove this comment 6491e1be28SWarner Losh * and #define). 6591e1be28SWarner Losh */ 6645d80087SDaniel Eischen #define _lock _extra 6729ac6bd2SDaniel Eischen 6829ac6bd2SDaniel Eischen void 6929ac6bd2SDaniel Eischen _flockfile(FILE *fp) 7029ac6bd2SDaniel Eischen { 7129ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 7229ac6bd2SDaniel Eischen 7344fce143SJohn Birrell if (fp->_lock->fl_owner == curthread) 7429ac6bd2SDaniel Eischen fp->_lock->fl_count++; 7529ac6bd2SDaniel Eischen else { 7629ac6bd2SDaniel Eischen /* 7729ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 7829ac6bd2SDaniel Eischen * internal mutex: 7929ac6bd2SDaniel Eischen */ 8029ac6bd2SDaniel Eischen _pthread_mutex_lock(&fp->_lock->fl_mutex); 8129ac6bd2SDaniel Eischen fp->_lock->fl_owner = curthread; 8229ac6bd2SDaniel Eischen fp->_lock->fl_count = 1; 8329ac6bd2SDaniel Eischen } 8429ac6bd2SDaniel Eischen } 85ec216c26SJohn Birrell 86ec216c26SJohn Birrell /* 8729ac6bd2SDaniel Eischen * This can be overriden by the threads library if it is linked in. 88ec216c26SJohn Birrell */ 89ec216c26SJohn Birrell void 90ec216c26SJohn Birrell _flockfile_debug_stub(FILE *fp, char *fname, int lineno) 91ec216c26SJohn Birrell { 9229ac6bd2SDaniel Eischen _flockfile(fp); 93ec216c26SJohn Birrell } 94ec216c26SJohn Birrell 95ec216c26SJohn Birrell int 9629ac6bd2SDaniel Eischen _ftrylockfile(FILE *fp) 97ec216c26SJohn Birrell { 9829ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 9929ac6bd2SDaniel Eischen int ret = 0; 100ec216c26SJohn Birrell 10144fce143SJohn Birrell if (fp->_lock->fl_owner == curthread) 10229ac6bd2SDaniel Eischen fp->_lock->fl_count++; 10329ac6bd2SDaniel Eischen /* 10429ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private 10529ac6bd2SDaniel Eischen * internal mutex: 10629ac6bd2SDaniel Eischen */ 10729ac6bd2SDaniel Eischen else if (_pthread_mutex_trylock(&fp->_lock->fl_mutex) == 0) { 10829ac6bd2SDaniel Eischen fp->_lock->fl_owner = curthread; 10929ac6bd2SDaniel Eischen fp->_lock->fl_count = 1; 11029ac6bd2SDaniel Eischen } 11129ac6bd2SDaniel Eischen else 11229ac6bd2SDaniel Eischen ret = -1; 11329ac6bd2SDaniel Eischen return (ret); 11429ac6bd2SDaniel Eischen } 11529ac6bd2SDaniel Eischen 116ec216c26SJohn Birrell void 11729ac6bd2SDaniel Eischen _funlockfile(FILE *fp) 118ec216c26SJohn Birrell { 11929ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self(); 12029ac6bd2SDaniel Eischen 12129ac6bd2SDaniel Eischen /* 12245d80087SDaniel Eischen * Check if this file is owned by the current thread: 12329ac6bd2SDaniel Eischen */ 12444fce143SJohn Birrell if (fp->_lock->fl_owner == curthread) { 12529ac6bd2SDaniel Eischen /* 12629ac6bd2SDaniel Eischen * Check if this thread has locked the FILE 12729ac6bd2SDaniel Eischen * more than once: 12829ac6bd2SDaniel Eischen */ 12929ac6bd2SDaniel Eischen if (fp->_lock->fl_count > 1) 13029ac6bd2SDaniel Eischen /* 13129ac6bd2SDaniel Eischen * Decrement the count of the number of 13229ac6bd2SDaniel Eischen * times the running thread has locked this 13329ac6bd2SDaniel Eischen * file: 13429ac6bd2SDaniel Eischen */ 13529ac6bd2SDaniel Eischen fp->_lock->fl_count--; 13629ac6bd2SDaniel Eischen else { 13729ac6bd2SDaniel Eischen /* 13829ac6bd2SDaniel Eischen * The running thread will release the 13929ac6bd2SDaniel Eischen * lock now: 14029ac6bd2SDaniel Eischen */ 14129ac6bd2SDaniel Eischen fp->_lock->fl_count = 0; 14229ac6bd2SDaniel Eischen fp->_lock->fl_owner = NULL; 14329ac6bd2SDaniel Eischen _pthread_mutex_unlock(&fp->_lock->fl_mutex); 14429ac6bd2SDaniel Eischen } 14529ac6bd2SDaniel Eischen } 146ec216c26SJohn Birrell } 147