1. 07 9月, 2014 2 次提交
  2. 06 9月, 2014 7 次提交
  3. 05 9月, 2014 6 次提交
    • R
      fix case mapping for U+00DF (ß) · 4674809b
      Rich Felker 提交于
      U+00DF ('ß') has had an uppercase form (U+1E9E) available since
      Unicode 5.1, but Unicode lacks the case mappings for it due to
      stability policy. when I added support for the new character in commit
      1a63a9fc, I omitted the mapping in the
      lowercase-to-uppercase direction. this choice was not based on any
      actual information, only assumptions.
      
      this commit adds bidirectional case mappings between U+00DF and
      U+1E9E, and removes the special-case hack that allowed U+00DF to be
      identified as lowecase despite lacking a mapping. aside from strong
      evidence that this is the "right" behavior for real-world usage of
      these characters, several factors informed this decision:
      
      - the other "potentially correct" mapping, to "SS", is not
        representable in the C case-mapping system anyway.
      
      - leaving one letter in lowercase form when transforming a string to
        uppercase is obviously wrong.
      
      - having a character which is nominally lowercase but which is fixed
        under case mapping violates reasonable invariants.
      4674809b
    • R
      make non-waiting paths of sem_[timed]wait and pthread_join cancelable · fff54693
      Rich Felker 提交于
      per POSIX these functions are both cancellation points, so they must
      act on any cancellation request which is pending prior to the call.
      previously, only the code path where actual waiting took place could
      act on cancellation.
      fff54693
    • R
      remove an extra layer of buffer copying in getnameinfo reverse dns · 80e64854
      Rich Felker 提交于
      the outer getnameinfo function already has a properly-sized temporary
      buffer for storing the reverse dns (ptr) result. there is no reason
      for the callback to use a secondary buffer and copy it on success, and
      doing so potentially expanded the impact of the dn_expand bug that was
      fixed in commit 49d2c8c6.
      
      this change reduces the code size by a small amount, and also reduces
      the run-time stack space requirements by about 256 bytes.
      80e64854
    • R
      fix multiple stdio functions' behavior on zero-length operations · 6e2bb7ac
      Rich Felker 提交于
      previously, fgets, fputs, fread, and fwrite completely omitted locking
      and access to the FILE object when their arguments yielded a zero
      length read or write operation independent of the FILE state. this
      optimization was invalid; it wrongly skipped marking the stream as
      byte-oriented (a C conformance bug) and exposed observably missing
      synchronization (a POSIX conformance bug) where one of these functions
      could wrongly complete despite another thread provably holding the
      lock.
      6e2bb7ac
    • R
      suppress null termination when fgets reads EOF with no data · 402611c3
      Rich Felker 提交于
      the C standard requires that "the contents of the array remain
      unchanged" in this case.
      
      this patch also changes the behavior on read errors, but in that case
      "the array contents are indeterminate", so the application cannot
      inspect them anyway.
      402611c3
    • S
      fix dn_expand empty name handling and offsets to 0 · 49d2c8c6
      Szabolcs Nagy 提交于
      Empty name was rejected in dn_expand since commit
      56b57f37
      which is a regression as reported by Natanael Copa.
      
      Furthermore if an offset pointer in a compressed name
      pointed to a terminating 0 byte (instead of a label)
      the returned name was not null terminated.
      49d2c8c6
  4. 27 8月, 2014 2 次提交
  5. 26 8月, 2014 7 次提交
    • R
      add malloc_usable_size function and non-stub malloc.h · 8d998a7b
      Rich Felker 提交于
      this function is needed for some important practical applications of
      ABI compatibility, and may be useful for supporting some non-portable
      software at the source level too.
      
      I was hesitant to add a function which imposes any constraints on
      malloc internals; however, it turns out that any malloc implementation
      which has realloc must already have an efficient way to determine the
      size of existing allocations, so no additional constraint is imposed.
      
      for now, some internal malloc definitions are duplicated in the new
      source file. if/when malloc is refactored to put them in a shared
      internal header file, these could be removed.
      
      since malloc_usable_size is conventionally declared in malloc.h, the
      empty stub version of this file was no longer suitable. it's updated
      to provide the standard allocator functions, nonstandard ones (even if
      stdlib.h would not expose them based on the feature test macros in
      effect), and any malloc-extension functions provided (currently, only
      malloc_usable_size).
      8d998a7b
    • R
      refrain from spinning on locks when there is already a waiter · f5fb20b0
      Rich Felker 提交于
      if there is already a waiter for a lock, spinning on the lock is
      essentially an attempt to steal it from whichever waiter would obtain
      it via any priority rules in place, and is therefore undesirable. in
      the current implementation, there is always an inherent race window at
      unlock during which a newly-arriving thread may steal the lock from
      the existing waiters, but we should aim to keep this window minimal
      rather than enlarging it.
      f5fb20b0
    • R
      97a7512b
    • R
      spin in sem_[timed]wait before performing futex wait · 2ff714c6
      Rich Felker 提交于
      empirically, this increases the maximum rate of wait/post operations
      between two threads by 20-150 times on machines I tested, including
      x86 and arm. conceptually, it makes sense to do some spinning because
      semaphores are intended to be usable as a notification mechanism
      between threads, not just as locks, and low-latency notification is a
      valuable property to have.
      2ff714c6
    • R
      fix build error on arm due to new a_spin code · 8b3d7d0d
      Rich Felker 提交于
      this was broken by commit ea818ea8.
      8b3d7d0d
    • R
      sanitize number of spins in userspace before futex wait · b8a9c90e
      Rich Felker 提交于
      the previous spin limit of 10000 was utterly unreasonable.
      empirically, it could consume up to 200000 cycles, whereas a failed
      futex wait (EAGAIN) typically takes 1000 cycles or less, and even a
      true wait/wake round seems much less expensive.
      
      the new counts (100 for general wait, 200 in barrier) were simply
      chosen to be in the range of what's reasonable without having adverse
      effects on casual micro-benchmark tests I have been running. they may
      still be too high, from a standpoint of not wasting cpu cycles, but at
      least they're a lot better than before. rigorous testing across
      different archs and cpu models should be performed at some point to
      determine whether further adjustments should be made.
      b8a9c90e
    • R
      add working a_spin() atomic for non-x86 targets · ea818ea8
      Rich Felker 提交于
      conceptually, a_spin needs to be at least a compiler barrier, so the
      compiler will not optimize out loops (and the load on each iteration)
      while spinning. it should also be a memory barrier, or the spinning
      thread might keep spinning without noticing stores from other threads,
      thus delaying for longer than it should.
      
      ideally, an optimal a_spin implementation that avoids unnecessary
      cache/memory contention should be chosen for each arch, but for now,
      the easiest thing is to perform a useless a_cas on the calling
      thread's stack.
      ea818ea8
  6. 24 8月, 2014 1 次提交
    • R
      fix false ownership of stdio FILEs due to tid reuse · 5345c9b8
      Rich Felker 提交于
      this is analogous commit fffc5cda
      which fixed the corresponding issue for mutexes.
      
      the robust list can't be used here because the locks do not share a
      common layout with mutexes. at some point it may make sense to simply
      incorporate a mutex object into the FILE structure and use it, but
      that would be a much more invasive change, and it doesn't mesh well
      with the current design that uses a simpler code path for internal
      locking and pulls in the recursive-mutex-like code when the flockfile
      API is used explicitly.
      5345c9b8
  7. 23 8月, 2014 2 次提交
    • R
      fix fallback checks for kernels without private futex support · b8ca9eb5
      Rich Felker 提交于
      for unknown syscall commands, the kernel produces ENOSYS, not EINVAL.
      b8ca9eb5
    • R
      fix use of uninitialized memory with application-provided thread stacks · a6293285
      Rich Felker 提交于
      the subsequent code in pthread_create and the code which copies TLS
      initialization images to the new thread's TLS space assume that the
      memory provided to them is zero-initialized, which is true when it's
      obtained by pthread_create using mmap. however, when the caller
      provides a stack using pthread_attr_setstack, pthread_create cannot
      make any assumptions about the contents. simply zero-filling the
      relevant memory in this case is the simplest and safest fix.
      a6293285
  8. 21 8月, 2014 1 次提交
    • R
      add max_align_t definition for C11 and C++11 · 321f4fa9
      Rich Felker 提交于
      unfortunately this needs to be able to vary by arch, because of a huge
      mess GCC made: the GCC definition, which became the ABI, depends on
      quirks in GCC's definition of __alignof__, which does not match the
      formal alignment of the type.
      
      GCC's __alignof__ unexpectedly exposes the an implementation detail,
      its "preferred alignment" for the type, rather than the formal/ABI
      alignment of the type, which it only actually uses in structures. on
      most archs the two values are the same, but on some (at least i386)
      the preferred alignment is greater than the ABI alignment.
      
      I considered using _Alignas(8) unconditionally, but on at least one
      arch (or1k), the alignment of max_align_t with GCC's definition is
      only 4 (even the "preferred alignment" for these types is only 4).
      321f4fa9
  9. 19 8月, 2014 1 次提交
    • R
      further simplify and optimize new cond var · 4992ace9
      Rich Felker 提交于
      the main idea of the changes made is to have waiters wait directly on
      the "barrier" lock that was used to prevent them from making forward
      progress too early rather than first waiting on the atomic state value
      and then attempting to lock the barrier.
      
      in addition, adjustments to the mutex waiter count are optimized.
      previously, each waking waiter decremented the count (unless it was
      the first) then immediately incremented it again for the next waiter
      (unless it was the last). this was a roundabout was of achieving the
      equivalent of incrementing it once for the first waiter and
      decrementing it once for the last.
      4992ace9
  10. 18 8月, 2014 2 次提交
    • R
      simplify and improve new cond var implementation · 2c4b510b
      Rich Felker 提交于
      previously, wake order could be unpredictable: if a waiter happened to
      leave its futex wait on the state early, e.g. due to EAGAIN while
      restarting after a signal handler, it could acquire the mutex out of
      turn. handling this required ugly O(n) list walking in the unwait
      function and accounting to remove waiters that already woke from the
      list.
      
      with the new changes, the "barrier" locks in each waiter node are only
      unlocked in turn. in addition to simplifying the code, this seems to
      improve performance slightly, probably by reducing the number of
      accesses threads make to each other's stacks.
      
      as an additional benefit, unrecoverable mutex re-locking errors
      (mainly ENOTRECOVERABLE for robust mutexes) no longer need to be
      handled with deadlock; they can be reported to the caller, since the
      unlocking sequence makes it unnecessary to rely on the mutex to
      synchronize access to the waiter list.
      2c4b510b
    • R
      redesign cond var implementation to fix multiple issues · 37195db8
      Rich Felker 提交于
      the immediate issue that was reported by Jens Gustedt and needed to be
      fixed was corruption of the cv/mutex waiter states when switching to
      using a new mutex with the cv after all waiters were unblocked but
      before they finished returning from the wait function.
      
      self-synchronized destruction was also handled poorly and may have had
      race conditions. and the use of sequence numbers for waking waiters
      admitted a theoretical missed-wakeup if the sequence number wrapped
      through the full 32-bit space.
      
      the new implementation is largely documented in the comments in the
      source. the basic principle is to use linked lists initially attached
      to the cv object, but detachable on signal/broadcast, made up of nodes
      residing in automatic storage (stack) on the threads that are waiting.
      this eliminates the need for waiters to access the cv object after
      they are signaled, and allows us to limit wakeup to one waiter at a
      time during broadcasts even when futex requeue cannot be used.
      
      performance is also greatly improved, roughly double some tests.
      
      basically nothing is changed in the process-shared cond var case,
      where this implementation does not work, since processes do not have
      access to one another's local storage.
      37195db8
  11. 17 8月, 2014 4 次提交
    • R
      fix possible failure-to-wake deadlock with robust mutexes · 4220d298
      Rich Felker 提交于
      when the kernel is responsible for waking waiters on a robust mutex
      whose owner died, it does not have a waiters count available and must
      rely entirely on the waiter bit of the lock value.
      
      normally, this bit is only set by newly arriving waiters, so it will
      be clear if no new waiters arrived after the current owner obtained
      the lock, even if there are other waiters present. leaving it clear is
      desirable because it allows timed-lock operations to remove themselves
      as waiters and avoid causing unnecessary futex wake syscalls. however,
      for process-shared robust mutexes, we need to set the bit whenever
      there are existing waiters so that the kernel will know to wake them.
      
      for non-process-shared robust mutexes, the wake happens in userspace
      and can look at the waiters count, so the bit does not need to be set
      in the non-process-shared case.
      4220d298
    • R
      make pointers used in robust list volatile · de7e99c5
      Rich Felker 提交于
      when manipulating the robust list, the order of stores matters,
      because the code may be asynchronously interrupted by a fatal signal
      and the kernel will then access the robust list in what is essentially
      an async-signal context.
      
      previously, aliasing considerations made it seem unlikely that a
      compiler could reorder the stores, but proving that they could not be
      reordered incorrectly would have been extremely difficult. instead
      I've opted to make all the pointers used as part of the robust list,
      including those in the robust list head and in the individual mutexes,
      volatile.
      
      in addition, the format of the robust list has been changed to point
      back to the head at the end, rather than ending with a null pointer.
      this is to match the documented kernel robust list ABI. the null
      pointer, which was previously used, only worked because faults during
      access terminate the robust list processing.
      de7e99c5
    • R
      fix robust mutex unrecoverable status, and related clean-up · d338b506
      Rich Felker 提交于
      a robust mutex should not enter the unrecoverable status until it's
      unlocked without marking it consistent. previously, flag 8 in the type
      was used as an indication of unrecoverable, but only honored after
      successful locking; this resulted in a race window where the
      unrecoverable mutex could appear to a second thread as locked/busy
      again while the first thread was in the process of observing it as
      unrecoverable.
      
      now, flag 8 is used to mean that the mutex is in the process of being
      recovered, but not yet marked consistent. the flag only takes effect
      in pthread_mutex_unlock, where it causes the value 0x40000000 (owner
      dead flag, with old owner tid 0, an otherwise impossible state) to be
      stored in the lock. subsequent lock attempts will interpret this state
      as unrecoverable.
      d338b506
    • R
      fix false ownership of mutexes due to tid reuse, using robust list · fffc5cda
      Rich Felker 提交于
      per the resolution of Austin Group issue 755, the POSIX requirement
      that ownership be enforced for recursive and error-checking mutexes
      does not allow a random new thread to acquire ownership of an orphaned
      mutex just because it happened to be assigned the same tid as the
      original owner that exited with the mutex locked.
      
      one possible fix for this issue would be to disallow the kernel thread
      to terminate when it exited with mutexes held, permanently reserving
      the tid against reuse. however, this does not solve the problem for
      process-shared mutexes where lifetime cannot be controlled, so it was
      not used.
      
      the alternate approach I've taken is to reuse the robust mutex system
      for non-robust recursive and error-checking mutexes. when a thread
      exits, the kernel (or the new userspace robust-list code added in
      commit b092f1c5) will set the
      owner-died bit for these orphaned mutexes, but since the mutex-type is
      not robust, pthread_mutex_trylock will not allow a new owner to
      acquire them. instead, they remain in a state of being permanently
      locked, as desired.
      fffc5cda
  12. 16 8月, 2014 3 次提交
    • R
      optimize locking against vm changes for mmap/munmap · 25d12fc0
      Rich Felker 提交于
      the whole point of this locking is to prevent munmap, or mmap with
      MAP_FIXED, from deallocating virtual addresses, or changing the
      backing a given virtual address refers to, during certain race windows
      involving self-synchronized unmapping or destruction of pthread
      synchronization objects. there is no need for exclusion in the other
      direction, so it suffices to take the lock momentarily and release it
      before making the syscall, rather than holding it across the syscall.
      25d12fc0
    • R
      enable private futex for process-local robust mutexes · b092f1c5
      Rich Felker 提交于
      the kernel always uses non-private wake when walking the robust list
      when a thread or process exits, so it's not able to wake waiters
      listening with the private futex flag. this problem is solved by doing
      the equivalent in userspace as the last step of pthread_exit.
      
      care is taken to remove mutexes from the robust list before unlocking
      them so that the kernel will not attempt to access them again,
      possibly after another thread locks them. this removal code can treat
      the list as singly-linked, since no further code which would add or
      remove items is able to run at this point. moreover, the pending
      pointer is not needed since the mutexes being unlocked are all
      process-local; in the case of asynchronous process termination, they
      all cease to exist.
      
      since a process-local robust mutex cannot come into existence without
      a call to pthread_mutexattr_setrobust in the same process, the code
      for userspace robust list processing is put in that source file, and
      a weak alias to a dummy function is used to avoid pulling in this
      bloat as part of pthread_exit in static-linked programs.
      b092f1c5
    • R
      make futex operations use private-futex mode when possible · bc09d58c
      Rich Felker 提交于
      private-futex uses the virtual address of the futex int directly as
      the hash key rather than requiring the kernel to resolve the address
      to an underlying backing for the mapping in which it lies. for certain
      usage patterns it improves performance significantly.
      
      in many places, the code using futex __wake and __wait operations was
      already passing a correct fixed zero or nonzero flag for the priv
      argument, so no change was needed at the site of the call, only in the
      __wake and __wait functions themselves. in other places, especially
      where the process-shared attribute for a synchronization object was
      not previously tracked, additional new code is needed. for mutexes,
      the only place to store the flag is in the type field, so additional
      bit masking logic is needed for accessing the type.
      
      for non-process-shared condition variable broadcasts, the futex
      requeue operation is unable to requeue from a private futex to a
      process-shared one in the mutex structure, so requeue is simply
      disabled in this case by waking all waiters.
      
      for robust mutexes, the kernel always performs a non-private wake when
      the owner dies. in order not to introduce a behavioral regression in
      non-process-shared robust mutexes (when the owning thread dies), they
      are simply forced to be treated as process-shared for now, giving
      correct behavior at the expense of performance. this can be fixed by
      adding explicit code to pthread_exit to do the right thing for
      non-shared robust mutexes in userspace rather than relying on the
      kernel to do it, and will be fixed in this way later.
      
      since not all supported kernels have private futex support, the new
      code detects EINVAL from the futex syscall and falls back to making
      the call without the private flag. no attempt to cache the result is
      made; caching it and using the cached value efficiently is somewhat
      difficult, and not worth the complexity when the benefits would be
      seen only on ancient kernels which have numerous other limitations and
      bugs anyway.
      bc09d58c
  13. 13 8月, 2014 2 次提交