libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

thread_pthread.c (3258B)


      1 /* Written by Kris Maglione <maglione.k at Gmail> */
      2 /* Public domain */
      3 #define _XOPEN_SOURCE 600
      4 #include <errno.h>
      5 #include <pthread.h>
      6 #include <stdlib.h>
      7 #include <unistd.h>
      8 #include "ixp_local.h"
      9 
     10 static IxpThread ixp_pthread;
     11 static pthread_key_t errstr_k;
     12 
     13 /**
     14  * Function: ixp_pthread_init
     15  *
     16  * This function initializes libixp for use in multithreaded
     17  * programs using the POSIX thread system. When using libixp in such
     18  * programs, this function must be called before any other libixp
     19  * functions. This function is part of libixp_pthread, which you
     20  * must explicitly link against.
     21  */
     22 int
     23 ixp_pthread_init() {
     24 	int ret;
     25 
     26 	IXP_ASSERT_VERSION;
     27 
     28 	ret = pthread_key_create(&errstr_k, free);
     29 	if(ret) {
     30 		werrstr("can't create TLS value: %s", ixp_errbuf());
     31 		return 1;
     32 	}
     33 
     34 	ixp_thread = &ixp_pthread;
     35 	return 0;
     36 }
     37 
     38 static char*
     39 errbuf(void) {
     40 	char *ret;
     41 
     42 	ret = pthread_getspecific(errstr_k);
     43 	if(ret == nil) {
     44 		ret = emallocz(IXP_ERRMAX);
     45 		pthread_setspecific(errstr_k, (void*)ret);
     46 	}
     47 	return ret;
     48 }
     49 
     50 static void
     51 mlock(IxpMutex *m) {
     52 	pthread_mutex_lock(m->aux);
     53 }
     54 
     55 static int
     56 mcanlock(IxpMutex *m) {
     57 	return !pthread_mutex_trylock(m->aux);
     58 }
     59 
     60 static void
     61 munlock(IxpMutex *m) {
     62 	pthread_mutex_unlock(m->aux);
     63 }
     64 
     65 static void
     66 mdestroy(IxpMutex *m) {
     67 	pthread_mutex_destroy(m->aux);
     68 	free(m->aux);
     69 }
     70 
     71 static int
     72 initmutex(IxpMutex *m) {
     73 	pthread_mutex_t *mutex;
     74 
     75 	mutex = emalloc(sizeof *mutex);
     76 	if(pthread_mutex_init(mutex, nil)) {
     77 		free(mutex);
     78 		return 1;
     79 	}
     80 
     81 	m->aux = mutex;
     82 	return 0;
     83 }
     84 
     85 static void
     86 rlock(IxpRWLock *rw) {
     87 	pthread_rwlock_rdlock(rw->aux);
     88 }
     89 
     90 static int
     91 canrlock(IxpRWLock *rw) {
     92 	return !pthread_rwlock_tryrdlock(rw->aux);
     93 }
     94 
     95 static void
     96 wlock(IxpRWLock *rw) {
     97 	pthread_rwlock_rdlock(rw->aux);
     98 }
     99 
    100 static int
    101 canwlock(IxpRWLock *rw) {
    102 	return !pthread_rwlock_tryrdlock(rw->aux);
    103 }
    104 
    105 static void
    106 rwunlock(IxpRWLock *rw) {
    107 	pthread_rwlock_unlock(rw->aux);
    108 }
    109 
    110 static void
    111 rwdestroy(IxpRWLock *rw) {
    112 	pthread_rwlock_destroy(rw->aux);
    113 	free(rw->aux);
    114 }
    115 
    116 static int
    117 initrwlock(IxpRWLock *rw) {
    118 	pthread_rwlock_t *rwlock;
    119 
    120 	rwlock = emalloc(sizeof *rwlock);
    121 	if(pthread_rwlock_init(rwlock, nil)) {
    122 		free(rwlock);
    123 		return 1;
    124 	}
    125 
    126 	rw->aux = rwlock;
    127 	return 0;
    128 }
    129 
    130 static void
    131 rsleep(IxpRendez *r) {
    132 	pthread_cond_wait(r->aux, r->mutex->aux);
    133 }
    134 
    135 static int
    136 rwake(IxpRendez *r) {
    137 	pthread_cond_signal(r->aux);
    138 	return 0;
    139 }
    140 
    141 static int
    142 rwakeall(IxpRendez *r) {
    143 	pthread_cond_broadcast(r->aux);
    144 	return 0;
    145 }
    146 
    147 static void
    148 rdestroy(IxpRendez *r) {
    149 	pthread_cond_destroy(r->aux);
    150 	free(r->aux);
    151 }
    152 
    153 static int
    154 initrendez(IxpRendez *r) {
    155 	pthread_cond_t *cond;
    156 
    157 	cond = emalloc(sizeof *cond);
    158 	if(pthread_cond_init(cond, nil)) {
    159 		free(cond);
    160 		return 1;
    161 	}
    162 
    163 	r->aux = cond;
    164 	return 0;
    165 }
    166 
    167 static IxpThread ixp_pthread = {
    168 	/* Mutex */
    169 	.initmutex = initmutex,
    170 	.lock = mlock,
    171 	.canlock = mcanlock,
    172 	.unlock = munlock,
    173 	.mdestroy = mdestroy,
    174 	/* RWLock */
    175 	.initrwlock = initrwlock,
    176 	.rlock = rlock,
    177 	.canrlock = canrlock,
    178 	.wlock = wlock,
    179 	.canwlock = canwlock,
    180 	.runlock = rwunlock,
    181 	.wunlock = rwunlock,
    182 	.rwdestroy = rwdestroy,
    183 	/* Rendez */
    184 	.initrendez = initrendez,
    185 	.sleep = rsleep,
    186 	.wake = rwake,
    187 	.wakeall = rwakeall,
    188 	.rdestroy = rdestroy,
    189 	/* Other */
    190 	.errbuf = errbuf,
    191 	.read = read,
    192 	.write = write,
    193 	.select = select,
    194 };
    195