diff options
Diffstat (limited to 'libc/stdio/flockfile.c')
-rw-r--r-- | libc/stdio/flockfile.c | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c deleted file mode 100644 index a81879e..0000000 --- a/libc/stdio/flockfile.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* implement flockfile(), ftrylockfile() and funlockfile() - * - * we can't use the OpenBSD implementation which uses kernel-specific - * APIs not available on Linux. - * - * Ideally, this would be trivially implemented by adding a - * pthread_mutex_t field to struct __sFILE as defined in - * <stdio.h>. - * - * However, since we don't want to bring pthread into the mix - * as well as change the size of a public API/ABI structure, - * we're going to store the data out-of-band. - * - * we use a hash-table to map FILE* pointers to recursive mutexes - * fclose() will call __fremovelock() defined below to remove - * a pointer from the table. - * - * the behaviour, if fclose() is called while the corresponding - * file is locked is totally undefined. - */ -#include <stdio.h> -#include <pthread.h> -#include <string.h> - -/* a node in the hash table */ -typedef struct FileLock { - struct FileLock* next; - FILE* file; - pthread_mutex_t mutex; -} FileLock; - -/* use a static hash table. We assume that we're not going to - * lock a really large number of FILE* objects on an embedded - * system. - */ -#define FILE_LOCK_BUCKETS 32 - -typedef struct { - pthread_mutex_t lock; - FileLock* buckets[ FILE_LOCK_BUCKETS ]; -} LockTable; - -static LockTable* _lockTable; -static pthread_once_t _lockTable_once = PTHREAD_ONCE_INIT; - -static void -lock_table_init( void ) -{ - _lockTable = malloc(sizeof(*_lockTable)); - if (_lockTable != NULL) { - pthread_mutex_init(&_lockTable->lock, NULL); - memset(_lockTable->buckets, 0, sizeof(_lockTable->buckets)); - } -} - -static LockTable* -lock_table_lock( void ) -{ - pthread_once( &_lockTable_once, lock_table_init ); - pthread_mutex_lock( &_lockTable->lock ); - return _lockTable; -} - -static void -lock_table_unlock( LockTable* t ) -{ - pthread_mutex_unlock( &t->lock ); -} - -static FileLock** -lock_table_lookup( LockTable* t, FILE* f ) -{ - uint32_t hash = (uint32_t)(void*)f; - FileLock** pnode; - - hash = (hash >> 2) ^ (hash << 17); - pnode = &t->buckets[hash % FILE_LOCK_BUCKETS]; - for (;;) { - FileLock* node = *pnode; - if (node == NULL || node->file == f) - break; - pnode = &node->next; - } - return pnode; -} - -void -flockfile(FILE * fp) -{ - LockTable* t = lock_table_lock(); - - if (t != NULL) { - FileLock** lookup = lock_table_lookup(t, fp); - FileLock* lock = *lookup; - - if (lock == NULL) { - pthread_mutexattr_t attr; - - /* create a new node in the hash table */ - lock = malloc(sizeof(*lock)); - if (lock == NULL) { - lock_table_unlock(t); - return; - } - lock->next = NULL; - lock->file = fp; - - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init( &lock->mutex, &attr ); - - *lookup = lock; - } - lock_table_unlock(t); - - /* we assume that another thread didn't destroy 'lock' - * by calling fclose() on the FILE*. This can happen if - * the client is *really* buggy, but we don't care about - * such code here. - */ - pthread_mutex_lock(&lock->mutex); - } -} - - -int -ftrylockfile(FILE *fp) -{ - int ret = -1; - LockTable* t = lock_table_lock(); - - if (t != NULL) { - FileLock** lookup = lock_table_lookup(t, fp); - FileLock* lock = *lookup; - - lock_table_unlock(t); - - /* see above comment about why we assume that 'lock' can - * be accessed from here - */ - if (lock != NULL && !pthread_mutex_trylock(&lock->mutex)) { - ret = 0; /* signal success */ - } - } - return ret; -} - -void -funlockfile(FILE * fp) -{ - LockTable* t = lock_table_lock(); - - if (t != NULL) { - FileLock** lookup = lock_table_lookup(t, fp); - FileLock* lock = *lookup; - - if (lock != NULL) - pthread_mutex_unlock(&lock->mutex); - - lock_table_unlock(t); - } -} - - -/* called from fclose() to remove the file lock */ -void -__fremovelock(FILE* fp) -{ - LockTable* t = lock_table_lock(); - - if (t != NULL) { - FileLock** lookup = lock_table_lookup(t, fp); - FileLock* lock = *lookup; - - if (lock != NULL) { - *lookup = lock->next; - lock->file = NULL; - } - lock_table_unlock(t); - - if (lock != NULL) - free(lock); - } -} |