home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / SLAX 6.0.8 / slax-6.0.8.iso / slax / base / 006-devel.lzm / usr / include / isc / atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-17  |  3.8 KB  |  159 lines

  1. /*
  2.  * Copyright (C) 2005  Internet Systems Consortium, Inc. ("ISC")
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software for any
  5.  * purpose with or without fee is hereby granted, provided that the above
  6.  * copyright notice and this permission notice appear in all copies.
  7.  *
  8.  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9.  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10.  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11.  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14.  * PERFORMANCE OF THIS SOFTWARE.
  15.  */
  16.  
  17. /* $Id: atomic.h,v 1.2.2.3 2005/07/27 04:23:33 marka Exp $ */
  18.  
  19. #ifndef ISC_ATOMIC_H
  20. #define ISC_ATOMIC_H 1
  21.  
  22. #include <isc/platform.h>
  23. #include <isc/types.h>
  24.  
  25. #ifdef ISC_PLATFORM_USEGCCASM
  26. /*
  27.  * This routine atomically increments the value stored in 'p' by 'val', and
  28.  * returns the previous value.
  29.  */
  30. static inline isc_int32_t
  31. isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
  32.     isc_int32_t prev = val;
  33.  
  34.     __asm__ volatile(
  35. #ifdef ISC_PLATFORM_USETHREADS
  36.         "lock;"
  37. #endif
  38.         "xadd %0, %1"
  39.         :"=q"(prev)
  40.         :"m"(*p), "0"(prev)
  41.         :"memory", "cc");
  42.  
  43.     return (prev);
  44. }
  45.  
  46. /*
  47.  * This routine atomically stores the value 'val' in 'p'.
  48.  */
  49. static inline void
  50. isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
  51.     __asm__ volatile(
  52. #ifdef ISC_PLATFORM_USETHREADS
  53.         /*
  54.          * xchg should automatically lock memory, but we add it
  55.          * explicitly just in case (it at least doesn't harm)
  56.          */
  57.         "lock;"        
  58. #endif
  59.  
  60.         "xchgl %1, %0"
  61.         :
  62.         : "r"(val), "m"(*p)
  63.         : "memory");
  64. }
  65.  
  66. /*
  67.  * This routine atomically replaces the value in 'p' with 'val', if the
  68.  * original value is equal to 'cmpval'.  The original value is returned in any
  69.  * case.
  70.  */
  71. static inline isc_int32_t
  72. isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
  73.     __asm__ volatile(
  74. #ifdef ISC_PLATFORM_USETHREADS
  75.         "lock;"
  76. #endif
  77.         "cmpxchgl %1, %2"
  78.         : "=a"(cmpval)
  79.         : "r"(val), "m"(*p), "a"(cmpval)
  80.         : "memory");
  81.  
  82.     return (cmpval);
  83. }
  84.  
  85. #elif defined(ISC_PLATFORM_USESTDASM)
  86. /*
  87.  * The followings are "generic" assembly code which implements the same
  88.  * functionality in case the gcc extension cannot be used.  It should be
  89.  * better to avoid inlining below, since we directly refer to specific
  90.  * positions of the stack frame, which would not actually point to the
  91.  * intended address in the embedded mnemonic.
  92.  */
  93. #include <isc/util.h>        /* for 'UNUSED' macro */
  94.  
  95. static isc_int32_t
  96. isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
  97.     UNUSED(p);
  98.     UNUSED(val);
  99.  
  100.     __asm (
  101.         "movl 8(%ebp), %ecx\n"
  102.         "movl 12(%ebp), %edx\n"
  103. #ifdef ISC_PLATFORM_USETHREADS
  104.         "lock;"
  105. #endif
  106.         "xadd %edx, (%ecx)\n"
  107.  
  108.         /*
  109.          * set the return value directly in the register so that we
  110.          * can avoid guessing the correct position in the stack for a
  111.          * local variable.
  112.          */
  113.         "movl %edx, %eax"
  114.         );
  115. }
  116.  
  117. static void
  118. isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
  119.     UNUSED(p);
  120.     UNUSED(val);
  121.  
  122.     __asm (
  123.         "movl 8(%ebp), %ecx\n"
  124.         "movl 12(%ebp), %edx\n"
  125. #ifdef ISC_PLATFORM_USETHREADS
  126.         "lock;"
  127. #endif
  128.         "xchgl (%ecx), %edx\n"
  129.         );
  130. }
  131.  
  132. static isc_int32_t
  133. isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
  134.     UNUSED(p);
  135.     UNUSED(cmpval);
  136.     UNUSED(val);
  137.  
  138.     __asm (
  139.         "movl 8(%ebp), %ecx\n"
  140.         "movl 12(%ebp), %eax\n"    /* must be %eax for cmpxchgl */
  141.         "movl 16(%ebp), %edx\n"
  142. #ifdef ISC_PLATFORM_USETHREADS
  143.         "lock;"
  144. #endif
  145.  
  146.         /*
  147.          * If (%ecx) == %eax then (%ecx) := %edx.
  148.          % %eax is set to old (%ecx), which will be the return value.
  149.          */
  150.         "cmpxchgl %edx, (%ecx)"
  151.         );
  152. }
  153. #else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
  154.  
  155. #error "unsupported compiler.  disable atomic ops by --disable-atomic"
  156.  
  157. #endif
  158. #endif /* ISC_ATOMIC_H */
  159.