xref: /freebsd/lib/libc/stdio/_flock_stub.c (revision 7dcf45c07b5d4417b12661360b94eeab4870db14)
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