Implement userland sleep queue. The queue is used to eliminate extra
context switches and system calls in condition variable use. The
problem is pthread_cond_broadcast can cause thread scheduler's thundering
hurd, and because a thread calls pthread_cond_signal or pthread_cond_broadcast
with mutex locked, resumed thread tries to lock the mutex and is block
again, this is extra context switch. The change tries to move sleeping
threads from condition variable's wait queue to mutex wait queue, only
when the mutex is unlocked, a sleeping thread is woken up, in ideal case,
only one system call is needed.
For simple mutex, we don't use thread id as owner data,
instead use some contants. This eliminates the need to link
the mutex into thread's private list, saves some cycles.
The m_owner is pointer of curthread, which is always duplicated
in child process after fork(), so for atfork handler in child process
which wants to unlock the mutex, it will success rather than return
EPERM.
Add missing function.
Remove link field in pthread_mutex, because it can not be used in
process-shared mutex, otherwise, another process can corrupt your
mutex link list when you owned it. Instead, allocate mutex link
entry from heap, keep it private.
Add sleep queue file.
Refetch lockword before retrying.
To avoid thundering hurd problem on pthread_cond_broadcast, implement wait
queue migration.
Save previous work in libthr.user_requeue.
Follow the change in kernel, use kernel's requeue function.
Change cv_signal to move thread from condition variable's queue
to mutex queue.
Cancel thread when it is not signaled by others.
Fix some comments. and ignore error code from umutex_unlock.
Define UCOND_BIND_MUTEX flag to bind a umutex to a ucond, it indicates
a protocol if the condition variable is shared among processes.
the system call argument CVWAIT_BIND_MUTEX is removed.
Introduce cv_wait options: CVWAIT_ABSTIME and CVWAIT_CLOCKID.
CVWAIT_ABSTIME indicates the timeout is absolute time.
CVWAIT_CLOCKID indicats the clockid should be retrieved from
condition variable field c_clockid. This is how POSIX condition
varible works.
Introduce UMUTEX_ABSTIME option, so we can reduce a clock_gettime
syscall in userland.
Merge condition variable work from previous work from
libthr.user_requeue. if the current thread is using the simple
mutex, use userlevel cv, otherwise use kernel based cv.
userlevel cv is fast. may there are other cases, thread
should use kernel based cv.
Move clock_gettime() after lock released. we should have another
UMTX_OP_WAIT with absolute timeout to save syscalls.
Don't check EINTR, we don't break loop for user level cv.
To reduce the size of condition variable, use a simple integer as lock,
Also none timesharing thread use kernel based cv, because the simple lock
can not protect priority inversion, and no intention to make it
PI or PP mutex which is too heavy for normal use.
Introduce a bit flag UMUTEX_SIMPLE for umutex, so that it does not use thread id
to lock and unlock. this is necessary, because a link entry can not be embedded
into mutex which will be shared between processes, because if other process do
incorrect think, it corrupt your link list.
But to let unlocking after fork() to work, we either should link it into list
to remember it or use a id which can be atomatically duplicated.
We use pthread pointer, the bit UMUTEX_SIMPLE_OWNER indicates if the mutex is
locked or unlocked.
Restore to previous version, don't use THR_UMTX_ACQUIRE, as it is not needed
to inhibit signal and other async things.