Below is a patch for "src/libexec/rtld-elf" which should fix the
assert failures in wine.  I'd appreciate hearing from anybody who
tests this with multithreaded packages such as wine, JDK, Mozilla,
and linuxthreads.

Just a reminder -- be extra careful when messing with the dynamic
linker.  It's easy to paint yourself into a corner if it's broken
badly.  Make a backup copy of your current working dynamic linker
(/usr/libexec/ld-elf.so.1) before installing the experimental version.
Then if things fall apart you can recover with something like this:

    cd /usr/libexec
    chflags 0 ld-elf.so.1*
    mv ld-elf.so.1.good ld-elf.so.1

Thanks in advance for any testing you folks can make time to do.

John

Index: Makefile
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/Makefile,v
retrieving revision 1.10
diff -u -r1.10 Makefile
--- Makefile    2000/01/29 03:16:54     1.10
+++ Makefile    2000/03/01 02:39:13
@@ -3,7 +3,7 @@
 #
 MAINTAINER=    jdp
 PROG=          ld-elf.so.1
-SRCS=          rtld_start.S rtld.c lockdflt.c map_object.c malloc.c \
+SRCS=          rtld_start.S rtld.c map_object.c malloc.c \
                xmalloc.c debug.c reloc.c
 MAN1=          rtld.1
 CFLAGS+=       -Wall -DFREEBSD_ELF -I${.CURDIR}/${MACHINE_ARCH} -I${.CURDIR}
Index: lockdflt.c
===================================================================
RCS file: lockdflt.c
diff -N lockdflt.c
--- /tmp/cvscXuMc22613  Sun Mar  5 17:48:37 2000
+++ /dev/null   Sun Mar  5 02:02:18 2000
@@ -1,89 +0,0 @@
-/*-
- * Copyright 1999, 2000 John D. Polstra.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: src/libexec/rtld-elf/lockdflt.c,v 1.4 2000/01/25 01:32:56 jdp Exp $
- */
-
-/*
- * Default thread locking implementation for the dynamic linker.  It
- * is used until the client registers a different implementation with
- * dllockinit().  The default implementation does mutual exclusion by
- * blocking almost all signals.  This is based on the observation that
- * most userland thread packages use signals to support preemption.
- */
-
-#include <dlfcn.h>
-#include <signal.h>
-#include <stdlib.h>
-
-#include "debug.h"
-#include "rtld.h"
-
-typedef struct Struct_LockDflt {
-    sigset_t lock_mask;
-    sigset_t old_mask;
-    int depth;
-} LockDflt;
-
-void
-lockdflt_acquire(void *lock)
-{
-    LockDflt *l = (LockDflt *)lock;
-    sigprocmask(SIG_BLOCK, &l->lock_mask, &l->old_mask);
-    assert(l->depth == 0);
-    l->depth++;
-}
-
-void *
-lockdflt_create(void *context)
-{
-    LockDflt *l;
-
-    l = NEW(LockDflt);
-    l->depth = 0;
-    sigfillset(&l->lock_mask);
-    sigdelset(&l->lock_mask, SIGTRAP);
-    sigdelset(&l->lock_mask, SIGABRT);
-    sigdelset(&l->lock_mask, SIGBUS);
-    sigdelset(&l->lock_mask, SIGSEGV);
-    sigdelset(&l->lock_mask, SIGKILL);
-    sigdelset(&l->lock_mask, SIGSTOP);
-    return l;
-}
-
-void
-lockdflt_destroy(void *lock)
-{
-    LockDflt *l = (LockDflt *)lock;
-    free(l);
-}
-
-void
-lockdflt_release(void *lock)
-{
-    LockDflt *l = (LockDflt *)lock;
-    assert(l->depth == 1);
-    l->depth--;
-    sigprocmask(SIG_SETMASK, &l->old_mask, NULL);
-}
Index: rtld.c
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.43
diff -u -r1.43 rtld.c
--- rtld.c      2000/01/29 01:26:59     1.43
+++ rtld.c      2000/03/06 01:44:11
@@ -61,6 +61,9 @@
 typedef struct Struct_LockInfo {
     void *context;             /* Client context for creating locks */
     void *thelock;             /* The one big lock */
+    /* Debugging aids. */
+    volatile int rcount;       /* Number of readers holding lock */
+    volatile int wcount;       /* Number of writers holding lock */
     /* Methods */
     void (*rlock_acquire)(void *lock);
     void (*wlock_acquire)(void *lock);
@@ -70,6 +73,16 @@
 } LockInfo;
 
 /*
+ * This structure provides a reentrant way to keep a list of objects and
+ * check which ones have already been processed in some way.
+ */
+typedef struct Struct_DoneList {
+    Obj_Entry **objs;                  /* Array of object pointers */
+    unsigned int num_alloc;            /* Allocated size of the array */
+    unsigned int num_used;             /* Number of array slots used */
+} DoneList;
+
+/*
  * Function declarations.
  */
 static const char *basename(const char *);
@@ -77,6 +90,7 @@
 static void digest_dynamic(Obj_Entry *);
 static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
 static Obj_Entry *dlcheck(void *);
+static bool donelist_check(DoneList *, Obj_Entry *);
 static char *find_library(const char *, const Obj_Entry *);
 static void funclist_call(Funclist *);
 static void funclist_clear(Funclist *);
@@ -85,7 +99,7 @@
 static void funclist_push_tail(Funclist *, InitFunc);
 static const char *gethints(void);
 static void init_dag(Obj_Entry *);
-static void init_dag1(Obj_Entry *root, Obj_Entry *obj);
+static void init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *);
 static void init_rtld(caddr_t);
 static bool is_exported(const Elf_Sym *);
 static void linkmap_add(Obj_Entry *);
@@ -93,6 +107,7 @@
 static int load_needed_objects(Obj_Entry *);
 static int load_preload_objects(void);
 static Obj_Entry *load_object(char *);
+static void lock_check(void);
 static void lock_nop(void *);
 static Obj_Entry *obj_from_addr(const void *);
 static void objlist_add(Objlist *, Obj_Entry *);
@@ -104,7 +119,7 @@
 static char *search_library_path(const char *, const char *);
 static void set_program_var(const char *, const void *);
 static const Elf_Sym *symlook_list(const char *, unsigned long,
-  Objlist *, const Obj_Entry **, bool in_plt);
+  Objlist *, const Obj_Entry **, bool in_plt, DoneList *);
 static void trace_loaded_objects(Obj_Entry *obj);
 static void unload_object(Obj_Entry *);
 static void unref_dag(Obj_Entry *);
@@ -128,7 +143,7 @@
 static Obj_Entry **obj_tail;   /* Link field of last object in list */
 static Obj_Entry *obj_main;    /* The main program shared object */
 static Obj_Entry obj_rtld;     /* The dynamic linker shared object */
-static unsigned long curmark;  /* Current mark value */
+static unsigned int obj_count; /* Number of objects in obj_list */
 
 static Objlist list_global =   /* Objects dlopened with RTLD_GLOBAL */
   STAILQ_HEAD_INITIALIZER(list_global);
@@ -167,21 +182,44 @@
 char *__progname;
 char **environ;
 
+/*
+ * Fill in a DoneList with an allocation large enough to hold all of
+ * the currently-loaded objects.  Keep this as a macro since it calls
+ * alloca and we want that to occur within the scope of the caller.
+ */
+#define donelist_init(dlp)                                     \
+    ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]),  \
+    assert((dlp)->objs != NULL),                               \
+    (dlp)->num_alloc = obj_count,                              \
+    (dlp)->num_used = 0)
+
 static __inline void
 rlock_acquire(void)
 {
     lockinfo.rlock_acquire(lockinfo.thelock);
+    atomic_incr_int(&lockinfo.rcount);
+    lock_check();
 }
 
 static __inline void
 wlock_acquire(void)
 {
     lockinfo.wlock_acquire(lockinfo.thelock);
+    atomic_incr_int(&lockinfo.wcount);
+    lock_check();
+}
+
+static __inline void
+rlock_release(void)
+{
+    atomic_decr_int(&lockinfo.rcount);
+    lockinfo.lock_release(lockinfo.thelock);
 }
 
 static __inline void
-lock_release(void)
+wlock_release(void)
 {
+    atomic_decr_int(&lockinfo.wcount);
     lockinfo.lock_release(lockinfo.thelock);
 }
 
@@ -316,6 +354,7 @@
     /* Link the main program into the list of objects. */
     *obj_tail = obj_main;
     obj_tail = &obj_main->next;
+    obj_count++;
     obj_main->refcount++;
 
     /* Initialize a fake symbol for resolving undefined weak references. */
@@ -366,7 +405,7 @@
     funclist_call(&initlist);
     wlock_acquire();
     funclist_clear(&initlist);
-    lock_release();
+    wlock_release();
 
     dbg("transferring control to program entry point = %p", obj_main->entry);
 
@@ -385,7 +424,7 @@
     Elf_Addr *where;
     Elf_Addr target;
 
-    wlock_acquire();
+    rlock_acquire();
     if (obj->pltrel)
        rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff);
     else
@@ -403,7 +442,7 @@
       (void *)target, basename(defobj->path));
 
     reloc_jmpslot(where, target);
-    lock_release();
+    rlock_release();
     return target;
 }
 
@@ -671,6 +710,28 @@
 }
 
 /*
+ * If the given object is already in the donelist, return true.  Otherwise
+ * add the object to the list and return false.
+ */
+static bool
+donelist_check(DoneList *dlp, Obj_Entry *obj)
+{
+    unsigned int i;
+
+    for (i = 0;  i < dlp->num_used;  i++)
+       if (dlp->objs[i] == obj)
+           return true;
+    /*
+     * Our donelist allocation should always be sufficient.  But if a
+     * threads package hasn't set up its locking properly, more shared
+     * objects could have been loaded since we allocated the list.
+     */
+    if (dlp->num_used < dlp->num_alloc)
+       dlp->objs[dlp->num_used++] = obj;
+    return false;
+}
+
+/*
  * Hash function for symbol table lookup.  Don't even think about changing
  * this.  It is specified by the System V ABI.
  */
@@ -741,6 +802,7 @@
 find_symdef(unsigned long symnum, Obj_Entry *refobj,
     const Obj_Entry **defobj_out, bool in_plt)
 {
+    DoneList donelist;
     const Elf_Sym *ref;
     const Elf_Sym *def;
     const Elf_Sym *symp;
@@ -755,11 +817,11 @@
     hash = elf_hash(name);
     def = NULL;
     defobj = NULL;
-    curmark++;
+    donelist_init(&donelist);
 
-    if (refobj->symbolic) {    /* Look first in the referencing object */
+    /* Look first in the referencing object if linked symbolically. */
+    if (refobj->symbolic && !donelist_check(&donelist, refobj)) {
        symp = symlook_obj(name, hash, refobj, in_plt);
-       refobj->mark = curmark;
        if (symp != NULL) {
            def = symp;
            defobj = refobj;
@@ -768,7 +830,7 @@
 
     /* Search all objects loaded at program start up. */
     if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
-       symp = symlook_list(name, hash, &list_main, &obj, in_plt);
+       symp = symlook_list(name, hash, &list_main, &obj, in_plt, &donelist);
        if (symp != NULL &&
          (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
            def = symp;
@@ -780,7 +842,8 @@
     STAILQ_FOREACH(elm, &refobj->dldags, link) {
        if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
            break;
-       symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt);
+       symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt,
+         &donelist);
        if (symp != NULL &&
          (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
            def = symp;
@@ -790,7 +853,7 @@
 
     /* Search all RTLD_GLOBAL objects. */
     if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
-       symp = symlook_list(name, hash, &list_global, &obj, in_plt);
+       symp = symlook_list(name, hash, &list_global, &obj, in_plt, &donelist);
        if (symp != NULL &&
          (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
            def = symp;
@@ -919,23 +982,24 @@
 static void
 init_dag(Obj_Entry *root)
 {
-    curmark++;
-    init_dag1(root, root);
+    DoneList donelist;
+
+    donelist_init(&donelist);
+    init_dag1(root, root, &donelist);
 }
 
 static void
-init_dag1(Obj_Entry *root, Obj_Entry *obj)
+init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp)
 {
     const Needed_Entry *needed;
 
-    if (obj->mark == curmark)
+    if (donelist_check(dlp, obj))
        return;
-    obj->mark = curmark;
     objlist_add(&obj->dldags, root);
     objlist_add(&root->dagmembers, obj);
     for (needed = obj->needed;  needed != NULL;  needed = needed->next)
        if (needed->obj != NULL)
-           init_dag1(root, needed->obj);
+           init_dag1(root, needed->obj, dlp);
 }
 
 /*
@@ -971,6 +1035,7 @@
         */
        obj_list = &obj_rtld;
        obj_tail = &obj_rtld.next;
+       obj_count = 1;
 
        relocate_objects(&obj_rtld, true);
     }
@@ -978,6 +1043,7 @@
     /* Make the object list empty again. */
     obj_list = NULL;
     obj_tail = &obj_list;
+    obj_count = 0;
 
     /* Replace the path with a dynamically allocated copy. */
     obj_rtld.path = xstrdup(obj_rtld.path);
@@ -1118,6 +1184,7 @@
 
        *obj_tail = obj;
        obj_tail = &obj->next;
+       obj_count++;
        linkmap_add(obj);       /* for GDB */
 
        dbg("  %p .. %p: %s", obj->mapbase,
@@ -1131,6 +1198,26 @@
     return obj;
 }
 
+/*
+ * Check for locking violations and die if one is found.
+ */
+static void
+lock_check(void)
+{
+    int rcount, wcount;
+
+    rcount = lockinfo.rcount;
+    wcount = lockinfo.wcount;
+    assert(rcount >= 0);
+    assert(wcount >= 0);
+    if (wcount > 1 || (wcount != 0 && rcount != 0)) {
+       _rtld_error("Application locking error: %d readers and %d writers"
+         " in dynamic linker.  See DLLOCKINIT(3) in manual pages.",
+         rcount, wcount);
+       die();
+    }
+}
+
 static void
 lock_nop(void *lock)
 {
@@ -1317,7 +1404,7 @@
     wlock_acquire();
     root = dlcheck(handle);
     if (root == NULL) {
-       lock_release();
+       wlock_release();
        return -1;
     }
 
@@ -1336,7 +1423,7 @@
            if (obj->refcount == 0 && obj->fini != NULL)
                funclist_push_tail(&finilist, obj->fini);
 
-       lock_release();
+       wlock_release();
        funclist_call(&finilist);
        wlock_acquire();
        funclist_clear(&finilist);
@@ -1346,7 +1433,7 @@
        unload_object(root);
        GDB_STATE(RT_CONSISTENT);
     }
-    lock_release();
+    wlock_release();
     return 0;
 }
 
@@ -1373,10 +1460,8 @@
     if (lock_create == NULL) {
        is_dflt = true;
        context = NULL;
-       lock_create = lockdflt_create;
-       rlock_acquire = wlock_acquire = lockdflt_acquire;
-       lock_release = lockdflt_release;
-       lock_destroy = lockdflt_destroy;
+       rlock_acquire = wlock_acquire = lock_release = lock_nop;
+       lock_destroy = NULL;
        context_destroy = NULL;
     }
 
@@ -1394,17 +1479,15 @@
     /*
      * Make sure the shared objects containing the locking methods are
      * fully bound, to avoid infinite recursion when they are called
-     * from the lazy binding code.
+     * from the lazy binding code.  Then allocate the lock we will use.
      */
     if (!is_dflt) {
        prebind((void *)rlock_acquire);
        prebind((void *)wlock_acquire);
        prebind((void *)lock_release);
+       lockinfo.thelock = lock_create(lockinfo.context);
     }
 
-    /* Allocate our lock. */
-    lockinfo.thelock = lock_create(lockinfo.context);
-
     /* Record the new method information. */
     lockinfo.context = context;
     lockinfo.rlock_acquire = rlock_acquire;
@@ -1482,11 +1565,11 @@
     GDB_STATE(RT_CONSISTENT);
 
     /* Call the init functions with no locks held. */
-    lock_release();
+    wlock_release();
     funclist_call(&initlist);
     wlock_acquire();
     funclist_clear(&initlist);
-    lock_release();
+    wlock_release();
     return obj;
 }
 
@@ -1502,14 +1585,14 @@
     def = NULL;
     defobj = NULL;
 
-    wlock_acquire();
+    rlock_acquire();
     if (handle == NULL || handle == RTLD_NEXT) {
        void *retaddr;
 
        retaddr = __builtin_return_address(0);  /* __GNUC__ only */
        if ((obj = obj_from_addr(retaddr)) == NULL) {
            _rtld_error("Cannot determine caller's shared object");
-           lock_release();
+           rlock_release();
            return NULL;
        }
        if (handle == NULL) {   /* Just the caller's shared object. */
@@ -1525,14 +1608,17 @@
        }
     } else {
        if ((obj = dlcheck(handle)) == NULL) {
-           lock_release();
+           rlock_release();
            return NULL;
        }
 
        if (obj->mainprog) {
+           DoneList donelist;
+
            /* Search main program and all libraries loaded by it. */
-           curmark++;
-           def = symlook_list(name, hash, &list_main, &defobj, true);
+           donelist_init(&donelist);
+           def = symlook_list(name, hash, &list_main, &defobj, true,
+             &donelist);
        } else {
            /*
             * XXX - This isn't correct.  The search should include the whole
@@ -1544,12 +1630,12 @@
     }
 
     if (def != NULL) {
-       lock_release();
+       rlock_release();
        return defobj->relocbase + def->st_value;
     }
 
     _rtld_error("Undefined symbol \"%s\"", name);
-    lock_release();
+    rlock_release();
     return NULL;
 }
 
@@ -1561,11 +1647,11 @@
     void *symbol_addr;
     unsigned long symoffset;
     
-    wlock_acquire();
+    rlock_acquire();
     obj = obj_from_addr(addr);
     if (obj == NULL) {
         _rtld_error("No shared object contains address");
-       lock_release();
+       rlock_release();
         return 0;
     }
     info->dli_fname = obj->path;
@@ -1604,7 +1690,7 @@
         if (info->dli_saddr == addr)
             break;
     }
-    lock_release();
+    rlock_release();
     return 1;
 }
 
@@ -1695,7 +1781,7 @@
 
 static const Elf_Sym *
 symlook_list(const char *name, unsigned long hash, Objlist *objlist,
-  const Obj_Entry **defobj_out, bool in_plt)
+  const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp)
 {
     const Elf_Sym *symp;
     const Elf_Sym *def;
@@ -1705,9 +1791,8 @@
     def = NULL;
     defobj = NULL;
     STAILQ_FOREACH(elm, objlist, link) {
-       if (elm->obj->mark == curmark)
+       if (donelist_check(dlp, elm->obj))
            continue;
-       elm->obj->mark = curmark;
        if ((symp = symlook_obj(name, hash, elm->obj, in_plt)) != NULL) {
            if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) {
                def = symp;
@@ -1877,6 +1962,7 @@
            munmap(obj->mapbase, obj->mapsize);
            linkmap_delete(obj);
            *linkp = obj->next;
+           obj_count--;
            obj_free(obj);
        } else
            linkp = &obj->next;
Index: rtld.h
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/rtld.h,v
retrieving revision 1.15
diff -u -r1.15 rtld.h
--- rtld.h      2000/01/29 01:26:59     1.15
+++ rtld.h      2000/03/01 02:39:27
@@ -149,7 +149,6 @@
     Objlist dagmembers;                /* DAG has these members (%) */
     dev_t dev;                 /* Object's filesystem's device */
     ino_t ino;                 /* Object's inode number */
-    unsigned long mark;                /* Set to "curmark" to avoid repeat visits */
 } Obj_Entry;
 
 #define RTLD_MAGIC     0xd550b87a
@@ -170,10 +169,6 @@
 const Elf_Sym *find_symdef(unsigned long, Obj_Entry *, const Obj_Entry **,
   bool);
 void init_pltgot(Obj_Entry *);
-void lockdflt_acquire(void *);
-void *lockdflt_create(void *);
-void lockdflt_destroy(void *);
-void lockdflt_release(void *);
 void obj_free(Obj_Entry *);
 Obj_Entry *obj_new(void);
 int reloc_non_plt(Obj_Entry *, Obj_Entry *);
Index: alpha/rtld_machdep.h
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/alpha/rtld_machdep.h,v
retrieving revision 1.3
diff -u -r1.3 rtld_machdep.h
--- alpha/rtld_machdep.h        1999/08/28 00:10:13     1.3
+++ alpha/rtld_machdep.h        2000/03/06 01:37:22
@@ -34,4 +34,8 @@
 
 void reloc_jmpslot(Elf_Addr *, Elf_Addr);
 
+/* Atomically increment / decrement an int. */
+void atomic_incr_int(volatile int *);
+void atomic_decr_int(volatile int *);
+
 #endif
Index: alpha/rtld_start.S
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/alpha/rtld_start.S,v
retrieving revision 1.3
diff -u -r1.3 rtld_start.S
--- alpha/rtld_start.S  1999/08/28 00:10:13     1.3
+++ alpha/rtld_start.S  2000/03/06 01:37:58
@@ -166,6 +166,24 @@
        jmp     $31, ($27)
        .end _rtld_bind_start
  
+/* Atomically increment an int. */
+LEAF(atomic_incr_int, 1)
+0:     ldl_l   t0, 0(a0)
+       addq    t0, 1, t0
+       stl_c   t0, 0(a0)
+       beq     t0, 1f
+       mb
+       RET
+1:     br      0b
+       END(atomic_incr_int)
 
-
-
+/* Atomically decrement an int. */
+LEAF(atomic_decr_int, 1)
+0:     ldl_l   t0, 0(a0)
+       subq    t0, 1, t0
+       stl_c   t0, 0(a0)
+       beq     t0, 1f
+       mb
+       RET
+1:     br      0b
+       END(atomic_decr_int)
Index: i386/rtld_machdep.h
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/i386/rtld_machdep.h,v
retrieving revision 1.3
diff -u -r1.3 rtld_machdep.h
--- i386/rtld_machdep.h 1999/08/28 00:10:14     1.3
+++ i386/rtld_machdep.h 2000/03/06 01:40:47
@@ -41,4 +41,18 @@
        (*(Elf_Addr *)(where) = (Elf_Addr)(target));    \
     } while (0)
 
+/* Atomically increment / decrement an int. */
+
+static __inline void
+atomic_incr_int(volatile int *p)
+{
+    __asm __volatile("lock; incl %0" : "=m" (*p) : "0" (*p));
+}
+
+static __inline void
+atomic_decr_int(volatile int *p)
+{
+    __asm __volatile("lock; decl %0" : "=m" (*p) : "0" (*p));
+}
+
 #endif


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to