1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */
5 /* This program is free software; you can redistribute it and/or */
6 /* modify it under the terms of the GNU Library General Public License */
7 /* as published by the Free Software Foundation; either version 2 */
8 /* of the License, or (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU Library General Public License for more details. */
25 #include "internals.h"
29 libpthread_hidden_proto(nanosleep)
31 static void __pthread_acquire(int * spinlock);
33 static __inline__ void __pthread_release(int * spinlock)
35 WRITE_MEMORY_BARRIER();
36 *spinlock = __LT_SPINLOCK_INIT;
37 __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock));
41 /* The status field of a spinlock is a pointer whose least significant
44 Thus the field values have the following meanings:
46 status == 0: spinlock is free
47 status == 1: spinlock is taken; no thread is waiting on it
49 (status & 1) == 1: spinlock is taken and (status & ~1L) is a
50 pointer to the first waiting thread; other
51 waiting threads are linked via the p_nextlock
53 (status & 1) == 0: same as above, but spinlock is not taken.
55 The waiting list is not sorted by priority order.
56 Actually, we always insert at top of list (sole insertion mode
57 that can be performed without locking).
58 For __pthread_unlock, we perform a linear search in the list
59 to find the highest-priority, oldest waiting thread.
60 This is safe because there are no concurrent __pthread_unlock
61 operations -- only the thread that locked the mutex can unlock it. */
64 void internal_function __pthread_lock(struct _pthread_fastlock * lock,
67 #if defined HAS_COMPARE_AND_SWAP
68 long oldstatus, newstatus;
69 int successful_seizure, spurious_wakeup_count;
72 #if defined TEST_FOR_COMPARE_AND_SWAP
73 if (!__pthread_has_cas)
75 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
77 __pthread_acquire(&lock->__spinlock);
82 #if defined HAS_COMPARE_AND_SWAP
83 /* First try it without preparation. Maybe it's a completely
85 if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1))
88 spurious_wakeup_count = 0;
90 /* On SMP, try spinning to get the lock. */
92 if (__pthread_smp_kernel) {
94 int max_count = lock->__spinlock * 2 + 10;
96 if (max_count > MAX_ADAPTIVE_SPIN_COUNT)
97 max_count = MAX_ADAPTIVE_SPIN_COUNT;
99 for (spin_count = 0; spin_count < max_count; spin_count++) {
100 if (((oldstatus = lock->__status) & 1) == 0) {
101 if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1))
104 lock->__spinlock += (spin_count - lock->__spinlock) / 8;
105 READ_MEMORY_BARRIER();
112 __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status));
115 lock->__spinlock += (spin_count - lock->__spinlock) / 8;
121 /* No luck, try once more or suspend. */
124 oldstatus = lock->__status;
125 successful_seizure = 0;
127 if ((oldstatus & 1) == 0) {
128 newstatus = oldstatus | 1;
129 successful_seizure = 1;
132 self = thread_self();
133 newstatus = (long) self | 1;
137 THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus));
138 /* Make sure the store in p_nextlock completes before performing
139 the compare-and-swap */
142 } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
144 /* Suspend with guard against spurious wakeup.
145 This can happen in pthread_cond_timedwait_relative, when the thread
146 wakes up due to timeout and is still on the condvar queue, and then
147 locks the queue to remove itself. At that point it may still be on the
148 queue, and may be resumed by a condition signal. */
150 if (!successful_seizure) {
153 if (self->p_nextlock != NULL) {
154 /* Count resumes that don't belong to us. */
155 spurious_wakeup_count++;
163 /* Put back any resumes we caught that don't belong to us. */
164 while (spurious_wakeup_count--)
167 READ_MEMORY_BARRIER();
171 int __pthread_unlock(struct _pthread_fastlock * lock)
173 #if defined HAS_COMPARE_AND_SWAP
175 pthread_descr thr, * ptr, * maxptr;
179 #if defined TEST_FOR_COMPARE_AND_SWAP
180 if (!__pthread_has_cas)
182 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
184 __pthread_release(&lock->__spinlock);
189 #if defined HAS_COMPARE_AND_SWAP
190 WRITE_MEMORY_BARRIER();
193 while ((oldstatus = lock->__status) == 1) {
194 if (__compare_and_swap_with_release_semantics(&lock->__status,
199 /* Find thread in waiting queue with maximal priority */
200 ptr = (pthread_descr *) &lock->__status;
201 thr = (pthread_descr) (oldstatus & ~1L);
205 /* Before we iterate over the wait queue, we need to execute
206 a read barrier, otherwise we may read stale contents of nodes that may
207 just have been inserted by other processors. One read barrier is enough to
208 ensure we have a stable list; we don't need one for each pointer chase
209 through the list, because we are the owner of the lock; other threads
210 can only add nodes at the front; if a front node is consistent,
211 the ones behind it must also be. */
213 READ_MEMORY_BARRIER();
216 if (thr->p_priority >= maxprio) {
218 maxprio = thr->p_priority;
220 ptr = &(thr->p_nextlock);
221 thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L);
224 /* Remove max prio thread from waiting list. */
225 if (maxptr == (pthread_descr *) &lock->__status) {
226 /* If max prio thread is at head, remove it with compare-and-swap
227 to guard against concurrent lock operation. This removal
228 also has the side effect of marking the lock as released
229 because the new status comes from thr->p_nextlock whose
230 least significant bit is clear. */
231 thr = (pthread_descr) (oldstatus & ~1L);
232 if (! __compare_and_swap_with_release_semantics
233 (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L))
236 /* No risk of concurrent access, remove max prio thread normally.
237 But in this case we must also flip the least significant bit
238 of the status to mark the lock as released. */
239 thr = (pthread_descr)((long)*maxptr & ~1L);
240 *maxptr = thr->p_nextlock;
242 /* Ensure deletion from linked list completes before we
244 WRITE_MEMORY_BARRIER();
247 oldstatus = lock->__status;
248 } while (!__compare_and_swap_with_release_semantics(&lock->__status,
249 oldstatus, oldstatus & ~1L));
252 /* Wake up the selected waiting thread. Woken thread can check
253 its own p_nextlock field for NULL to detect that it has been removed. No
254 barrier is needed here, since restart() and suspend() take
255 care of memory synchronization. */
257 thr->p_nextlock = NULL;
265 * Alternate fastlocks do not queue threads directly. Instead, they queue
266 * these wait queue node structures. When a timed wait wakes up due to
267 * a timeout, it can leave its wait node in the queue (because there
268 * is no safe way to remove from the quue). Some other thread will
269 * deallocate the abandoned node.
274 struct wait_node *next; /* Next node in null terminated linked list */
275 pthread_descr thr; /* The thread waiting with this node */
276 int abandoned; /* Atomic flag */
279 static long wait_node_free_list;
280 static int wait_node_free_list_spinlock;
282 /* Allocate a new node from the head of the free list using an atomic
283 operation, or else using malloc if that list is empty. A fundamental
284 assumption here is that we can safely access wait_node_free_list->next.
285 That's because we never free nodes once we allocate them, so a pointer to a
286 node remains valid indefinitely. */
288 static struct wait_node *wait_node_alloc(void)
290 struct wait_node *new_node = 0;
292 __pthread_acquire(&wait_node_free_list_spinlock);
293 if (wait_node_free_list != 0) {
294 new_node = (struct wait_node *) wait_node_free_list;
295 wait_node_free_list = (long) new_node->next;
297 WRITE_MEMORY_BARRIER();
298 __pthread_release(&wait_node_free_list_spinlock);
301 return malloc(sizeof *wait_node_alloc());
306 /* Return a node to the head of the free list using an atomic
309 static void wait_node_free(struct wait_node *wn)
311 __pthread_acquire(&wait_node_free_list_spinlock);
312 wn->next = (struct wait_node *) wait_node_free_list;
313 wait_node_free_list = (long) wn;
314 WRITE_MEMORY_BARRIER();
315 __pthread_release(&wait_node_free_list_spinlock);
319 #if defined HAS_COMPARE_AND_SWAP
321 /* Remove a wait node from the specified queue. It is assumed
322 that the removal takes place concurrently with only atomic insertions at the
323 head of the queue. */
325 static void wait_node_dequeue(struct wait_node **pp_head,
326 struct wait_node **pp_node,
327 struct wait_node *p_node)
329 /* If the node is being deleted from the head of the
330 list, it must be deleted using atomic compare-and-swap.
331 Otherwise it can be deleted in the straightforward way. */
333 if (pp_node == pp_head) {
334 /* We don't need a read barrier between these next two loads,
335 because it is assumed that the caller has already ensured
336 the stability of *p_node with respect to p_node. */
338 long oldvalue = (long) p_node;
339 long newvalue = (long) p_node->next;
341 if (__compare_and_swap((long *) pp_node, oldvalue, newvalue))
344 /* Oops! Compare and swap failed, which means the node is
345 no longer first. We delete it using the ordinary method. But we don't
346 know the identity of the node which now holds the pointer to the node
347 being deleted, so we must search from the beginning. */
349 for (pp_node = pp_head; p_node != *pp_node; ) {
350 pp_node = &(*pp_node)->next;
351 READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */
355 *pp_node = p_node->next;
361 void __pthread_alt_lock(struct _pthread_fastlock * lock,
364 #if defined HAS_COMPARE_AND_SWAP
365 long oldstatus, newstatus;
367 struct wait_node wait_node;
369 #if defined TEST_FOR_COMPARE_AND_SWAP
370 if (!__pthread_has_cas)
372 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
374 int suspend_needed = 0;
375 __pthread_acquire(&lock->__spinlock);
377 if (lock->__status == 0)
381 self = thread_self();
383 wait_node.abandoned = 0;
384 wait_node.next = (struct wait_node *) lock->__status;
385 wait_node.thr = self;
386 lock->__status = (long) &wait_node;
390 __pthread_release(&lock->__spinlock);
398 #if defined HAS_COMPARE_AND_SWAP
400 oldstatus = lock->__status;
401 if (oldstatus == 0) {
405 self = thread_self();
406 wait_node.thr = self;
407 newstatus = (long) &wait_node;
409 wait_node.abandoned = 0;
410 wait_node.next = (struct wait_node *) oldstatus;
411 /* Make sure the store in wait_node.next completes before performing
412 the compare-and-swap */
414 } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
416 /* Suspend. Note that unlike in __pthread_lock, we don't worry
417 here about spurious wakeup. That's because this lock is not
418 used in situations where that can happen; the restart can
419 only come from the previous lock owner. */
424 READ_MEMORY_BARRIER();
428 /* Timed-out lock operation; returns 0 to indicate timeout. */
430 int __pthread_alt_timedlock(struct _pthread_fastlock * lock,
431 pthread_descr self, const struct timespec *abstime)
434 #if defined HAS_COMPARE_AND_SWAP
437 struct wait_node *p_wait_node = wait_node_alloc();
439 /* Out of memory, just give up and do ordinary lock. */
440 if (p_wait_node == 0) {
441 __pthread_alt_lock(lock, self);
445 #if defined TEST_FOR_COMPARE_AND_SWAP
446 if (!__pthread_has_cas)
448 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
450 __pthread_acquire(&lock->__spinlock);
452 if (lock->__status == 0)
456 self = thread_self();
458 p_wait_node->abandoned = 0;
459 p_wait_node->next = (struct wait_node *) lock->__status;
460 p_wait_node->thr = self;
461 lock->__status = (long) p_wait_node;
462 oldstatus = 1; /* force suspend */
465 __pthread_release(&lock->__spinlock);
470 #if defined HAS_COMPARE_AND_SWAP
472 oldstatus = lock->__status;
473 if (oldstatus == 0) {
477 self = thread_self();
478 p_wait_node->thr = self;
479 newstatus = (long) p_wait_node;
481 p_wait_node->abandoned = 0;
482 p_wait_node->next = (struct wait_node *) oldstatus;
483 /* Make sure the store in wait_node.next completes before performing
484 the compare-and-swap */
486 } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus));
489 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
493 /* If we did not get the lock, do a timed suspend. If we wake up due
494 to a timeout, then there is a race; the old lock owner may try
495 to remove us from the queue. This race is resolved by us and the owner
496 doing an atomic testandset() to change the state of the wait node from 0
497 to 1. If we succeed, then it's a timeout and we abandon the node in the
498 queue. If we fail, it means the owner gave us the lock. */
500 if (oldstatus != 0) {
501 if (timedsuspend(self, abstime) == 0) {
502 if (!testandset(&p_wait_node->abandoned))
503 return 0; /* Timeout! */
505 /* Eat oustanding resume from owner, otherwise wait_node_free() below
506 will race with owner's wait_node_dequeue(). */
511 wait_node_free(p_wait_node);
513 READ_MEMORY_BARRIER();
515 return 1; /* Got the lock! */
518 void __pthread_alt_unlock(struct _pthread_fastlock *lock)
520 struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio;
521 struct wait_node ** const pp_head = (struct wait_node **) &lock->__status;
524 WRITE_MEMORY_BARRIER();
526 #if defined TEST_FOR_COMPARE_AND_SWAP
527 if (!__pthread_has_cas)
529 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
531 __pthread_acquire(&lock->__spinlock);
537 /* If no threads are waiting for this lock, try to just
538 atomically release it. */
539 #if defined TEST_FOR_COMPARE_AND_SWAP
540 if (!__pthread_has_cas)
542 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
544 if (lock->__status == 0 || lock->__status == 1) {
551 #if defined TEST_FOR_COMPARE_AND_SWAP
555 #if defined HAS_COMPARE_AND_SWAP
557 long oldstatus = lock->__status;
558 if (oldstatus == 0 || oldstatus == 1) {
559 if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0))
567 /* Process the entire queue of wait nodes. Remove all abandoned
568 wait nodes and put them into the global free queue, and
569 remember the one unabandoned node which refers to the thread
570 having the highest priority. */
572 pp_max_prio = pp_node = pp_head;
573 p_max_prio = p_node = *pp_head;
576 READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */
578 while (p_node != (struct wait_node *) 1) {
581 if (p_node->abandoned) {
582 /* Remove abandoned node. */
583 #if defined TEST_FOR_COMPARE_AND_SWAP
584 if (!__pthread_has_cas)
586 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
587 *pp_node = p_node->next;
589 #if defined TEST_FOR_COMPARE_AND_SWAP
592 #if defined HAS_COMPARE_AND_SWAP
593 wait_node_dequeue(pp_head, pp_node, p_node);
595 wait_node_free(p_node);
596 /* Note that the next assignment may take us to the beginning
597 of the queue, to newly inserted nodes, if pp_node == pp_head.
598 In that case we need a memory barrier to stabilize the first of
601 if (pp_node == pp_head)
602 READ_MEMORY_BARRIER(); /* No stale reads through p_node */
604 } else if ((prio = p_node->thr->p_priority) >= maxprio) {
605 /* Otherwise remember it if its thread has a higher or equal priority
606 compared to that of any node seen thus far. */
608 pp_max_prio = pp_node;
612 /* This canno6 jump backward in the list, so no further read
613 barrier is needed. */
614 pp_node = &p_node->next;
618 /* If all threads abandoned, go back to top */
619 if (maxprio == INT_MIN)
622 /* Now we want to to remove the max priority thread's wait node from
623 the list. Before we can do this, we must atomically try to change the
624 node's abandon state from zero to nonzero. If we succeed, that means we
625 have the node that we will wake up. If we failed, then it means the
626 thread timed out and abandoned the node in which case we repeat the
627 whole unlock operation. */
629 if (!testandset(&p_max_prio->abandoned)) {
630 #if defined TEST_FOR_COMPARE_AND_SWAP
631 if (!__pthread_has_cas)
633 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
634 *pp_max_prio = p_max_prio->next;
636 #if defined TEST_FOR_COMPARE_AND_SWAP
639 #if defined HAS_COMPARE_AND_SWAP
640 wait_node_dequeue(pp_head, pp_max_prio, p_max_prio);
642 restart(p_max_prio->thr);
647 #if defined TEST_FOR_COMPARE_AND_SWAP
648 if (!__pthread_has_cas)
650 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
652 __pthread_release(&lock->__spinlock);
658 /* Compare-and-swap emulation with a spinlock */
660 #ifdef TEST_FOR_COMPARE_AND_SWAP
661 int __pthread_has_cas = 0;
664 #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
666 int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
671 __pthread_acquire(spinlock);
673 if (*ptr == oldval) {
674 *ptr = newval; res = 1;
679 __pthread_release(spinlock);
686 /* The retry strategy is as follows:
687 - We test and set the spinlock MAX_SPIN_COUNT times, calling
688 sched_yield() each time. This gives ample opportunity for other
689 threads with priority >= our priority to make progress and
690 release the spinlock.
691 - If a thread with priority < our priority owns the spinlock,
692 calling sched_yield() repeatedly is useless, since we're preventing
693 the owning thread from making progress and releasing the spinlock.
694 So, after MAX_SPIN_LOCK attemps, we suspend the calling thread
695 using nanosleep(). This again should give time to the owning thread
696 for releasing the spinlock.
697 Notice that the nanosleep() interval must not be too small,
698 since the kernel does busy-waiting for short intervals in a realtime
699 process (!). The smallest duration that guarantees thread
700 suspension is currently 2ms.
701 - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT
702 sched_yield(), then sleeping again if needed. */
704 static void __pthread_acquire(int * spinlock)
709 READ_MEMORY_BARRIER();
711 while (testandset(spinlock)) {
712 if (cnt < MAX_SPIN_COUNT) {
717 tm.tv_nsec = SPIN_SLEEP_DURATION;
718 nanosleep(&tm, NULL);