LCOV - code coverage report
Current view: directory - src/shared/platform/posix - nacl_file_lock.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 125 112 89.6 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2013 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <errno.h>
       8                 : #include <string.h>
       9                 : #include <sys/file.h>
      10                 : 
      11                 : #include "native_client/src/shared/platform/posix/nacl_file_lock_intern.h"
      12                 : 
      13                 : #include "native_client/src/shared/platform/nacl_check.h"
      14                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      15                 : #include "native_client/src/shared/platform/nacl_log.h"
      16                 : #include "native_client/src/shared/platform/nacl_sync.h"
      17                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      18                 : 
      19                 : 
      20                 : static struct NaClFileLockEntry **NaClFileLockManagerFindEntryMu(
      21              60 :     struct NaClFileLockManager *self,
      22              60 :     struct NaClFileLockEntry const *key) {
      23              60 :   struct NaClFileLockEntry **pptr;
      24              60 :   struct NaClFileLockEntry *ptr;
      25                 : 
      26             164 :   for (pptr = &self->head; NULL != (ptr = *pptr); pptr = &ptr->next) {
      27             136 :     if (ptr->file_dev == key->file_dev &&
      28                 :         ptr->file_ino == key->file_ino) {
      29              46 :       return pptr;
      30                 :     }
      31              22 :   }
      32              14 :   return NULL;
      33              60 : }
      34                 : 
      35                 : static struct NaClFileLockEntry *NaClFileLockManagerEntryFactory(
      36              14 :     struct NaClFileLockManager *self,
      37              14 :     int desc) {
      38              14 :   struct NaClFileLockEntry *result;
      39                 : 
      40              14 :   result = malloc(sizeof *result);
      41              42 :   CHECK(NULL != result);
      42              14 :   (*self->set_file_identity_data)(result, desc);
      43              14 :   result->next = NULL;
      44              14 :   NaClXMutexCtor(&result->mu);
      45              14 :   NaClXCondVarCtor(&result->cv);
      46              14 :   result->holding_lock = 1;  /* caller is creating to hold the lock */
      47              14 :   result->num_waiting = 0;
      48              14 :   return result;
      49                 : }
      50                 : 
      51                 : static void NaClFileLockManagerFileEntryRecycler(
      52              14 :     struct NaClFileLockEntry **entryp) {
      53              14 :   struct NaClFileLockEntry *entry;
      54              42 :   CHECK(NULL != entryp);
      55              14 :   entry = *entryp;
      56              42 :   CHECK(0 == entry->holding_lock);
      57              42 :   CHECK(0 == entry->num_waiting);
      58              14 :   entry->file_dev = 0;
      59              14 :   entry->file_ino = 0;
      60              14 :   entry->next = NULL;
      61              14 :   NaClMutexDtor(&entry->mu);
      62              14 :   NaClCondVarDtor(&entry->cv);
      63              14 :   entry->holding_lock = 0;
      64              14 :   entry->num_waiting = 0;
      65              14 :   free(entry);
      66              14 :   *entryp = NULL;
      67              14 : }
      68                 : 
      69                 : static void NaClFileLockManagerSetFileIdentityData(
      70              37 :     struct NaClFileLockEntry *entry,
      71              37 :     int desc) {
      72              37 :   nacl_host_stat_t stbuf;
      73              37 :   if (0 != NACL_HOST_FSTAT64(desc, &stbuf)) {
      74               0 :     NaClLog(LOG_FATAL,
      75                 :             "NaClFileLockManagerSetFileIdentityData: fstat failed, desc %d,"
      76               0 :             " errno %d\n", desc, errno);
      77               0 :   }
      78              37 :   entry->file_dev = stbuf.st_dev;
      79              37 :   entry->file_ino = stbuf.st_ino;
      80              37 : }
      81                 : 
      82              15 : static void NaClFileLockManagerTakeLock(int desc) {
      83              15 :   if (0 != flock(desc, LOCK_EX)) {
      84               0 :     char buf[256];
      85               0 :     int err = errno;
      86               0 :     (void) strerror_r(err, buf, sizeof buf);
      87               0 :     NaClLog(LOG_FATAL,
      88                 :             "NaClFileLockManagerTakeLock: flock failed: %s (%d)\n",
      89                 :             buf, err);
      90               0 :   }
      91              15 : }
      92                 : 
      93              15 : static void NaClFileLockManagerDropLock(int desc) {
      94              15 :   if (0 != flock(desc, LOCK_UN)) {
      95               0 :     char buf[256];
      96               0 :     int err = errno;
      97               0 :     (void) strerror_r(err, buf, sizeof buf);
      98               0 :     NaClLog(LOG_FATAL,
      99                 :             "NaClFileLockManagerDropLock: flock failed: %s (%d)\n",
     100                 :             buf, err);
     101               0 :   }
     102              15 : }
     103                 : 
     104               8 : void NaClFileLockManagerCtor(struct NaClFileLockManager *self) {
     105               8 :   NaClXMutexCtor(&self->mu);
     106               8 :   self->head = NULL;
     107               8 :   self->set_file_identity_data = NaClFileLockManagerSetFileIdentityData;
     108               8 :   self->take_file_lock = NaClFileLockManagerTakeLock;
     109               8 :   self->drop_file_lock = NaClFileLockManagerDropLock;
     110               8 : }
     111                 : 
     112               8 : void NaClFileLockManagerDtor(struct NaClFileLockManager *self) {
     113              24 :   CHECK(NULL == self->head);
     114               8 :   NaClMutexDtor(&self->mu);
     115               8 : }
     116                 : 
     117              30 : void NaClFileLockManagerLock(struct NaClFileLockManager *self,
     118              30 :                              int desc) {
     119              30 :   struct NaClFileLockEntry key;
     120              30 :   struct NaClFileLockEntry **existing;
     121              30 :   struct NaClFileLockEntry *entry;
     122                 : 
     123              30 :   (*self->set_file_identity_data)(&key, desc);
     124                 : 
     125              30 :   NaClXMutexLock(&self->mu);
     126              30 :   existing = NaClFileLockManagerFindEntryMu(self, &key);
     127              30 :   if (NULL == existing) {
     128                 :     /* make new entry */
     129              14 :     entry = NaClFileLockManagerEntryFactory(self, desc);
     130              14 :     entry->next = self->head;
     131              14 :     self->head = entry;
     132              14 :     NaClXMutexUnlock(&self->mu);
     133              14 :   } else {
     134              16 :     entry = *existing;
     135              16 :     NaClXMutexLock(&entry->mu);
     136              16 :     entry->num_waiting++;
     137                 :     /* arithmetic overflow */
     138              48 :     CHECK(0 != entry->num_waiting);
     139                 :     /* drop container lock after ensuring that the entry will not be deleted */
     140              16 :     NaClXMutexUnlock(&self->mu);
     141              52 :     while (entry->holding_lock) {
     142              20 :       NaClXCondVarWait(&entry->cv, &entry->mu);
     143              20 :     }
     144              16 :     entry->holding_lock = 1;
     145              16 :     entry->num_waiting--;
     146              16 :     NaClXMutexUnlock(&entry->mu);
     147                 :   }
     148              30 :   (*self->take_file_lock)(desc);
     149              30 : }
     150                 : 
     151              30 : void NaClFileLockManagerUnlock(struct NaClFileLockManager *self,
     152              30 :                                int desc) {
     153              30 :   struct NaClFileLockEntry key;
     154              30 :   struct NaClFileLockEntry **existing;
     155              30 :   struct NaClFileLockEntry *entry;
     156                 : 
     157              30 :   (*self->set_file_identity_data)(&key, desc);
     158                 : 
     159              30 :   NaClXMutexLock(&self->mu);
     160              30 :   existing = NaClFileLockManagerFindEntryMu(self, &key);
     161              90 :   CHECK(NULL != existing);
     162              30 :   entry = *existing;
     163              30 :   NaClXMutexLock(&entry->mu);
     164              30 :   entry->holding_lock = 0;
     165              30 :   if (0 == entry->num_waiting) {
     166              14 :     *existing = entry->next;
     167              14 :     NaClXMutexUnlock(&entry->mu);
     168              14 :     NaClXMutexUnlock(&self->mu);
     169              14 :     NaClFileLockManagerFileEntryRecycler(&entry);
     170              14 :   } else {
     171              16 :     NaClXMutexUnlock(&self->mu);
     172                 :     /* tell waiting threads that they can now compete for the lock */
     173              16 :     NaClXCondVarBroadcast(&entry->cv);
     174              16 :     NaClXMutexUnlock(&entry->mu);
     175                 :   }
     176              30 :   (*self->drop_file_lock)(desc);
     177              30 : }

Generated by: LCOV version 1.7