mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-29 08:42:28 +00:00
Get rid of kmalloc()
This changes *NSYNC to allocate waiters on the stack so our locks don't need to depend on dynamic memory. This make our runtiem simpler, and it also fixes bugs with thread cancellation support.
This commit is contained in:
parent
77a7873057
commit
a359de7893
57 changed files with 405 additions and 472 deletions
91
third_party/nsync/common.c
vendored
91
third_party/nsync/common.c
vendored
|
@ -16,10 +16,6 @@
|
|||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/kmalloc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/nsync/atomic.h"
|
||||
#include "third_party/nsync/atomic.internal.h"
|
||||
|
@ -147,78 +143,25 @@ waiter *nsync_dll_waiter_samecond_ (struct Dll *e) {
|
|||
|
||||
/* -------------------------------- */
|
||||
|
||||
static struct Dll *free_waiters = NULL;
|
||||
|
||||
/* free_waiters points to a doubly-linked list of free waiter structs. */
|
||||
static nsync_atomic_uint32_ free_waiters_mu; /* spinlock; protects free_waiters */
|
||||
|
||||
#define waiter_for_thread __get_tls()->tib_nsync
|
||||
|
||||
static void waiter_destroy (void *v) {
|
||||
waiter *w = (waiter *) v;
|
||||
/* Reset waiter_for_thread in case another thread-local variable reuses
|
||||
the waiter in its destructor while the waiter is taken by the other
|
||||
thread from free_waiters. This can happen as the destruction order
|
||||
of thread-local variables can be arbitrary in some platform e.g.
|
||||
POSIX. */
|
||||
waiter_for_thread = NULL;
|
||||
IGNORE_RACES_START ();
|
||||
ASSERT ((w->flags & (WAITER_RESERVED|WAITER_IN_USE)) == WAITER_RESERVED);
|
||||
w->flags &= ~WAITER_RESERVED;
|
||||
nsync_spin_test_and_set_ (&free_waiters_mu, 1, 1, 0);
|
||||
dll_make_first (&free_waiters, &w->nw.q);
|
||||
ATM_STORE_REL (&free_waiters_mu, 0); /* release store */
|
||||
IGNORE_RACES_END ();
|
||||
/* Initializes waiter struct. */
|
||||
void nsync_waiter_init_ (waiter *w) {
|
||||
w->tag = WAITER_TAG;
|
||||
w->nw.tag = NSYNC_WAITER_TAG;
|
||||
nsync_mu_semaphore_init (&w->sem);
|
||||
w->nw.sem = &w->sem;
|
||||
dll_init (&w->nw.q);
|
||||
NSYNC_ATOMIC_UINT32_STORE_ (&w->nw.waiting, 0);
|
||||
w->nw.flags = NSYNC_WAITER_FLAG_MUCV;
|
||||
ATM_STORE (&w->remove_count, 0);
|
||||
dll_init (&w->same_condition);
|
||||
w->flags = WAITER_IN_USE;
|
||||
}
|
||||
|
||||
/* Return a pointer to an unused waiter struct.
|
||||
Ensures that the enclosed timer is stopped and its channel drained. */
|
||||
waiter *nsync_waiter_new_ (void) {
|
||||
struct Dll *q;
|
||||
waiter *tw;
|
||||
waiter *w;
|
||||
tw = waiter_for_thread;
|
||||
w = tw;
|
||||
if (w == NULL || (w->flags & (WAITER_RESERVED|WAITER_IN_USE)) != WAITER_RESERVED) {
|
||||
w = NULL;
|
||||
nsync_spin_test_and_set_ (&free_waiters_mu, 1, 1, 0);
|
||||
q = dll_first (free_waiters);
|
||||
if (q != NULL) { /* If free list is non-empty, dequeue an item. */
|
||||
dll_remove (&free_waiters, q);
|
||||
w = DLL_WAITER (q);
|
||||
}
|
||||
ATM_STORE_REL (&free_waiters_mu, 0); /* release store */
|
||||
if (w == NULL) { /* If free list was empty, allocate an item. */
|
||||
w = (waiter *) kmalloc (sizeof (*w));
|
||||
w->tag = WAITER_TAG;
|
||||
w->nw.tag = NSYNC_WAITER_TAG;
|
||||
nsync_mu_semaphore_init (&w->sem);
|
||||
w->nw.sem = &w->sem;
|
||||
dll_init (&w->nw.q);
|
||||
NSYNC_ATOMIC_UINT32_STORE_ (&w->nw.waiting, 0);
|
||||
w->nw.flags = NSYNC_WAITER_FLAG_MUCV;
|
||||
ATM_STORE (&w->remove_count, 0);
|
||||
dll_init (&w->same_condition);
|
||||
w->flags = 0;
|
||||
}
|
||||
if (tw == NULL) {
|
||||
w->flags |= WAITER_RESERVED;
|
||||
nsync_set_per_thread_waiter_ (w, &waiter_destroy);
|
||||
waiter_for_thread = w;
|
||||
}
|
||||
}
|
||||
w->flags |= WAITER_IN_USE;
|
||||
return (w);
|
||||
}
|
||||
|
||||
/* Return an unused waiter struct *w to the free pool. */
|
||||
void nsync_waiter_free_ (waiter *w) {
|
||||
ASSERT ((w->flags & WAITER_IN_USE) != 0);
|
||||
w->flags &= ~WAITER_IN_USE;
|
||||
if ((w->flags & WAITER_RESERVED) == 0) {
|
||||
nsync_spin_test_and_set_ (&free_waiters_mu, 1, 1, 0);
|
||||
dll_make_first (&free_waiters, &w->nw.q);
|
||||
ATM_STORE_REL (&free_waiters_mu, 0); /* release store */
|
||||
/* Destroys waiter struct. */
|
||||
void nsync_waiter_destroy_ (waiter *w) {
|
||||
if (w->tag) {
|
||||
nsync_mu_semaphore_destroy (&w->sem);
|
||||
w->tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue