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
3929ac6bd2SDaniel Eischen #include "namespace.h"
40ec216c26SJohn Birrell #include <stdio.h>
4129ac6bd2SDaniel Eischen #include <stdlib.h>
4229ac6bd2SDaniel Eischen #include <string.h>
4329ac6bd2SDaniel Eischen #include <pthread.h>
4429ac6bd2SDaniel Eischen #include "un-namespace.h"
45ec216c26SJohn Birrell
4645d80087SDaniel Eischen #include "local.h"
4745d80087SDaniel Eischen
4845d80087SDaniel Eischen
49ec216c26SJohn Birrell /*
5029ac6bd2SDaniel Eischen * Weak symbols for externally visible functions in this file:
51ec216c26SJohn Birrell */
5254fd7f68SDaniel Eischen __weak_reference(_flockfile, flockfile);
5354fd7f68SDaniel Eischen __weak_reference(_flockfile_debug_stub, _flockfile_debug);
5454fd7f68SDaniel Eischen __weak_reference(_ftrylockfile, ftrylockfile);
5554fd7f68SDaniel Eischen __weak_reference(_funlockfile, funlockfile);
5629ac6bd2SDaniel Eischen
577dcedc7aSCraig Rodrigues void _flockfile_debug_stub(FILE *, char *, int);
587dcedc7aSCraig Rodrigues int _ftrylockfile(FILE *);
59486828e8SCraig Rodrigues
6029ac6bd2SDaniel Eischen void
_flockfile(FILE * fp)6129ac6bd2SDaniel Eischen _flockfile(FILE *fp)
6229ac6bd2SDaniel Eischen {
6329ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self();
6429ac6bd2SDaniel Eischen
651e98f887SJohn Baldwin if (fp->_fl_owner == curthread)
661e98f887SJohn Baldwin fp->_fl_count++;
6729ac6bd2SDaniel Eischen else {
6829ac6bd2SDaniel Eischen /*
6929ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private
7029ac6bd2SDaniel Eischen * internal mutex:
7129ac6bd2SDaniel Eischen */
721e98f887SJohn Baldwin _pthread_mutex_lock(&fp->_fl_mutex);
731e98f887SJohn Baldwin fp->_fl_owner = curthread;
741e98f887SJohn Baldwin fp->_fl_count = 1;
7529ac6bd2SDaniel Eischen }
7629ac6bd2SDaniel Eischen }
77ec216c26SJohn Birrell
78ec216c26SJohn Birrell /*
7929ac6bd2SDaniel Eischen * This can be overriden by the threads library if it is linked in.
80ec216c26SJohn Birrell */
81ec216c26SJohn Birrell void
_flockfile_debug_stub(FILE * fp,char * fname,int lineno)82ec216c26SJohn Birrell _flockfile_debug_stub(FILE *fp, char *fname, int lineno)
83ec216c26SJohn Birrell {
8429ac6bd2SDaniel Eischen _flockfile(fp);
85ec216c26SJohn Birrell }
86ec216c26SJohn Birrell
87ec216c26SJohn Birrell int
_ftrylockfile(FILE * fp)8829ac6bd2SDaniel Eischen _ftrylockfile(FILE *fp)
89ec216c26SJohn Birrell {
9029ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self();
9129ac6bd2SDaniel Eischen int ret = 0;
92ec216c26SJohn Birrell
931e98f887SJohn Baldwin if (fp->_fl_owner == curthread)
941e98f887SJohn Baldwin fp->_fl_count++;
9529ac6bd2SDaniel Eischen /*
9629ac6bd2SDaniel Eischen * Make sure this mutex is treated as a private
9729ac6bd2SDaniel Eischen * internal mutex:
9829ac6bd2SDaniel Eischen */
991e98f887SJohn Baldwin else if (_pthread_mutex_trylock(&fp->_fl_mutex) == 0) {
1001e98f887SJohn Baldwin fp->_fl_owner = curthread;
1011e98f887SJohn Baldwin fp->_fl_count = 1;
10229ac6bd2SDaniel Eischen }
10329ac6bd2SDaniel Eischen else
10429ac6bd2SDaniel Eischen ret = -1;
10529ac6bd2SDaniel Eischen return (ret);
10629ac6bd2SDaniel Eischen }
10729ac6bd2SDaniel Eischen
108ec216c26SJohn Birrell void
_funlockfile(FILE * fp)10929ac6bd2SDaniel Eischen _funlockfile(FILE *fp)
110ec216c26SJohn Birrell {
11129ac6bd2SDaniel Eischen pthread_t curthread = _pthread_self();
11229ac6bd2SDaniel Eischen
11329ac6bd2SDaniel Eischen /*
11445d80087SDaniel Eischen * Check if this file is owned by the current thread:
11529ac6bd2SDaniel Eischen */
1161e98f887SJohn Baldwin if (fp->_fl_owner == curthread) {
11729ac6bd2SDaniel Eischen /*
11829ac6bd2SDaniel Eischen * Check if this thread has locked the FILE
11929ac6bd2SDaniel Eischen * more than once:
12029ac6bd2SDaniel Eischen */
1211e98f887SJohn Baldwin if (fp->_fl_count > 1)
12229ac6bd2SDaniel Eischen /*
12329ac6bd2SDaniel Eischen * Decrement the count of the number of
12429ac6bd2SDaniel Eischen * times the running thread has locked this
12529ac6bd2SDaniel Eischen * file:
12629ac6bd2SDaniel Eischen */
1271e98f887SJohn Baldwin fp->_fl_count--;
12829ac6bd2SDaniel Eischen else {
12929ac6bd2SDaniel Eischen /*
13029ac6bd2SDaniel Eischen * The running thread will release the
13129ac6bd2SDaniel Eischen * lock now:
13229ac6bd2SDaniel Eischen */
1331e98f887SJohn Baldwin fp->_fl_count = 0;
1341e98f887SJohn Baldwin fp->_fl_owner = NULL;
1351e98f887SJohn Baldwin _pthread_mutex_unlock(&fp->_fl_mutex);
13629ac6bd2SDaniel Eischen }
13729ac6bd2SDaniel Eischen }
138ec216c26SJohn Birrell }
139