void flockfile(FILE * fp) { int idx = file_idx(fp); struct file_lock *p; /* Lock the hash table: */ _SPINLOCK(&hash_lock); /* Check if the static array has not been initialised: */ if (!init_done) { /* Initialise the global array: */ memset(flh,0,sizeof(flh)); /* Flag the initialisation as complete: */ init_done = 1; } /* Get a pointer to any existing lock for the file: */ if ((p = find_lock(idx, fp)) == NULL) { /* * The file is not locked, so this thread can * grab the lock: */ p = do_lock(idx, fp); /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); /* * The file is already locked, so check if the * running thread is the owner: */ } else if (p->owner == _thread_run) { /* * The running thread is already the * owner, so increment the count of * the number of times it has locked * the file: */ p->count++; /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); } else { /* * The file is locked for another thread. * Append this thread to the queue of * threads waiting on the lock. */ TAILQ_INSERT_TAIL(&p->l_head,_thread_run,qe); /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); /* Wait on the FILE lock: */ _thread_kern_sched_state(PS_FILE_WAIT, "", 0); } }
int (ftrylockfile)(FILE * fp) { int ret = -1; int idx = file_idx(fp); struct file_lock *p; /* Lock the hash table: */ _spinlock(&hash_lock); /* Get a pointer to any existing lock for the file: */ if ((p = find_lock(idx, fp)) == NULL) { /* * The file is not locked, so this thread can * grab the lock: */ p = do_lock(idx, fp); /* * The file is already locked, so check if the * running thread is the owner: */ } else if (p->owner == pthread_self()) { /* * The running thread is already the * owner, so increment the count of * the number of times it has locked * the file: */ p->count++; } else { /* * The file is locked for another thread, * so this try fails. */ p = NULL; } /* Unlock the hash table: */ _spinunlock(&hash_lock); /* Check if the lock was obtained: */ if (p != NULL) /* Return success: */ ret = 0; return (ret); }
void (flockfile)(FILE * fp) { int idx = file_idx(fp); struct file_lock *p; pthread_t self = pthread_self(); /* Lock the hash table: */ _spinlock(&hash_lock); /* Get a pointer to any existing lock for the file: */ if ((p = find_lock(idx, fp)) == NULL) { /* * The file is not locked, so this thread can * grab the lock: */ do_lock(idx, fp); /* * The file is already locked, so check if the * running thread is the owner: */ } else if (p->owner == self) { /* * The running thread is already the * owner, so increment the count of * the number of times it has locked * the file: */ p->count++; } else { /* * The file is locked for another thread. * Append this thread to the queue of * threads waiting on the lock. */ TAILQ_INSERT_TAIL(&p->lockers,self,waiting); while (p->owner != self) { __thrsleep(self, 0 | _USING_TICKETS, NULL, &hash_lock.ticket, NULL); _spinlock(&hash_lock); } } /* Unlock the hash table: */ _spinunlock(&hash_lock); }
void (funlockfile)(FILE * fp) { int idx = file_idx(fp); struct file_lock *p; /* Lock the hash table: */ _spinlock(&hash_lock); /* * Get a pointer to the lock for the file and check that * the running thread is the one with the lock: */ if ((p = find_lock(idx, fp)) != NULL && p->owner == pthread_self()) { /* * Check if this thread has locked the FILE * more than once: */ if (--p->count == 0) { /* Get the new owner of the lock: */ if ((p->owner = TAILQ_FIRST(&p->lockers)) != NULL) { /* Pop the thread off the queue: */ TAILQ_REMOVE(&p->lockers,p->owner,waiting); /* * This is the first lock for the new * owner: */ p->count = 1; __thrwakeup(p->owner, 1); } } } /* Unlock the hash table: */ _spinunlock(&hash_lock); }
void funlockfile(FILE * fp) { int idx = file_idx(fp); struct file_lock *p; /* * Defer signals to protect the scheduling queues from * access by the signal handler: */ _thread_kern_sig_defer(); /* Lock the hash table: */ _SPINLOCK(&hash_lock); /* * Get a pointer to the lock for the file and check that * the running thread is the one with the lock: */ if ((p = find_lock(idx, fp)) != NULL && p->owner == _thread_run) { /* * Check if this thread has locked the FILE * more than once: */ if (p->count > 1) /* * Decrement the count of the number of * times the running thread has locked this * file: */ p->count--; else { /* * The running thread will release the * lock now: */ p->count = 0; /* Get the new owner of the lock: */ if ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) { /* Pop the thread off the queue: */ TAILQ_REMOVE(&p->l_head,p->owner,qe); /* * This is the first lock for the new * owner: */ p->count = 1; /* Allow the new owner to run: */ PTHREAD_NEW_STATE(p->owner,PS_RUNNING); } } } /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); /* * Undefer and handle pending signals, yielding if * necessary: */ _thread_kern_sig_undefer(); }