TODO revision 1.5
1$NetBSD: TODO,v 1.5 2006/12/25 11:36:36 ad Exp $
2
3Bugs to fix, mostly with SA:
4
5- some blocking routines (like sem_wait()) don't work if SA's aren't
6  running yet, because the alarm system isn't up and running or there is no
7  thread context to switch to. It would be weird to use them that
8  way, but it's perfectly legal.
9- There is a race between pthread_cancel() and
10  pthread_cond_broadcast() or pthread_exit() about removing an item
11  from the sleep queue. The locking protocols there need a little
12  adjustment.
13- pthread_sig.c: pthread__kill_self() passes a bogus ucontext to the handler.
14  This is probably not very important.
15- pthread_sig.c: Come up with a signal trampoline naming convention like
16  libc's, so that GDB will have an easier time with things.
17- Consider moving pthread__signal_tramp() to its own file, and building
18  it with -fasync-unwind-tables, so that DWARF2 EH unwinding works through
19  it.  (This is required for e.g. GCC's libjava.)
20- Add locking to ld.elf_so so that multiple threads doing lazy binding
21  doesn't trash things.
22- Verify the cancel stub symbol trickery.
23
24
25Interfaces/features to implement:
26- pthread_atfork()
27- priority scheduling
28- libc integration: 
29   - foo_r interfaces
30- system integration
31   - some macros and prototypes belong in headers other than pthread.h
32
33
34Features that need more/better regression tests:
35 - pthread_cond_broadcast()
36 - pthread_once()
37 - pthread_get/setspecific()
38 - signals
39
40
41Things that need fixing:
42- Recycle dead threads for new threads.
43
44Ideas to play with:
45- Explore the trapcontext vs. usercontext distinction in ucontext_t.
46- Get rid of thread structures when too many accumulate (is this
47  actually a good idea?)
48- Adaptive spin/sleep locks for mutexes.
49- Currently, each thread uses two real pages of memory: one at the top
50  of the stack for actual stack data, and one at the bottom for the
51  pthread_st. If we can get suitable space above the initial stack for
52  main(), we can cut this to one page per thread. Perhaps crt0 should
53  do something different (give us more space) if libpthread is linked
54  in?
55- Figure out whether/how to expose the inline version of
56  pthread_self().
57- Along the same lines, figure out whether/how to use registers reserved
58  in the ABI for thread-specific-data to implement pthread_self().
59- Figure out what to do with changing stack sizes.
60
61Future work for 1:1 threads:
62
63- Stress testing, particularly with multiple CPUs.
64
65- Verify that gdb still works well (basic functionality seems to be OK).
66
67- There is a race between pthread_exit() and pthread_create() for
68  detached LWPs, where the stack (and pthread structure) could be reclaimed
69  before the thread has a chance to call _lwp_exit().  Checking the return
70  of _lwp_kill(target, 0) could be used to fix this but that seems a bit
71  heavyweight. (See shared page item.)
72
73- Adaptive mutexes and spinlocks (see shared page item). These need
74  to implement exponential backoff to reduce bus contention. On x86 we
75  need to issue the 'pause' instruction while spinning, perhaps on other
76  SMT processors too.
77
78- Have a shared page that:
79
80  o Allows an LWP to request it not be preempted by the kernel. This would
81    be used over critical sections like pthread_cond_wait(), where we can
82    acquire a bunch of spin locks: being preempted while holding them would
83    suck. _lwp_park() would reset the flag once in kernel mode, and there
84    would need to be an equivalent way to do this from user mode. The user
85    path would probably need to notice deferred preemption and call
86    sched_yield() on exit from the critical section.
87
88  o Perhaps has some kind of hint mechanism that gives us a clue about
89    whether an LWP is currently running on another CPU. This could be used
90    for adaptive locks, but would need to be cheap to do in-kernel.
91
92  o Perhaps has a flag value that's reset when a detached LWP is into the
93    kernel and lwp_exit1(), meaning that its stack can be reclaimed. Again,
94    may or may not be worth it.
95
96- Keep a pool of dead LWPs so that we do not have take the full hit of
97  _lwp_create() every time pthread_create() is called. If nothing else
98  this is important for benchmarks.. There are a few different ways this
99  could be implemented, but it needs to be clear if the advantages are
100  real. Lots of thought and benchmarking required.
101
102- LWPs that are parked or that have called nanosleep() (common) burn up
103  kernel resources. "struct lwp" itself isn't a big deal, but the VA space
104  and swap used by kernel stacks is. _lwp_park() takes a ucontext_t pointer
105  in expectation that at some point we may be able to recycle the kernel
106  stack and re-start the LWP at the correct point, using pageable user
107  memory to hold state. It might also be useful to have a nanosleep call
108  that does something similar. Again, lots of thought and benchmarking
109  required. (Original idea from matt@)
110
111- It's possible that we don't need to take so many spinlocks around
112  cancellation points like pthread_cond_wait() given that _lwp_wakeup()
113  and _lwp_unpark() need to synchronise anyway.
114
115- Need to give consideration to the order in which threads enter and exit
116  synchronisation objects, both in the pthread library and in the kernel.
117  Commonly locks are acquired/released in order (a, b, c -> c, b, a). The
118  pthread spec probably has something to say about this.
119
120- The kernel scheduler needs improving to handle LWPs and processor affinity
121  better, and user space tools like top(1) and ps(1) need to be changed to
122  report correctly.  Tied into that is the need for a mechanism to impose
123  limits on various aspects of LWPs.
124
125- Streamlining of the park/unpark path.
126
127- Priority inheritance and similar nasties.
128