diff options
| author | 2025-03-09 17:47:56 +0100 | |
|---|---|---|
| committer | 2025-12-01 22:08:04 +0100 | |
| commit | b1af8fd87760b34e3ff2fd3bda38f211815a0473 (patch) | |
| tree | 9317fad1a7ec298d7a8d2678e4e422953bbc6f33 /vendor/modernc.org/libc/pthread.go | |
| parent | [chore] update URLs to forked source (diff) | |
| download | gotosocial-b1af8fd87760b34e3ff2fd3bda38f211815a0473.tar.xz | |
[chore] remove vendor
Diffstat (limited to 'vendor/modernc.org/libc/pthread.go')
| -rw-r--r-- | vendor/modernc.org/libc/pthread.go | 728 |
1 files changed, 0 insertions, 728 deletions
diff --git a/vendor/modernc.org/libc/pthread.go b/vendor/modernc.org/libc/pthread.go deleted file mode 100644 index 538766b2d..000000000 --- a/vendor/modernc.org/libc/pthread.go +++ /dev/null @@ -1,728 +0,0 @@ -// Copyright 2021 The Libc Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !(linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm)) - -package libc // import "modernc.org/libc" - -import ( - "runtime" - "sync" - "sync/atomic" - "time" - "unsafe" - - "modernc.org/libc/errno" - "modernc.org/libc/pthread" - "modernc.org/libc/sys/types" - ctime "modernc.org/libc/time" -) - -var ( - mutexes = map[uintptr]*mutex{} - mutexesMu sync.Mutex - - threads = map[int32]*TLS{} - threadsMu sync.Mutex - - threadKey pthread.Pthread_key_t - threadKeyDestructors = map[pthread.Pthread_key_t][]uintptr{} // key: []destructor - threadsKeysMu sync.Mutex - - conds = map[uintptr]*cond{} - condsMu sync.Mutex -) - -// Thread local storage. -type TLS struct { - errnop uintptr - allocaStack [][]uintptr - allocas []uintptr - jumpBuffers []uintptr - lastError uint32 - pthreadData - sp int - stack stackHeader - - ID int32 - reentryGuard int32 // memgrind - stackHeaderBalance int32 -} - -var errno0 int32 // Temp errno for NewTLS - -func NewTLS() *TLS { - return newTLS(false) -} - -func newTLS(detached bool) *TLS { - id := atomic.AddInt32(&tid, 1) - t := &TLS{ID: id, errnop: uintptr(unsafe.Pointer(&errno0))} - t.pthreadData.init(t, detached) - if memgrind { - atomic.AddInt32(&tlsBalance, 1) - } - t.errnop = t.Alloc(int(unsafe.Sizeof(int32(0)))) - *(*int32)(unsafe.Pointer(t.errnop)) = 0 - return t -} - -// StackSlots reports the number of tls stack slots currently in use. -func (tls *TLS) StackSlots() int { - return tls.sp -} - -func (t *TLS) alloca(n size_t) (r uintptr) { - r = Xmalloc(t, n) - t.allocas = append(t.allocas, r) - return r -} - -func (t *TLS) FreeAlloca() func() { - t.allocaStack = append(t.allocaStack, t.allocas) - t.allocas = nil - return func() { - for _, v := range t.allocas { - Xfree(t, v) - } - n := len(t.allocaStack) - t.allocas = t.allocaStack[n-1] - t.allocaStack = t.allocaStack[:n-1] - } -} - -func (tls *TLS) PushJumpBuffer(jb uintptr) { - tls.jumpBuffers = append(tls.jumpBuffers, jb) -} - -type LongjmpRetval int32 - -func (tls *TLS) PopJumpBuffer(jb uintptr) { - n := len(tls.jumpBuffers) - if n == 0 || tls.jumpBuffers[n-1] != jb { - panic(todo("unsupported setjmp/longjmp usage")) - } - - tls.jumpBuffers = tls.jumpBuffers[:n-1] -} - -func (tls *TLS) Longjmp(jb uintptr, val int32) { - tls.PopJumpBuffer(jb) - if val == 0 { - val = 1 - } - panic(LongjmpRetval(val)) -} - -func Xalloca(tls *TLS, size size_t) uintptr { - if __ccgo_strace { - trc("tls=%v size=%v, (%v:)", tls, size, origin(2)) - } - return tls.alloca(size) -} - -func X__builtin_alloca(tls *TLS, size size_t) uintptr { - if __ccgo_strace { - trc("tls=%v size=%v, (%v:)", tls, size, origin(2)) - } - return Xalloca(tls, size) -} - -// Pthread specific part of a TLS. -type pthreadData struct { - done chan struct{} - kv map[pthread.Pthread_key_t]uintptr - retVal uintptr - wait chan struct{} // cond var interaction - - detached bool -} - -func (d *pthreadData) init(t *TLS, detached bool) { - d.detached = detached - d.wait = make(chan struct{}, 1) - if detached { - return - } - - d.done = make(chan struct{}) - - threadsMu.Lock() - - defer threadsMu.Unlock() - - threads[t.ID] = t -} - -func (d *pthreadData) close(t *TLS) { - threadsMu.Lock() - - defer threadsMu.Unlock() - - delete(threads, t.ID) -} - -// int pthread_attr_destroy(pthread_attr_t *attr); -func Xpthread_attr_destroy(t *TLS, pAttr uintptr) int32 { - if __ccgo_strace { - trc("t=%v pAttr=%v, (%v:)", t, pAttr, origin(2)) - } - return 0 -} - -// int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope); -func Xpthread_attr_setscope(t *TLS, pAttr uintptr, contentionScope int32) int32 { - if __ccgo_strace { - trc("t=%v pAttr=%v contentionScope=%v, (%v:)", t, pAttr, contentionScope, origin(2)) - } - switch contentionScope { - case pthread.PTHREAD_SCOPE_SYSTEM: - return 0 - default: - panic(todo("", contentionScope)) - } -} - -// int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); -func Xpthread_attr_setstacksize(t *TLS, attr uintptr, stackSize types.Size_t) int32 { - if __ccgo_strace { - trc("t=%v attr=%v stackSize=%v, (%v:)", t, attr, stackSize, origin(2)) - } - return 0 -} - -// Go side data of pthread_cond_t. -type cond struct { - sync.Mutex - waiters map[*TLS]struct{} -} - -func newCond() *cond { - return &cond{ - waiters: map[*TLS]struct{}{}, - } -} - -func (c *cond) signal(all bool) int32 { - if c == nil { - return errno.EINVAL - } - - c.Lock() - - defer c.Unlock() - - // The pthread_cond_broadcast() and pthread_cond_signal() functions shall have - // no effect if there are no threads currently blocked on cond. - for tls := range c.waiters { - tls.wait <- struct{}{} - delete(c.waiters, tls) - if !all { - break - } - } - return 0 -} - -// The pthread_cond_init() function shall initialize the condition variable -// referenced by cond with attributes referenced by attr. If attr is NULL, the -// default condition variable attributes shall be used; the effect is the same -// as passing the address of a default condition variable attributes object. -// Upon successful initialization, the state of the condition variable shall -// become initialized. -// -// If successful, the pthread_cond_destroy() and pthread_cond_init() functions -// shall return zero; otherwise, an error number shall be returned to indicate -// the error. -// -// int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); -func Xpthread_cond_init(t *TLS, pCond, pAttr uintptr) int32 { - if __ccgo_strace { - trc("t=%v pAttr=%v, (%v:)", t, pAttr, origin(2)) - } - if pCond == 0 { - return errno.EINVAL - } - - if pAttr != 0 { - panic(todo("%#x %#x", pCond, pAttr)) - } - - condsMu.Lock() - - defer condsMu.Unlock() - - conds[pCond] = newCond() - return 0 -} - -// int pthread_cond_destroy(pthread_cond_t *cond); -func Xpthread_cond_destroy(t *TLS, pCond uintptr) int32 { - if __ccgo_strace { - trc("t=%v pCond=%v, (%v:)", t, pCond, origin(2)) - } - if pCond == 0 { - return errno.EINVAL - } - - condsMu.Lock() - - defer condsMu.Unlock() - - cond := conds[pCond] - if cond == nil { - return errno.EINVAL - } - - cond.Lock() - - defer cond.Unlock() - - if len(cond.waiters) != 0 { - return errno.EBUSY - } - - delete(conds, pCond) - return 0 -} - -// int pthread_cond_signal(pthread_cond_t *cond); -func Xpthread_cond_signal(t *TLS, pCond uintptr) int32 { - if __ccgo_strace { - trc("t=%v pCond=%v, (%v:)", t, pCond, origin(2)) - } - return condSignal(pCond, false) -} - -// int pthread_cond_broadcast(pthread_cond_t *cond); -func Xpthread_cond_broadcast(t *TLS, pCond uintptr) int32 { - if __ccgo_strace { - trc("t=%v pCond=%v, (%v:)", t, pCond, origin(2)) - } - return condSignal(pCond, true) -} - -func condSignal(pCond uintptr, all bool) int32 { - if pCond == 0 { - return errno.EINVAL - } - - condsMu.Lock() - cond := conds[pCond] - condsMu.Unlock() - - return cond.signal(all) -} - -// int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); -func Xpthread_cond_wait(t *TLS, pCond, pMutex uintptr) int32 { - if __ccgo_strace { - trc("t=%v pMutex=%v, (%v:)", t, pMutex, origin(2)) - } - if pCond == 0 { - return errno.EINVAL - } - - condsMu.Lock() - cond := conds[pCond] - if cond == nil { // static initialized condition variables are valid - cond = newCond() - conds[pCond] = cond - } - - cond.Lock() - cond.waiters[t] = struct{}{} - cond.Unlock() - - condsMu.Unlock() - - mutexesMu.Lock() - mu := mutexes[pMutex] - mutexesMu.Unlock() - - mu.Unlock() - <-t.wait - mu.Lock() - return 0 -} - -// int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); -func Xpthread_cond_timedwait(t *TLS, pCond, pMutex, pAbsTime uintptr) int32 { - if __ccgo_strace { - trc("t=%v pAbsTime=%v, (%v:)", t, pAbsTime, origin(2)) - } - if pCond == 0 { - return errno.EINVAL - } - - condsMu.Lock() - cond := conds[pCond] - if cond == nil { // static initialized condition variables are valid - cond = newCond() - conds[pCond] = cond - } - - cond.Lock() - cond.waiters[t] = struct{}{} - cond.Unlock() - - condsMu.Unlock() - - mutexesMu.Lock() - mu := mutexes[pMutex] - mutexesMu.Unlock() - - deadlineSecs := (*ctime.Timespec)(unsafe.Pointer(pAbsTime)).Ftv_sec - deadlineNsecs := (*ctime.Timespec)(unsafe.Pointer(pAbsTime)).Ftv_nsec - deadline := time.Unix(int64(deadlineSecs), int64(deadlineNsecs)) - d := deadline.Sub(time.Now()) - switch { - case d <= 0: - return errno.ETIMEDOUT - default: - to := time.After(d) - mu.Unlock() - - defer mu.Lock() - - select { - case <-t.wait: - return 0 - case <-to: - cond.Lock() - - defer cond.Unlock() - - delete(cond.waiters, t) - return errno.ETIMEDOUT - } - } -} - -// Go side data of pthread_mutex_t -type mutex struct { - sync.Mutex - typ int // PTHREAD_MUTEX_NORMAL, ... - wait sync.Mutex - - id int32 // owner's t.ID - cnt int32 - - robust bool -} - -func newMutex(typ int) *mutex { - return &mutex{ - typ: typ, - } -} - -func (m *mutex) lock(id int32) int32 { - if m.robust { - panic(todo("")) - } - - // If successful, the pthread_mutex_lock() and pthread_mutex_unlock() functions - // shall return zero; otherwise, an error number shall be returned to indicate - // the error. - switch m.typ { - default: - fallthrough - case pthread.PTHREAD_MUTEX_NORMAL: - // If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection shall not be - // provided. Attempting to relock the mutex causes deadlock. If a thread - // attempts to unlock a mutex that it has not locked or a mutex which is - // unlocked, undefined behavior results. - m.Lock() - m.id = id - return 0 - case pthread.PTHREAD_MUTEX_RECURSIVE: - for { - m.Lock() - switch m.id { - case 0: - m.cnt = 1 - m.id = id - m.wait.Lock() - m.Unlock() - return 0 - case id: - m.cnt++ - m.Unlock() - return 0 - } - - m.Unlock() - m.wait.Lock() - // intentional empty section - wake up other waiters - m.wait.Unlock() - } - } -} - -func (m *mutex) tryLock(id int32) int32 { - if m.robust { - panic(todo("")) - } - - switch m.typ { - default: - fallthrough - case pthread.PTHREAD_MUTEX_NORMAL: - return errno.EBUSY - case pthread.PTHREAD_MUTEX_RECURSIVE: - m.Lock() - switch m.id { - case 0: - m.cnt = 1 - m.id = id - m.wait.Lock() - m.Unlock() - return 0 - case id: - m.cnt++ - m.Unlock() - return 0 - } - - m.Unlock() - return errno.EBUSY - } -} - -func (m *mutex) unlock() int32 { - if m.robust { - panic(todo("")) - } - - // If successful, the pthread_mutex_lock() and pthread_mutex_unlock() functions - // shall return zero; otherwise, an error number shall be returned to indicate - // the error. - switch m.typ { - default: - fallthrough - case pthread.PTHREAD_MUTEX_NORMAL: - // If the mutex type is PTHREAD_MUTEX_NORMAL, deadlock detection shall not be - // provided. Attempting to relock the mutex causes deadlock. If a thread - // attempts to unlock a mutex that it has not locked or a mutex which is - // unlocked, undefined behavior results. - m.id = 0 - m.Unlock() - return 0 - case pthread.PTHREAD_MUTEX_RECURSIVE: - m.Lock() - m.cnt-- - if m.cnt == 0 { - m.id = 0 - m.wait.Unlock() - } - m.Unlock() - return 0 - } -} - -// int pthread_mutex_destroy(pthread_mutex_t *mutex); -func Xpthread_mutex_destroy(t *TLS, pMutex uintptr) int32 { - if __ccgo_strace { - trc("t=%v pMutex=%v, (%v:)", t, pMutex, origin(2)) - } - mutexesMu.Lock() - - defer mutexesMu.Unlock() - - delete(mutexes, pMutex) - return 0 -} - -// int pthread_mutex_lock(pthread_mutex_t *mutex); -func Xpthread_mutex_lock(t *TLS, pMutex uintptr) int32 { - if __ccgo_strace { - trc("t=%v pMutex=%v, (%v:)", t, pMutex, origin(2)) - } - mutexesMu.Lock() - mu := mutexes[pMutex] - if mu == nil { // static initialized mutexes are valid - mu = newMutex(int(X__ccgo_getMutexType(t, pMutex))) - mutexes[pMutex] = mu - } - mutexesMu.Unlock() - return mu.lock(t.ID) -} - -// int pthread_mutex_trylock(pthread_mutex_t *mutex); -func Xpthread_mutex_trylock(t *TLS, pMutex uintptr) int32 { - if __ccgo_strace { - trc("t=%v pMutex=%v, (%v:)", t, pMutex, origin(2)) - } - mutexesMu.Lock() - mu := mutexes[pMutex] - if mu == nil { // static initialized mutexes are valid - mu = newMutex(int(X__ccgo_getMutexType(t, pMutex))) - mutexes[pMutex] = mu - } - mutexesMu.Unlock() - return mu.tryLock(t.ID) -} - -// int pthread_mutex_unlock(pthread_mutex_t *mutex); -func Xpthread_mutex_unlock(t *TLS, pMutex uintptr) int32 { - if __ccgo_strace { - trc("t=%v pMutex=%v, (%v:)", t, pMutex, origin(2)) - } - mutexesMu.Lock() - - defer mutexesMu.Unlock() - - return mutexes[pMutex].unlock() -} - -// int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); -func Xpthread_key_create(t *TLS, pKey, destructor uintptr) int32 { - threadsKeysMu.Lock() - - defer threadsKeysMu.Unlock() - - threadKey++ - r := threadKey - if destructor != 0 { - threadKeyDestructors[r] = append(threadKeyDestructors[r], destructor) - } - *(*pthread.Pthread_key_t)(unsafe.Pointer(pKey)) = pthread.Pthread_key_t(r) - return 0 -} - -// int pthread_key_delete(pthread_key_t key); -func Xpthread_key_delete(t *TLS, key pthread.Pthread_key_t) int32 { - if __ccgo_strace { - trc("t=%v key=%v, (%v:)", t, key, origin(2)) - } - if _, ok := t.kv[key]; ok { - delete(t.kv, key) - return 0 - } - - panic(todo("")) - -} - -// void *pthread_getspecific(pthread_key_t key); -func Xpthread_getspecific(t *TLS, key pthread.Pthread_key_t) uintptr { - if __ccgo_strace { - trc("t=%v key=%v, (%v:)", t, key, origin(2)) - } - return t.kv[key] -} - -// int pthread_setspecific(pthread_key_t key, const void *value); -func Xpthread_setspecific(t *TLS, key pthread.Pthread_key_t, value uintptr) int32 { - if __ccgo_strace { - trc("t=%v key=%v value=%v, (%v:)", t, key, value, origin(2)) - } - if t.kv == nil { - t.kv = map[pthread.Pthread_key_t]uintptr{} - } - t.kv[key] = value - return 0 -} - -// int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); -func Xpthread_create(t *TLS, pThread, pAttr, startRoutine, arg uintptr) int32 { - if __ccgo_strace { - trc("t=%v arg=%v, (%v:)", t, arg, origin(2)) - } - fn := (*struct { - f func(*TLS, uintptr) uintptr - })(unsafe.Pointer(&struct{ uintptr }{startRoutine})).f - detached := pAttr != 0 && X__ccgo_pthreadAttrGetDetachState(t, pAttr) == pthread.PTHREAD_CREATE_DETACHED - tls := newTLS(detached) - *(*pthread.Pthread_t)(unsafe.Pointer(pThread)) = pthread.Pthread_t(tls.ID) - - go func() { - Xpthread_exit(tls, fn(tls, arg)) - }() - - return 0 -} - -// int pthread_detach(pthread_t thread); -func Xpthread_detach(t *TLS, thread pthread.Pthread_t) int32 { - if __ccgo_strace { - trc("t=%v thread=%v, (%v:)", t, thread, origin(2)) - } - threadsMu.Lock() - threads[int32(thread)].detached = true - threadsMu.Unlock() - return 0 -} - -// int pthread_equal(pthread_t t1, pthread_t t2); -func Xpthread_equal(t *TLS, t1, t2 pthread.Pthread_t) int32 { - if __ccgo_strace { - trc("t=%v t2=%v, (%v:)", t, t2, origin(2)) - } - return Bool32(t1 == t2) -} - -// void pthread_exit(void *value_ptr); -func Xpthread_exit(t *TLS, value uintptr) { - if __ccgo_strace { - trc("t=%v value=%v, (%v:)", t, value, origin(2)) - } - t.retVal = value - - // At thread exit, if a key value has a non-NULL destructor pointer, and the - // thread has a non-NULL value associated with that key, the value of the key - // is set to NULL, and then the function pointed to is called with the - // previously associated value as its sole argument. The order of destructor - // calls is unspecified if more than one destructor exists for a thread when it - // exits. - for k, v := range t.kv { - if v == 0 { - continue - } - - threadsKeysMu.Lock() - destructors := threadKeyDestructors[k] - threadsKeysMu.Unlock() - - for _, destructor := range destructors { - delete(t.kv, k) - panic(todo("%#x", destructor)) //TODO call destructor(v) - } - } - - switch { - case t.detached: - threadsMu.Lock() - delete(threads, t.ID) - threadsMu.Unlock() - default: - close(t.done) - } - runtime.Goexit() -} - -// int pthread_join(pthread_t thread, void **value_ptr); -func Xpthread_join(t *TLS, thread pthread.Pthread_t, pValue uintptr) int32 { - if __ccgo_strace { - trc("t=%v thread=%v pValue=%v, (%v:)", t, thread, pValue, origin(2)) - } - threadsMu.Lock() - tls := threads[int32(thread)] - delete(threads, int32(thread)) - threadsMu.Unlock() - <-tls.done - if pValue != 0 { - *(*uintptr)(unsafe.Pointer(pValue)) = tls.retVal - } - return 0 -} - -// pthread_t pthread_self(void); -func Xpthread_self(t *TLS) pthread.Pthread_t { - if __ccgo_strace { - trc("t=%v, (%v:)", t, origin(2)) - } - return pthread.Pthread_t(t.ID) -} |
