Date: Sun, 04 Dec 2005 10:53:01 +0800 From: David Xu <davidxu@freebsd.org> To: David Xu <davidxu@freebsd.org> Cc: Jason Evans <jasone@canonware.com>, current@freebsd.org Subject: Re: New libc malloc patch Message-ID: <43925A0D.8070906@freebsd.org> In-Reply-To: <43924917.3070506@freebsd.org> References: <B6653214-2181-4342-854D-323979D23EE8@canonware.com> <Pine.LNX.4.53.0511291121360.27754@regurgitate.ugcs.caltech.edu> <0B746373-8C29-4ADF-9218-311AE08F3834@canonware.com> <4391569A.7080808@freebsd.org> <D1B3ED90-7936-41AA-93D3-AAC7E1615CDA@canonware.com> <43924917.3070506@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Here is sample code to implement a mutex by using umtx syscalls: #include <errno.h> #include <stddef.h> #include <sys/ucontext.h> #include <sys/umtx.h> #include <sys/types.h> #include <machine/atomic.h> #include <pthread.h> #define LCK_UNLOCKED 0 #define LCK_LOCKED 1 #define LCK_CONTENDED 2 void lock_mtx(struct umtx *mtx) { volatile uintptr_t *m = (volatile uintptr_t *)mtx; for (;;) { /* try to lock it. */ if (atomic_cmpset_acq_ptr(m, LCK_UNLOCKED, LCK_LOCKED)) return; if (atomic_load_acq_ptr(m) == LCK_LOCKED) { /* * if it was locked by single thread, try to * set it to contented state. */ if (!atomic_cmpset_acq_ptr(m, LCK_LOCKED, LCK_CONTENDED)) continue; } /* if in contented state, wait it to be unlocked. */ if (atomic_load_acq_ptr(m) == LCK_CONTENDED) _umtx_op((struct umtx *)m, UMTX_OP_WAIT, LCK_CONTENDED, 0, NULL); } } void unlock_mtx(struct umtx *mtx) { volatile uintptr_t *m = (volatile uintptr_t *)mtx; for (;;) { if (atomic_load_acq_ptr(m) == LCK_UNLOCKED) err(1, "unlock a unlocked mutex\n"); if (atomic_load_acq_ptr(m) == LCK_LOCKED) { if (atomic_cmpset_acq_ptr(m, LCK_LOCKED, LCK_UNLOCKED)) return; } if (atomic_load_acq_ptr(m) == LCK_CONTENDED) { atomic_store_rel_ptr(m, LCK_UNLOCKED); _umtx_op((struct umtx *)m, UMTX_OP_WAKE, 1, NULL, NULL); break; } } } struct umtx m; void * lock_test(void *arg) { int i = 0; for (i = 0; i < 10000; ++i) { lock_mtx(&m); pthread_yield(); unlock_mtx(&m); } return (0); } int main() { pthread_t td1, td2; pthread_create(&td1, NULL, lock_test, NULL); pthread_create(&td2, NULL, lock_test, NULL); pthread_join(td1, NULL); pthread_join(td2, NULL); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?43925A0D.8070906>