Home | History | Annotate | Line # | Download | only in libpthread
pthread_mutex.c revision 1.1.2.1
      1  1.1.2.1  nathanw /* Copyright */
      2  1.1.2.1  nathanw 
      3  1.1.2.1  nathanw #include <assert.h>
      4  1.1.2.1  nathanw #include <errno.h>
      5  1.1.2.1  nathanw #include <signal.h>
      6  1.1.2.1  nathanw #include <stdlib.h>
      7  1.1.2.1  nathanw #include <ucontext.h>
      8  1.1.2.1  nathanw #include <sys/queue.h>
      9  1.1.2.1  nathanw 
     10  1.1.2.1  nathanw #include "pthread.h"
     11  1.1.2.1  nathanw #include "pthread_int.h"
     12  1.1.2.1  nathanw #include "pthread_mutex.h"
     13  1.1.2.1  nathanw 
     14  1.1.2.1  nathanw 
     15  1.1.2.1  nathanw 
     16  1.1.2.1  nathanw 
     17  1.1.2.1  nathanw int
     18  1.1.2.1  nathanw pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
     19  1.1.2.1  nathanw {
     20  1.1.2.1  nathanw 	pthread_mutex_t newmutex;
     21  1.1.2.1  nathanw 
     22  1.1.2.1  nathanw 	assert(mutex != NULL);
     23  1.1.2.1  nathanw 
     24  1.1.2.1  nathanw 	/* XXX No mutex attr support yet. */
     25  1.1.2.1  nathanw 	if (attr != NULL)
     26  1.1.2.1  nathanw 		return EINVAL;
     27  1.1.2.1  nathanw 
     28  1.1.2.1  nathanw 	/* Allocate. */
     29  1.1.2.1  nathanw 	newmutex = pthread__malloc(sizeof(struct pthread_mutex_st));
     30  1.1.2.1  nathanw 	if (newmutex == NULL)
     31  1.1.2.1  nathanw 		return ENOMEM;
     32  1.1.2.1  nathanw 
     33  1.1.2.1  nathanw 	newmutex->ptm_magic = PT_MUTEX_MAGIC;
     34  1.1.2.1  nathanw 	newmutex->ptm_owner = NULL;
     35  1.1.2.1  nathanw 	SIMPLEQ_INIT(&newmutex->ptm_blocked);
     36  1.1.2.1  nathanw 
     37  1.1.2.1  nathanw 	*mutex = newmutex;
     38  1.1.2.1  nathanw 
     39  1.1.2.1  nathanw 	return 0;
     40  1.1.2.1  nathanw }
     41  1.1.2.1  nathanw 
     42  1.1.2.1  nathanw 
     43  1.1.2.1  nathanw int
     44  1.1.2.1  nathanw pthread_mutex_destroy(pthread_mutex_t *mutex)
     45  1.1.2.1  nathanw {
     46  1.1.2.1  nathanw 
     47  1.1.2.1  nathanw 	if ((mutex == NULL) || (*mutex == NULL) ||
     48  1.1.2.1  nathanw 	    (*mutex)->ptm_magic != PT_MUTEX_MAGIC)
     49  1.1.2.1  nathanw 		return EINVAL;
     50  1.1.2.1  nathanw 
     51  1.1.2.1  nathanw 	(*mutex)->ptm_magic = PT_MUTEX_DEAD;
     52  1.1.2.1  nathanw 	pthread__free(*mutex);
     53  1.1.2.1  nathanw 
     54  1.1.2.1  nathanw 	return 0;
     55  1.1.2.1  nathanw }
     56  1.1.2.1  nathanw 
     57  1.1.2.1  nathanw 
     58  1.1.2.1  nathanw int
     59  1.1.2.1  nathanw pthread_mutex_lock(pthread_mutex_t *mutex)
     60  1.1.2.1  nathanw {
     61  1.1.2.1  nathanw 	pthread_t self;
     62  1.1.2.1  nathanw 
     63  1.1.2.1  nathanw 	if ((mutex == NULL) || (*mutex == NULL) ||
     64  1.1.2.1  nathanw 	    (*mutex)->ptm_magic != PT_MUTEX_MAGIC)
     65  1.1.2.1  nathanw 		return EINVAL;
     66  1.1.2.1  nathanw 
     67  1.1.2.1  nathanw 	self = pthread__self();
     68  1.1.2.1  nathanw 
     69  1.1.2.1  nathanw 	pthread_spinlock(self, &(*mutex)->ptm_interlock);
     70  1.1.2.1  nathanw 
     71  1.1.2.1  nathanw 	while ((*mutex)->ptm_locked == PT_MUTEX_LOCKED) {
     72  1.1.2.1  nathanw 		/* Put ourselves on the queue and go to sleep. */
     73  1.1.2.1  nathanw 		SIMPLEQ_INSERT_TAIL(&(*mutex)->ptm_blocked, self, pt_sleep);
     74  1.1.2.1  nathanw 
     75  1.1.2.1  nathanw 		self->pt_state = PT_STATE_BLOCKED;
     76  1.1.2.1  nathanw 		pthread__block(self, &(*mutex)->ptm_interlock);
     77  1.1.2.1  nathanw 
     78  1.1.2.1  nathanw 		/* We're back. Try again. */
     79  1.1.2.1  nathanw 		pthread_spinlock(self, &(*mutex)->ptm_interlock);
     80  1.1.2.1  nathanw 	}
     81  1.1.2.1  nathanw 
     82  1.1.2.1  nathanw 	assert((*mutex)->ptm_locked == PT_MUTEX_UNLOCKED);
     83  1.1.2.1  nathanw 
     84  1.1.2.1  nathanw 	/* We have the interlock; go for the real thing. */
     85  1.1.2.1  nathanw 	(*mutex)->ptm_locked = PT_MUTEX_LOCKED;
     86  1.1.2.1  nathanw 	(*mutex)->ptm_owner = self;
     87  1.1.2.1  nathanw 
     88  1.1.2.1  nathanw 	pthread_spinunlock(self, &(*mutex)->ptm_interlock);
     89  1.1.2.1  nathanw 
     90  1.1.2.1  nathanw 	return 0;
     91  1.1.2.1  nathanw }
     92  1.1.2.1  nathanw 
     93  1.1.2.1  nathanw 
     94  1.1.2.1  nathanw int
     95  1.1.2.1  nathanw pthread_mutex_trylock(pthread_mutex_t *mutex)
     96  1.1.2.1  nathanw {
     97  1.1.2.1  nathanw 	pthread_t self;
     98  1.1.2.1  nathanw 
     99  1.1.2.1  nathanw 	if ((mutex == NULL) || (*mutex == NULL) ||
    100  1.1.2.1  nathanw 	    (*mutex)->ptm_magic != PT_MUTEX_MAGIC)
    101  1.1.2.1  nathanw 		return EINVAL;
    102  1.1.2.1  nathanw 
    103  1.1.2.1  nathanw 	if ((*mutex)->ptm_locked == PT_MUTEX_LOCKED)
    104  1.1.2.1  nathanw 		return EBUSY;
    105  1.1.2.1  nathanw 
    106  1.1.2.1  nathanw 	self = pthread__self();
    107  1.1.2.1  nathanw 
    108  1.1.2.1  nathanw 	pthread_spinlock(self, &(*mutex)->ptm_interlock);
    109  1.1.2.1  nathanw 	if ((*mutex)->ptm_locked == PT_MUTEX_LOCKED) {
    110  1.1.2.1  nathanw 		pthread_spinunlock(self, &(*mutex)->ptm_interlock);
    111  1.1.2.1  nathanw 		return EBUSY;
    112  1.1.2.1  nathanw 	}
    113  1.1.2.1  nathanw 
    114  1.1.2.1  nathanw 	assert((*mutex)->ptm_locked == PT_MUTEX_UNLOCKED);
    115  1.1.2.1  nathanw 
    116  1.1.2.1  nathanw 	/* We have the interlock; go for the real thing. */
    117  1.1.2.1  nathanw 	(*mutex)->ptm_locked = PT_MUTEX_LOCKED;
    118  1.1.2.1  nathanw 	(*mutex)->ptm_owner = self;
    119  1.1.2.1  nathanw 
    120  1.1.2.1  nathanw 	pthread_spinunlock(self, &(*mutex)->ptm_interlock);
    121  1.1.2.1  nathanw 
    122  1.1.2.1  nathanw 	return 0;
    123  1.1.2.1  nathanw }
    124  1.1.2.1  nathanw 
    125  1.1.2.1  nathanw 
    126  1.1.2.1  nathanw int
    127  1.1.2.1  nathanw pthread_mutex_unlock(pthread_mutex_t *mutex)
    128  1.1.2.1  nathanw {
    129  1.1.2.1  nathanw 	pthread_t self, blocked;
    130  1.1.2.1  nathanw 
    131  1.1.2.1  nathanw 	if ((mutex == NULL) || (*mutex == NULL) ||
    132  1.1.2.1  nathanw 	    (*mutex)->ptm_magic != PT_MUTEX_MAGIC)
    133  1.1.2.1  nathanw 		return EINVAL;
    134  1.1.2.1  nathanw 
    135  1.1.2.1  nathanw 	if ((*mutex)->ptm_locked == PT_MUTEX_UNLOCKED)
    136  1.1.2.1  nathanw 		return EPERM; /* Not exactly the right error. */
    137  1.1.2.1  nathanw 
    138  1.1.2.1  nathanw 	assert((*mutex)->ptm_locked == PT_MUTEX_LOCKED);
    139  1.1.2.1  nathanw 
    140  1.1.2.1  nathanw 	/* One is only permitted to unlock one's own mutexes. */
    141  1.1.2.1  nathanw 	self = pthread__self();
    142  1.1.2.1  nathanw 	if ((*mutex)->ptm_owner != self)
    143  1.1.2.1  nathanw 		return EPERM;
    144  1.1.2.1  nathanw 
    145  1.1.2.1  nathanw 	pthread_spinlock(self, &(*mutex)->ptm_interlock);
    146  1.1.2.1  nathanw 	(*mutex)->ptm_locked = PT_MUTEX_UNLOCKED;
    147  1.1.2.1  nathanw 	(*mutex)->ptm_owner = NULL;
    148  1.1.2.1  nathanw 
    149  1.1.2.1  nathanw 	blocked = SIMPLEQ_FIRST(&(*mutex)->ptm_blocked);
    150  1.1.2.1  nathanw 	if (blocked)
    151  1.1.2.1  nathanw 		SIMPLEQ_REMOVE_HEAD(&(*mutex)->ptm_blocked, blocked, pt_sleep);
    152  1.1.2.1  nathanw 
    153  1.1.2.1  nathanw 	pthread_spinunlock(self, &(*mutex)->ptm_interlock);
    154  1.1.2.1  nathanw 
    155  1.1.2.1  nathanw 	if (blocked)
    156  1.1.2.1  nathanw 		pthread__sched(self, blocked);
    157  1.1.2.1  nathanw 
    158  1.1.2.1  nathanw 	return 0;
    159  1.1.2.1  nathanw }
    160